aboutsummaryrefslogtreecommitdiff
path: root/jabberd
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-06-04 12:35:54 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-06-04 12:35:54 +0000
commite7ffd40909f60b2230879e2767ad0a057198eb9f (patch)
tree4572199ebe2170e6abc97b77d4e1c4e496009079 /jabberd
parentc4687307a4e3f4d08d5da97c0537fe0ce95960d1 (diff)
downloadgsc-e7ffd40909f60b2230879e2767ad0a057198eb9f.tar.gz
gsc-e7ffd40909f60b2230879e2767ad0a057198eb9f.tar.bz2
Implement long options, running instance control and component dependency checking
git-svn-id: file:///svnroot/gsc/trunk@254 d2de0444-eb31-0410-8365-af798a554d48
Diffstat (limited to 'jabberd')
-rw-r--r--jabberd/Makefile.am3
-rw-r--r--jabberd/jabberd.h4
-rw-r--r--jabberd/main.c412
-rw-r--r--jabberd/progman.c228
4 files changed, 568 insertions, 79 deletions
diff --git a/jabberd/Makefile.am b/jabberd/Makefile.am
index b5667ba..8fe9158 100644
--- a/jabberd/Makefile.am
+++ b/jabberd/Makefile.am
@@ -1,3 +1,4 @@
bin_PROGRAMS = jabberd
jabberd_SOURCES = main.c progman.c jabber.h argcv.c
-AM_CPPFLAGS=-DSYSCONFDIR=\"$(sysconfdir)\" \ No newline at end of file
+AM_CPPFLAGS=-DSYSCONFDIR=\"$(sysconfdir)\"\
+ -DSTATEDIR=\"$(localstatedir)/jabberd\"
diff --git a/jabberd/jabberd.h b/jabberd/jabberd.h
index 6c9f480..336a023 100644
--- a/jabberd/jabberd.h
+++ b/jabberd/jabberd.h
@@ -48,7 +48,7 @@
#define SLEEPTIME 5*60
#define MAXSPAWN 10
-void register_prog (char *tag, char **argv, int retr[2]);
+void register_trasport (char *tag, char **argv, int retr[2], char **depv);
void register_jabber_process (char *cmd, char *cfg);
void logmsg(int prio, char *fmt, ...);
void signal_setup (RETSIGTYPE (*sf)(int));
@@ -59,6 +59,8 @@ void progman_start (void);
void progman_stop (void);
void progman_cleanup (int);
void progman_wake_disabled (void);
+void progman_stop_component (const char *);
+void progman_dump_stats (const char *);
extern int debug_level;
extern char *syslog_tag;
diff --git a/jabberd/main.c b/jabberd/main.c
index e2a00ac..476abd8 100644
--- a/jabberd/main.c
+++ b/jabberd/main.c
@@ -28,7 +28,9 @@ char *syslog_tag = "jabberd";
int log_facility = LOG_LOCAL7;
int x_argc;
char **x_argv;
-char *pidfile;
+char *pidfile = STATEDIR "/jabberd.pid";
+char *ctlfile = STATEDIR "/.jabberd.ctl";
+char *statfile = STATEDIR "/.jabberd.stat";
unsigned long shutdown_timeout = 5;
mode_t jabberd_umask = 037;
@@ -131,17 +133,27 @@ version ()
void
usage ()
{
- printf ("usage: jabberd [-Dfehv][-c config][-p pidfile]\n");
+ printf ("usage: jabberd [-Dfehv][-c config][-r tag [tag...]]\n");
printf ("jabberd -- A dispatcher program for jabber 2.x\n");
printf ("\n");
- printf ("Options:\n");
- printf (" -c FILE use this configuration file\n");
- printf (" -D increase debugging level\n");
- printf (" -f run in foreground mode (implies -e)\n");
- printf (" -e use standard error for diagnostics output\n");
- printf (" -h display this help list\n");
- printf (" -p FILE write master process ID to FILE\n");
- printf (" -v display program version\n");
+ printf ("General-purpose options:\n");
+ printf (" -c, --config-file=FILE use this configuration file\n");
+ printf (" -D, --debug increase debugging level\n");
+ printf (" -e, --stderr use standard error for diagnostics output\n");
+ printf (" -f, --foreground run in foreground mode (implies -e)\n");
+ printf (" --force start up even if another copy seems to be running\n");
+
+ printf ("\nControlling running instance:\n");
+ printf (" --status display status information\n");
+ printf (" --stop stop the running copy\n");
+ printf (" --reload, --hup reload the running copy\n");
+ printf (" -r, --restart tag [tag...] restart named components\n");
+
+ printf ("\nInformational options:\n");
+ printf (" -h, --help display this help list\n");
+ printf (" -v, --version display program version\n");
+
+
printf ("\n");
printf ("Report bugs to <%s>\n", PACKAGE_BUGREPORT);
}
@@ -356,6 +368,18 @@ cfg_pidfile (struct cfg_file *file, char *kw, char *val, void *unused)
}
void
+cfg_ctlfile (struct cfg_file *file, char *kw, char *val, void *unused)
+{
+ ctlfile = strdup (val);
+}
+
+void
+cfg_statfile (struct cfg_file *file, char *kw, char *val, void *unused)
+{
+ ctlfile = strdup (val);
+}
+
+void
cfg_umask (struct cfg_file *file, char *kw, char *val, void *unused)
{
char *p;
@@ -390,60 +414,76 @@ cfg_prog (struct cfg_file *file, char *kw, char *val, void *unused)
register_jabber_process (prog, val);
}
-struct exec_rec {
+struct transport_rec
+{
char *tag;
char *command;
int facility;
int retr[2];
+ int depc;
+ char **depv;
};
static void
-cfg_exec_command (struct cfg_file *file, char *kw, char *val, void *data)
+cfg_transport_command (struct cfg_file *file, char *kw, char *val, void *data)
{
- struct exec_rec *prec = data;
+ struct transport_rec *prec = data;
prec->command = strdup (val);
}
void
-cfg_exec_facility (struct cfg_file *file, char *kw, char *val, void *data)
+cfg_transport_facility (struct cfg_file *file, char *kw, char *val, void *data)
{
- struct exec_rec *prec = data;
+ struct transport_rec *prec = data;
if (str_to_facility (val, &prec->facility))
logmsg (LOG_ERR, "%s:%u: Unknown facility `%s'",
config_file, file->line, val);
}
void
-cfg_exec_stdout (struct cfg_file *file, char *kw, char *val, void *data)
+cfg_transport_stdout (struct cfg_file *file, char *kw, char *val, void *data)
{
- struct exec_rec *prec = data;
+ struct transport_rec *prec = data;
if (str_to_priority (val, &prec->retr[RETR_OUT]))
logmsg (LOG_ERR, "%s:%u: Unknown priority `%s'",
config_file, file->line, val);
}
void
-cfg_exec_stderr (struct cfg_file *file, char *kw, char *val, void *data)
+cfg_transport_stderr (struct cfg_file *file, char *kw, char *val, void *data)
{
- struct exec_rec *prec = data;
+ struct transport_rec *prec = data;
if (str_to_priority (val, &prec->retr[RETR_ERR]))
logmsg (LOG_ERR, "%s:%u: Unknown priority `%s'",
config_file, file->line, val);
}
void
-cfg_exec (struct cfg_file *file, char *kw, char *val, void *unused)
+cfg_transport_depend (struct cfg_file *file, char *kw, char *val, void *data)
+{
+ struct transport_rec *prec = data;
+ int rc;
+ if (rc = argcv_get (val, NULL, NULL, &prec->depc, &prec->depv))
+ {
+ logmsg (LOG_ERR, "%s:%u: cannot split dependency line: %s",
+ config_file, file->line, strerror (rc));
+ }
+}
+
+void
+cfg_transport (struct cfg_file *file, char *kw, char *val, void *unused)
{
int rc;
int argc;
char **argv;
- struct exec_rec rec;
+ struct transport_rec rec;
static struct kw_handler kwtab[] = {
- { "command", cfg_exec_command },
- { "stdout", cfg_exec_stdout },
- { "stderr", cfg_exec_stderr },
- { "facility", cfg_exec_facility },
+ { "command", cfg_transport_command },
+ { "stdout", cfg_transport_stdout },
+ { "stderr", cfg_transport_stderr },
+ { "facility", cfg_transport_facility },
+ { "depend", cfg_transport_depend },
{ NULL }
};
memset (&rec, 0, sizeof rec);
@@ -459,9 +499,10 @@ cfg_exec (struct cfg_file *file, char *kw, char *val, void *unused)
config_file, file->line, strerror (rc));
return;
}
- register_prog (rec.tag, argv, rec.retr);
+ register_transport (rec.tag, argv, rec.retr, rec.depv);
free (rec.tag);
free (rec.command);
+ argcv_free (rec.depc, rec.depv);
argcv_free (argc, argv);
}
@@ -482,9 +523,12 @@ struct kw_handler kw_handler[] = {
{ "user", cfg_user },
{ "group", cfg_group },
{ "pidfile", cfg_pidfile },
+ { "ctlfile", cfg_ctlfile },
+ { "statfile", cfg_statfile },
{ "umask", cfg_umask },
{ "prog", cfg_prog },
- { "exec", cfg_exec },
+ { "transport", cfg_transport },
+ { "exec", cfg_transport },
{ "shutdown-timeout", cfg_shutdown_timeout },
{ NULL }
};
@@ -516,24 +560,59 @@ parse_config ()
void
pidfile_write ()
{
- if (pidfile)
+ FILE *fp = fopen (pidfile, "w");
+ if (!fp)
+ {
+ logmsg (LOG_CRIT, "cannot open pidfile `%s' for writing: %s",
+ pidfile, strerror (errno));
+ return;
+ }
+ fprintf (fp, "%lu\n", (unsigned long) getpid ());
+ fclose (fp);
+}
+
+pid_t
+pidfile_read (int must_exist)
+{
+ int c;
+ pid_t n = 0;
+ FILE *fp = fopen (pidfile, "r");
+ if (!fp)
{
- FILE *fp = fopen (pidfile, "w");
- if (!fp)
+ if (must_exist && errno != ENOENT)
+ logmsg (LOG_ERR, "cannot open pid file `%s': %s",
+ pidfile,
+ strerror (errno));
+ return -1;
+ }
+
+ while ((c = fgetc (fp)) != EOF)
+ {
+ if (isdigit (c))
+ n = n * 10 + c - '0';
+ else if (c == '\n')
+ break;
+ else
{
- logmsg (LOG_CRIT, "cannot open pidfile `%s' for writing: %s",
- pidfile, strerror (errno));
- return;
+ logmsg (LOG_ERR, "unexpected character %#03o in pidfile `%s'",
+ c, pidfile);
+ return -1;
}
- fprintf (fp, "%lu\n", (unsigned long) getpid ());
- fclose (fp);
}
+ fclose (fp);
+ if (kill (n, 0))
+ {
+ logmsg (LOG_ERR, "Cannot signal master process %lu: %s",
+ (unsigned long) n, strerror (errno));
+ return -1;
+ }
+ return n;
}
void
pidfile_remove ()
{
- if (pidfile && unlink (pidfile))
+ if (unlink (pidfile))
logmsg (LOG_ERR, "cannot remove pidfile `%s': %s",
pidfile, strerror (errno));
}
@@ -547,7 +626,7 @@ switch_to_privs (uid_t uid, gid_t gid)
gid_t *emptygidset;
size_t size = 1, j = 1;
struct group_list *gp;
-
+
if (uid == 0)
{
logmsg(LOG_EMERG, "refusing to run as root");
@@ -688,9 +767,11 @@ priv_setup ()
}
-#define ACTION_CONT 0
-#define ACTION_STOP 1
-#define ACTION_RESTART 2
+#define ACTION_CONT 0
+#define ACTION_STOP 1
+#define ACTION_RESTART 2
+#define ACTION_COMPRELOAD 3
+#define ACTION_DUMPSTATS 4
int action = ACTION_CONT;
int children_cleanup = 0;
@@ -726,6 +807,15 @@ sig_handler(int sig)
case SIGALRM:
got_alarm = 1;
+ break;
+
+ case SIGUSR1:
+ action = ACTION_COMPRELOAD;
+ break;
+
+ case SIGUSR2:
+ action = ACTION_DUMPSTATS;
+ break;
}
signal (sig, sig_handler);
}
@@ -739,6 +829,8 @@ signal_setup (RETSIGTYPE (*sf)(int))
signal (SIGINT, sf);
signal (SIGHUP, sf);
signal (SIGALRM, sf);
+ signal (SIGUSR1, sf);
+ signal (SIGUSR2, sf);
}
void
@@ -748,13 +840,178 @@ syslog_setup ()
}
+
+void
+stop_components ()
+{
+ FILE *fp;
+ size_t size = 0;
+ char *buf = NULL;
+
+ logmsg (LOG_INFO, "stopping components");
+
+ fp = fopen (ctlfile, "r");
+ if (!fp)
+ {
+ logmsg (LOG_ERR, "cannot open control file `%s': %s",
+ ctlfile, strerror (errno));
+ return;
+ }
+ if (unlink (ctlfile))
+ {
+ logmsg (LOG_ERR, "cannot open control file `%s': %s",
+ ctlfile, strerror (errno));
+ fclose (fp);
+ return;
+ }
+
+ while (getline (&buf, &size, fp) > 0)
+ {
+ size_t len = strlen (buf);
+ if (len == 0)
+ continue;
+ if (buf[len-1] == '\n')
+ buf[len-1] = 0;
+ progman_stop_component (buf);
+ }
+
+ free (buf);
+ fclose (fp);
+}
+
+int
+request_restart_components (char **argv)
+{
+ FILE *fp;
+ pid_t pid = pidfile_read (1);
+
+ if (pid == -1)
+ return 1;
+
+ fp = fopen (ctlfile, "w");
+ if (!fp)
+ {
+ logmsg (LOG_ERR, "cannot open control file `%s': %s",
+ ctlfile, strerror (errno));
+ return 1;
+ }
+ for (; *argv; argv++)
+ fprintf (fp, "%s\n", *argv);
+ fclose (fp);
+
+ kill (pid, SIGUSR1);
+ return 0;
+}
+
+
+int
+jabberd_reload ()
+{
+ pid_t pid = pidfile_read (1);
+
+ if (pid == -1)
+ {
+ logmsg (LOG_CRIT, "jabberd is not running");
+ return 1;
+ }
+
+ logmsg (LOG_INFO, "reloading jabberd at PID %lu", (unsigned long) pid);
+ return kill (pid, SIGHUP) ? 2 : 0;
+}
+
+int
+jabberd_status ()
+{
+ FILE *fp;
+ pid_t pid = pidfile_read (0);
+ int i;
+
+ if (pid == -1)
+ {
+ logmsg (LOG_INFO, "jabberd is not running");
+ return 1;
+ }
+
+ if (kill (pid, SIGUSR2))
+ {
+ logmsg (LOG_INFO,
+ "jabberd is not running, but a pidfile is found (pid %lu)\n",
+ (unsigned long) pid);
+ return 1;
+ }
+ logmsg (LOG_INFO, "jabberd is running; PID %lu",
+ (unsigned long) pid);
+
+ for (i = 0; i < access (statfile, R_OK); i++)
+ sleep (1);
+
+ fp = fopen (statfile, "r");
+ if (!fp)
+ logmsg (LOG_ERR, "cannot open statfile `%s': %s",
+ statfile, strerror (errno));
+ else
+ {
+ char c;
+
+ if (unlink (statfile))
+ logmsg (LOG_ERR, "cannot unlink statfile `%s': %s",
+ statfile, strerror (errno));
+ while ((c = fgetc (fp)) != EOF)
+ fputc (c, stdout);
+ fclose (fp);
+ }
+ return 0;
+}
+
+int
+jabberd_stop ()
+{
+ pid_t pid = pidfile_read (1);
+
+ if (pid == -1)
+ {
+ logmsg (LOG_CRIT, "jabberd is not running");
+ return 1;
+ }
+
+ logmsg (LOG_INFO, "stopping jabberd at PID %lu", (unsigned long) pid);
+ return kill (pid, SIGTERM) ? 2 : 0;
+}
+
+
+enum {
+ OPTION_RELOAD = 256,
+ OPTION_STATUS,
+ OPTION_STOP,
+ OPTION_FORCE
+};
+
+struct option options[] = {
+ { "config-file", required_argument, NULL, 'c' },
+ { "debug", no_argument, NULL, 'D' },
+ { "foreground", no_argument, NULL, 'f' },
+ { "stderr", no_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "restart-module", no_argument, NULL, 'r' },
+ { "reload", no_argument, NULL, OPTION_RELOAD },
+ { "hup", no_argument, NULL, OPTION_RELOAD },
+ { "status", no_argument, NULL, OPTION_STATUS },
+ { "stop", no_argument, NULL, OPTION_STOP },
+ { "version", no_argument, NULL, 'v' },
+ { "force", no_argument, NULL, OPTION_FORCE },
+ { NULL }
+};
+
int
main(int argc, char **argv)
{
int c;
-
+ int mode = 0;
+ pid_t pid;
+ int force = 0;
+
progname = argv[0];
- while ((c = getopt(argc, argv, "c:Dfehp:v")) != EOF)
+ while ((c = getopt_long (argc, argv, "c:Dfehrv", options, NULL)) != EOF)
{
switch (c)
{
@@ -777,13 +1034,21 @@ main(int argc, char **argv)
usage ();
exit (0);
- case 'p':
- pidfile = optarg;
- break;
-
case 'v':
version ();
exit (0);
+
+ case 'r':
+ case OPTION_RELOAD:
+ case OPTION_STATUS:
+ case OPTION_STOP:
+ log_to_stderr = 1;
+ mode = c;
+ break;
+
+ case OPTION_FORCE:
+ force = 1;
+ break;
default:
logmsg (LOG_CRIT, "unknown option: %c", c);
@@ -791,7 +1056,7 @@ main(int argc, char **argv)
}
}
- if (argc != optind)
+ if (argc != optind && mode != 'r')
{
logmsg (LOG_CRIT, "extra command line arguments");
exit (1);
@@ -805,16 +1070,51 @@ main(int argc, char **argv)
log_printer = syslog_printer;
}
+ switch (mode)
+ {
+ case 'r':
+ priv_setup ();
+ umask (jabberd_umask);
+ exit (request_restart_components (argv + optind));
+
+ case OPTION_RELOAD:
+ exit (jabberd_reload ());
+
+ case OPTION_STATUS:
+ exit (jabberd_status ());
+
+ case OPTION_STOP:
+ exit (jabberd_stop ());
+
+ default:
+ priv_setup ();
+ umask (jabberd_umask);
+ }
+
+ if (!force)
+ {
+ pid = pidfile_read (0);
+ if (pid != -1)
+ {
+ logmsg (LOG_ALERT,
+ "jabberd seems to be already running at pid %lu",
+ (unsigned long) pid);
+ logmsg (LOG_INFO,
+ "use --status to verify or --force to start up anyway");
+ exit (1);
+ }
+ }
+
if (argv[0][0] == '/')
{
x_argc = argc;
x_argv = argv;
}
else
- logmsg (LOG_NOTICE, "jabberd not started as an absolute pathname; SIGHUP will not work");
+ logmsg (LOG_NOTICE,
+ "jabberd not started as an absolute pathname; "
+ "SIGHUP will not work");
- priv_setup ();
- umask (jabberd_umask);
logmsg (LOG_NOTICE, "jabberd started");
if (!foreground && daemon (0, 0) == -1)
{
@@ -841,6 +1141,18 @@ main(int argc, char **argv)
got_alarm = 0;
progman_wake_disabled ();
}
+ switch (action)
+ {
+ case ACTION_COMPRELOAD:
+ stop_components ();
+ action = ACTION_CONT;
+ break;
+
+ case ACTION_DUMPSTATS:
+ progman_dump_stats (statfile);
+ action = ACTION_CONT;
+ break;
+ }
}
progman_stop ();
diff --git a/jabberd/progman.c b/jabberd/progman.c
index f39dd62..26693e4 100644
--- a/jabberd/progman.c
+++ b/jabberd/progman.c
@@ -20,8 +20,9 @@
#include <sys/stat.h>
#include <fcntl.h>
-#define TYPE_PROG 0
-#define TYPE_RETR 1
+#define TYPE_CORE 0
+#define TYPE_TRANSPORT 1
+#define TYPE_RETR 2
struct prog
{
@@ -29,10 +30,12 @@ struct prog
int type;
pid_t pid; /* PID */
char *tag; /* Entry tag (for diagnostics purposes) */
+ char **depend;
union
{
struct
{
+ int argc;
char **argv; /* Command line arguments */
int retr[2];
time_t timestamp; /* Time of last startup */
@@ -48,6 +51,8 @@ struct prog
};
+#define IS_PROG(p) ((p)->type == TYPE_CORE || (p)->type == TYPE_TRANSPORT)
+
static struct prog *proghead, *progtail;
static size_t prognum;
@@ -92,42 +97,110 @@ register_retr (int type, struct prog *master, pid_t pid)
}
void
-register_prog (char *tag, char **argv, int retr[2])
+register_prog (int type, char *tag, char **argv, int retr[2], char **depv)
{
- struct prog *pp;
+ struct prog *p, *newp;
char *pstr;
int i;
size_t size = 0;
+ int dep_all = 0;
+ int depc = 0;
+
+ if (depv)
+ {
+ if (depv[0] && depv[1] == NULL)
+ {
+ if (strcmp (depv[0], "all") == 0)
+ {
+ dep_all = 1;
+ for (p = proghead; p; p = p->next)
+ if (p->type == TYPE_CORE)
+ {
+ depc++;
+ size += strlen (p->tag) + 1;
+ }
+ }
+ else if (strcmp (depv[0], "none") == 0)
+ depv = NULL;
+ }
+ if (depc == 0)
+ for (depc = 0; depv[depc]; depc++)
+ ;
+ size += sizeof (depv[0]) * (depc + 1);
+ }
+
for (i = 0; argv[i]; i++)
size += strlen (argv[i]);
- size += i + sizeof (argv[0]) * (i + 1) + sizeof (*pp)
+ size += i + sizeof (argv[0]) * (i + 1) + sizeof (*newp)
+ (tag ? (strlen (tag) + 1) : 0);
- pp = emalloc (size);
- memset (pp, 0, sizeof(*pp));
- pp->type = TYPE_PROG;
- pp->pid = 0;
- pp->v.p.argv = (char **) (pp + 1);
- pstr = (char*) (pp->v.p.argv + i + 1);
+ newp = emalloc (size);
+ memset (newp, 0, sizeof(*newp));
+ newp->type = type;
+ newp->pid = 0;
+ newp->v.p.argc = i;
+ newp->v.p.argv = (char **) (newp + 1);
+ pstr = (char*) (newp->v.p.argv + i + 1);
for (i = 0; argv[i]; i++)
{
strcpy (pstr, argv[i]);
- pp->v.p.argv[i] = pstr;
+ newp->v.p.argv[i] = pstr;
pstr += strlen (pstr) + 1;
}
- pp->v.p.argv[i] = NULL;
+ newp->v.p.argv[i] = NULL;
if (tag)
- pp->tag = strcpy (pstr, tag);
+ {
+ newp->tag = strcpy (pstr, tag);
+ pstr += strlen (pstr) + 1;
+ }
else
- pp->tag = pp->v.p.argv[0];
+ newp->tag = newp->v.p.argv[0];
- pp->v.p.retr[0] = retr[0];
- pp->v.p.retr[1] = retr[1];
+ if (depv)
+ {
+ newp->depend = (char**) pstr;
+ pstr = (char*) (newp->depend + depc + 1);
+ if (dep_all)
+ {
+ depc = 0;
+ for (p = proghead; p; p = p->next)
+ if (p->type == TYPE_CORE)
+ {
+ newp->depend[depc++] = pstr;
+ strcpy (pstr, p->tag);
+ pstr += strlen (pstr) + 1;
+ }
+ }
+ else
+ {
+ for (depc = 0; depv[depc]; depc++)
+ {
+ newp->depend[depc] = pstr;
+ strcpy (pstr, p->tag);
+ pstr += strlen (pstr) + 1;
+ }
+ }
+ depv[depc] = NULL;
+ }
+ else
+ newp->depend = NULL;
+
+ newp->v.p.retr[0] = retr[0];
+ newp->v.p.retr[1] = retr[1];
- link_prog (pp, 0);
+ link_prog (newp, 0);
+}
+
+void
+register_transport (char *tag, char **argv, int retr[2], char **depv)
+{
+ static char *std_dep[] = { "all", NULL };
+ if (!depv)
+ depv = std_dep;
+ register_prog (TYPE_TRANSPORT, tag, argv, retr, depv);
}
void
@@ -147,7 +220,7 @@ register_jabber_process (char *cmd, char *cfg)
argv[argc++] = "-D";
argv[argc] = NULL;
- register_prog (NULL, argv, retr);
+ register_prog (TYPE_CORE, NULL, argv, retr, NULL);
}
static struct prog *
@@ -316,7 +389,7 @@ progman_start ()
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
- if (prog->type == TYPE_PROG)
+ if (IS_PROG (prog))
prog_start (prog);
}
@@ -326,7 +399,7 @@ progman_wake_disabled ()
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
- if (prog->type == TYPE_PROG && prog->v.p.disabled)
+ if (IS_PROG (prog) && prog->v.p.disabled)
{
prog->v.p.disabled = 0;
prog->v.p.count = 0;
@@ -336,17 +409,23 @@ progman_wake_disabled ()
}
static void
-prog_stop_recursive (struct prog *prog, int sig)
+prog_stop (struct prog *prog, int sig)
{
- if (!prog)
- return;
- prog_stop_recursive (prog->next, sig);
if (prog->pid > 0)
{
logmsg (LOG_DEBUG, "Stopping %s",
prog->tag, (unsigned long) prog->pid);
kill (prog->pid, sig);
}
+}
+
+static void
+prog_stop_recursive (struct prog *prog, int sig)
+{
+ if (!prog)
+ return;
+ prog_stop_recursive (prog->next, sig);
+ prog_stop (prog, sig);
}
void
@@ -412,6 +491,21 @@ print_status (char *tag, pid_t pid, int status, int expect_term)
}
void
+prog_stop_dependent (struct prog *prog)
+{
+ struct prog *p;
+
+ for (p = proghead; p; p = p->next)
+ if (p->depend)
+ {
+ int i;
+ for (i = 0; p->depend[i]; i++)
+ if (strcmp (prog->tag, p->depend[i]) == 0)
+ prog_stop (p, SIGTERM);
+ }
+}
+
+void
progman_cleanup (int expect_term)
{
pid_t pid;
@@ -427,7 +521,87 @@ progman_cleanup (int expect_term)
}
print_status (prog->tag, prog->pid, status, expect_term);
prog->pid = 0;
- if (prog->type == TYPE_PROG && !expect_term)
- prog_start (prog);
+ if (IS_PROG (prog))
+ {
+ prog_stop_dependent (prog);
+ if (!expect_term)
+ prog_start (prog);
+ }
+ }
+}
+
+void
+progman_stop_component (const char *name)
+{
+ struct prog *prog;
+
+ logmsg (LOG_INFO, "stopping component `%s'", name);
+ for (prog = proghead; prog; prog = prog->next)
+ if (IS_PROG (prog) && strcmp (prog->tag, name) == 0)
+ {
+ if (prog->v.p.disabled)
+ logmsg (LOG_INFO, "stopping component `%s': component not started",
+ name);
+ else
+ prog_stop (prog, SIGTERM);
+ }
+}
+
+void
+progman_dump_stats (const char *filename)
+{
+ FILE *fp;
+ struct prog *prog;
+ char *s;
+ int rc;
+
+ logmsg (LOG_INFO, "dumping statistics to `%s'", filename);
+ fp = fopen (filename, "w");
+ if (!fp)
+ {
+ logmsg (LOG_ERR, "cannot open file `%s' for writing: %s",
+ filename, strerror (errno));
+ return;
+ }
+
+ for (prog = proghead; prog; prog = prog->next)
+ {
+ switch (prog->type)
+ {
+ case TYPE_CORE:
+ case TYPE_TRANSPORT:
+ fprintf (fp, "%s %s ",
+ prog->type == TYPE_CORE ? "core" : "transport",
+ prog->tag);
+ if (prog->pid)
+ fprintf (fp, "%lu", (unsigned long) prog->pid);
+ else if (prog->v.p.disabled)
+ {
+ char buf[48];
+
+ strftime (buf, sizeof buf, "%c",
+ localtime (&prog->v.p.timestamp));
+ fprintf (fp, "[disabled; scheduled for %s]", buf);
+ }
+ else
+ fprintf (fp, "[not running]");
+ if (rc = argcv_string (prog->v.p.argc, prog->v.p.argv, &s))
+ {
+ logmsg (LOG_ERR, "cannot convert argument list: %s",
+ strerror (rc));
+ }
+ else
+ {
+ fprintf (fp, " %s", s);
+ free (s);
+ }
+ fputc ('\n', fp);
+ break;
+
+ case TYPE_RETR:
+ fprintf (fp, "retranslator %s %lu\n", prog->tag,
+ (unsigned long) prog->pid);
+ }
}
+ fclose (fp);
}

Return to:

Send suggestions and report system problems to the System administrator.