summaryrefslogtreecommitdiffabout
path: root/jabberd/progman.c
Side-by-side diff
Diffstat (limited to 'jabberd/progman.c') (more/less context) (ignore whitespace changes)
-rw-r--r--jabberd/progman.c647
1 files changed, 0 insertions, 647 deletions
diff --git a/jabberd/progman.c b/jabberd/progman.c
deleted file mode 100644
index 3dfe3ba..0000000
--- a/jabberd/progman.c
+++ b/dev/null
@@ -1,647 +0,0 @@
-/* jabberd - a dispatcher program for jabber 2.x
- Copyright (C) 2007 Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "jabberd.h"
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define TYPE_CORE 0
-#define TYPE_TRANSPORT 1
-#define TYPE_RETR 2
-
-struct prog
-{
- struct prog *next; /* Next program in the list */
- 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];
- char *pidfile; /* Pidfile location */
- time_t timestamp; /* Time of last startup */
- size_t count; /* Number of failed starts since timestamp */
- int disabled; /* 1 if this entry is disabled */
- } p;
-
- struct
- {
- struct prog *master;
- } r;
- } v;
-};
-
-
-#define IS_PROG(p) ((p)->type == TYPE_CORE || (p)->type == TYPE_TRANSPORT)
-
-static struct prog *proghead, *progtail;
-static size_t prognum;
-
-static void prog_stop (struct prog *prog, int sig);
-
-void
-link_prog (struct prog *pp, int prepend)
-{
- if (prepend)
- {
- pp->next = proghead;
- proghead = pp;
- if (!progtail)
- progtail = pp;
- }
- else
- {
- pp->next = NULL;
- if (progtail)
- progtail->next = pp;
- else
- proghead = pp;
- progtail = pp;
- }
-}
-
-void
-register_retr (int type, struct prog *master, pid_t pid)
-{
- struct prog *pp;
- static char *retrstr[2] = { "stdout", "stderr" };
- size_t taglen = strlen (master->tag) + 1 + strlen (retrstr[type]);
- char *tag = emalloc (taglen + 1);
-
- strcpy (tag, master->tag);
- strcat (tag, "/");
- strcat (tag, retrstr[type]);
-
- for (pp = proghead; pp; pp = pp->next)
- if (pp->type == TYPE_RETR && pp->v.r.master == master
- && strcmp (pp->tag, tag) == 0)
- {
- free (tag);
- prog_stop (pp, SIGKILL);
- break;
- }
-
- if (!pp)
- {
- pp = emalloc (sizeof(*pp) + taglen + 1);
- memset (pp, 0, sizeof(*pp));
- pp->type = TYPE_RETR;
- pp->tag = (char *) (pp + 1);
- strcpy (pp->tag, tag);
- free (tag);
- pp->v.r.master = master;
- link_prog (pp, 1);
- }
-
- pp->pid = pid;
-}
-
-void
-register_prog (int type, char *tag, char **argv, int retr[2], char **depv,
- char *pidfile)
-{
- 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 (*newp)
- + (tag ? (strlen (tag) + 1) : 0);
- if (pidfile)
- size += strlen (pidfile) + 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]);
- newp->v.p.argv[i] = pstr;
- pstr += strlen (pstr) + 1;
- }
- newp->v.p.argv[i] = NULL;
-
- if (tag)
- {
- newp->tag = strcpy (pstr, tag);
- pstr += strlen (pstr) + 1;
- }
- else
- newp->tag = newp->v.p.argv[0];
-
- if (pidfile)
- {
- newp->v.p.pidfile = strcpy (pstr, pidfile);
- pstr += strlen (pstr) + 1;
- }
- else
- newp->v.p.pidfile = NULL;
-
- 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 (newp, 0);
-}
-
-void
-register_transport (char *tag, char **argv, int retr[2], char **depv,
- char *pidfile)
-{
- static char *std_dep[] = { "all", NULL };
- if (!depv)
- depv = std_dep;
- register_prog (TYPE_TRANSPORT, tag, argv, retr, depv, pidfile);
-}
-
-void
-register_jabber_process (char *cmd, char *cfg)
-{
- int retr[2] = { -1, -1 };
- char *argv[5];
- int argc = 0;
-
- argv[argc++] = cmd;
- if (cfg)
- {
- argv[argc++] = "-c";
- argv[argc++] = cfg;
- }
- if (debug_level > 2)
- {
- argv[argc++] = "-D";
- retr[RETR_ERR] = LOG_DEBUG;
- }
- argv[argc] = NULL;
-
- register_prog (TYPE_CORE, NULL, argv, retr, NULL, NULL);
-}
-
-static struct prog *
-find_prog (pid_t pid)
-{
- struct prog *prog;
-
- for (prog = proghead; prog; prog = prog->next)
- if (prog->pid == pid)
- break;
- return prog;
-}
-
-size_t
-progman_running_count ()
-{
- size_t size = 0;
- struct prog *prog;
-
- for (prog = proghead; prog; prog = prog->next)
- if (prog->pid > 0)
- size++;
- return size;
-}
-
-RETSIGTYPE
-retr_exit (int sig)
-{
- exit (0);
-}
-
-int
-open_retranslator (struct prog *master, int type)
-{
- int p[2];
- FILE *fp;
- char *buf = NULL;
- size_t size = 0;
- pid_t pid;
-
- if (master->v.p.retr[type] == -1)
- return -1;
- pipe (p);
- switch (pid = fork ())
- {
- case 0:
- /* Retranslator process */
-
- syslog_setup ();
- signal_setup (retr_exit);
-
- close (p[1]);
- fp = fdopen (p[0], "r");
- if (fp == NULL)
- exit (1);
-
- openlog (master->tag, LOG_PID, log_facility);
-
- while (getline (&buf, &size, fp) > 0)
- logmsg (master->v.p.retr[type], "%s", buf);
- exit (0);
-
- case -1:
- logmsg (LOG_CRIT, "cannot run retranslator `%s': fork failed: %s",
- master->tag, strerror (errno));
- return -1;
-
- default:
- register_retr (type, master, pid);
-
- close (p[0]);
- return p[1];
- }
-}
-
-static void
-prog_start (struct prog *prog)
-{
- int i;
- pid_t pid;
- time_t now;
- int retr[2];
-
- time (&now);
-
- if (prog->v.p.timestamp + TESTTIME > now)
- prog->v.p.count++;
- else
- {
- prog->v.p.count = 0;
- prog->v.p.timestamp = now;
- }
-
- if (prog->v.p.count > MAXSPAWN)
- {
- int old_alarm;
-
- logmsg(LOG_ERR, "%s is respawning too fast, disabled for %d minutes",
- prog->tag, SLEEPTIME / 60);
- prog->v.p.timestamp = now;
- prog->v.p.disabled = 1;
-
- old_alarm = alarm (0);
- if (old_alarm > SLEEPTIME || old_alarm <= 0)
- old_alarm = SLEEPTIME;
- alarm (old_alarm);
- return;
- }
-
- logmsg (LOG_DEBUG, "starting %s", prog->tag);
-
- if (prog->v.p.pidfile)
- {
- if (unlink (prog->v.p.pidfile) && errno != ENOENT)
- logmsg (LOG_ERR, "%s: cannot remove pidfile `%s': %s",
- prog->tag, prog->v.p.pidfile, strerror (errno));
- }
-
- retr[RETR_OUT] = open_retranslator (prog, RETR_OUT);
- retr[RETR_ERR] = open_retranslator (prog, RETR_ERR);
-
- switch (pid = fork ())
- {
- /* The child branch. */
- case 0:
- if (retr[RETR_OUT] == -1)
- {
- close (1);
- open ("/dev/null", O_RDWR);
- }
- else if (retr[RETR_OUT] != 1)
- {
- close (1);
- dup2 (retr[RETR_OUT], 1);
- }
-
- if (retr[RETR_ERR] == -1)
- {
- close (2);
- open ("/dev/null", O_RDWR);
- }
- else if (retr[RETR_ERR] != 1)
- {
- close (2);
- dup2 (retr[RETR_ERR], 2);
- }
-
- /* Close unneded descripitors */
- for (i = getmaxfd (); i > 2; i--)
- close (i);
-
- signal_setup (SIG_DFL);
-
- execvp(prog->v.p.argv[0], prog->v.p.argv);
- openlog (syslog_tag, LOG_PID, log_facility);
- logmsg (LOG_CRIT, "cannot start `%s': %s", prog->tag,
- strerror (errno));
- exit (1);
-
- case -1:
- logmsg (LOG_CRIT, "cannot run `%s': fork failed: %s",
- prog->tag, strerror (errno));
- break;
-
- default:
- prog->pid = pid;
- }
-}
-
-void
-progman_start ()
-{
- struct prog *prog;
-
- for (prog = proghead; prog; prog = prog->next)
- if (IS_PROG (prog))
- prog_start (prog);
-}
-
-void
-progman_wake_disabled ()
-{
- struct prog *prog;
-
- for (prog = proghead; prog; prog = prog->next)
- if (IS_PROG (prog) && prog->v.p.disabled)
- {
- prog->v.p.disabled = 0;
- prog->v.p.count = 0;
- prog->v.p.timestamp = 0;
- prog_start (prog);
- }
-}
-
-static void
-prog_stop (struct prog *prog, int 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
-progman_stop ()
-{
- unsigned long i;
-
- prog_stop_recursive (proghead, SIGTERM);
- for (i = 0; i < shutdown_timeout; i++)
- {
- progman_cleanup (1);
- if (progman_running_count () == 0)
- return;
- sleep (1);
- }
- prog_stop_recursive (proghead, SIGKILL);
-}
-
-static void
-print_status (char *tag, pid_t pid, int status, int expect_term)
-{
- if (WIFEXITED (status))
- {
- if (WEXITSTATUS (status) == 0)
- logmsg (LOG_DEBUG,
- "%s (%lu) exited successfully",
- tag, (unsigned long) pid);
- else
- logmsg (LOG_ERR,
- "%s (%lu) failed with status %d",
- tag, (unsigned long) pid,
- WEXITSTATUS (status));
- }
- else if (WIFSIGNALED (status))
- {
- int prio;
-
- if (expect_term && WTERMSIG (status) == SIGTERM)
- prio = LOG_DEBUG;
- else
- prio = LOG_ERR;
-
- logmsg(prio,
- "%s (%lu) terminated on signal %d",
- tag, (unsigned long) pid,
- WTERMSIG (status));
- }
- else if (WIFSTOPPED (status))
- logmsg(LOG_ERR,
- "%s (%lu) stopped on signal %d",
- tag, (unsigned long) pid,
- WSTOPSIG (status));
-#ifdef WCOREDUMP
- else if (WCOREDUMP (status))
- logmsg (LOG_ERR,
- "%s (%lu) dumped core",
- tag, (unsigned long) pid);
-#endif
- else
- logmsg(LOG_ERR,
- "%s (%lu) terminated with unrecognized status",
- tag, (unsigned long) pid);
-}
-
-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;
- int status;
- while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
- {
- struct prog *prog = find_prog (pid);
- if (!prog)
- {
- logmsg (LOG_NOTICE, "unknown child %lu finished",
- (unsigned long) pid);
- continue;
- }
- print_status (prog->tag, prog->pid, status, expect_term);
- prog->pid = 0;
- 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];
- time_t t = prog->v.p.timestamp + SLEEPTIME;
- strftime (buf, sizeof buf, "%c",
- localtime (&t));
- 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.