summaryrefslogtreecommitdiffabout
path: root/jabberd/main.c
Side-by-side diff
Diffstat (limited to 'jabberd/main.c') (more/less context) (ignore whitespace changes)
-rw-r--r--jabberd/main.c910
1 files changed, 0 insertions, 910 deletions
diff --git a/jabberd/main.c b/jabberd/main.c
deleted file mode 100644
index de0551f..0000000
--- a/jabberd/main.c
+++ b/dev/null
@@ -1,910 +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"
-
-char *progname;
-char *config_file = SYSCONFDIR "/jabberd.cfg";
-int debug_level = 0;
-int foreground = 0;
-int log_to_stderr = 0;
-char *user = "jabber";
-char *syslog_tag = "jabberd";
-int log_facility = LOG_LOCAL7;
-int x_argc;
-char **x_argv;
-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;
-
-void
-syslog_printer (int prio, const char *fmt, va_list ap)
-{
-#if HAVE_VSYSLOG
- vsyslog (prio, fmt, ap);
-#else
- char buf[128];
- vsnprintf (buf, sizeof buf, fmt, ap);
- syslog (prio, "%s", buf);
-#endif
-}
-
-void
-stderr_printer (int prio, const char *fmt, va_list ap)
-{
- const char *p = gsc_syslog_priority_to_str (prio);
- fprintf (stderr, "%s: ", progname);
-
- if (p)
- fprintf (stderr, "[%s] ", p);
-
- vfprintf (stderr, fmt, ap);
- fputc ('\n', stderr);
-}
-
-
-static void (*log_printer) (int prio, const char *fmt, va_list ap) =
- stderr_printer;
-
-void
-logmsg (int prio, char *fmt, ...)
-{
- va_list ap;
- va_start (ap, fmt);
- log_printer (prio, fmt, ap);
- va_end (ap);
-}
-
-void *
-emalloc (size_t size)
-{
- char *p = malloc (size);
- if (!p)
- {
- logmsg (LOG_EMERG, "%s", strerror (errno));
- exit (1);
- }
- return p;
-}
-
-void
-usage ()
-{
- printf ("usage: jabberd [-Dfehv][-c config][-r tag [tag...]]\n");
- printf ("jabberd -- A dispatcher program for jabber 2.x\n");
- printf ("\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);
-}
-
-
-/* Configuration file handling */
-
-void
-cfg_syslog_tag (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- syslog_tag = strdup (val);
-}
-
-void
-cfg_syslog_facility (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- if (gsc_str_to_syslog_facility (val, &log_facility))
- file->error_msg (file->file_name, file->line, "Unknown facility `%s'",
- val);
-}
-
-void
-cfg_user (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- struct passwd *pwd = getpwnam (val);
- if (!pwd)
- file->error_msg (file->file_name, file->line, "no such user `%s'",
- val);
- else if (pwd->pw_uid == 0)
- file->error_msg (file->file_name, file->line, "user `%s' has zero UID",
- val);
- else
- user = strdup (val);
-}
-
-struct group_list
-{
- struct group_list *next;
- gid_t gid;
-};
-
-static struct group_list *group_list;
-
-void
-cfg_group (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- struct group *group = getgrnam (val);
- if (group)
- {
- struct group_list *p = emalloc (sizeof *p);
- p->gid = group->gr_gid;
- p->next = group_list;
- group_list = p;
- }
- else
- file->error_msg (file->file_name, file->line, "unknown group `%s'",
- val);
-}
-
-void
-cfg_pidfile (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- pidfile = strdup (val);
-}
-
-void
-cfg_ctlfile (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- ctlfile = strdup (val);
-}
-
-void
-cfg_statfile (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- ctlfile = strdup (val);
-}
-
-void
-cfg_umask (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- char *p;
- unsigned long n = strtoul (val, &p, 8);
- if (*p)
- file->error_msg (file->file_name, file->line,
- "invalid umask; stopped near `%s'", p);
- else
- jabberd_umask = (mode_t) n;
-}
-
-void
-cfg_prog (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- char *prog = val;
- char *p = val;
-
- for (; *p && !isspace (*p); p++)
- ;
-
- if (*p)
- {
- *p++ = 0;
- for (; *p && isspace (*p); p++)
- ;
-
- val = p;
- }
- else
- val = 0;
-
- register_jabber_process (prog, val);
-}
-
-struct transport_rec
-{
- char *tag;
- char *command;
- int facility;
- int retr[2];
- int depc;
- char **depv;
- char *pidfile;
-};
-
-static void
-cfg_transport_command (gsc_config_file_t *file, char *kw, char *val, void *data)
-{
- struct transport_rec *prec = data;
- prec->command = strdup (val);
-}
-
-void
-cfg_transport_facility (gsc_config_file_t *file, char *kw, char *val, void *data)
-{
- struct transport_rec *prec = data;
- if (gsc_str_to_syslog_facility (val, &prec->facility))
- file->error_msg (file->file_name, file->line,
- "Unknown facility `%s'",
- val);
-}
-
-void
-cfg_transport_stdout (gsc_config_file_t *file, char *kw, char *val, void *data)
-{
- struct transport_rec *prec = data;
- if (gsc_str_to_syslog_priority (val, &prec->retr[RETR_OUT]))
- file->error_msg (file->file_name, file->line, "Unknown priority `%s'",
- val);
-}
-
-void
-cfg_transport_stderr (gsc_config_file_t *file, char *kw, char *val, void *data)
-{
- struct transport_rec *prec = data;
- if (gsc_str_to_syslog_priority (val, &prec->retr[RETR_ERR]))
- file->error_msg (file->file_name, file->line, "Unknown priority `%s'",
- val);
-}
-
-void
-cfg_transport_depend (gsc_config_file_t *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))
- file->error_msg (file->file_name, file->line,
- "cannot split dependency line: %s",
- strerror (rc));
-}
-
-void
-cfg_transport_pidfile (gsc_config_file_t *file, char *kw, char *val,
- void *data)
-{
- struct transport_rec *prec = data;
- prec->pidfile = strdup (val);
-}
-
-void
-cfg_transport (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- int rc;
- int argc;
- char **argv;
-
- struct transport_rec rec;
- static struct gsc_config_keyword kwtab[] = {
- { "command", cfg_transport_command },
- { "stdout", cfg_transport_stdout },
- { "stderr", cfg_transport_stderr },
- { "facility", cfg_transport_facility },
- { "depend", cfg_transport_depend },
- { "pidfile", cfg_transport_pidfile },
- { NULL }
- };
- memset (&rec, 0, sizeof rec);
- rec.retr[RETR_OUT] = rec.retr[RETR_ERR] = -1;
- if (val)
- rec.tag = strdup (val);
-
- gsc_config_parse_block (file, &rec, kwtab, "end");
-
- if (rc = argcv_get (rec.command, NULL, NULL, &argc, &argv))
- {
- file->error_msg (file->file_name, file->line,
- "cannot split command line: %s",
- strerror (rc));
- return;
- }
- register_transport (rec.tag, argv, rec.retr, rec.depv, rec.pidfile);
- free (rec.tag);
- free (rec.command);
- free (rec.pidfile);
- argcv_free (rec.depc, rec.depv);
- argcv_free (argc, argv);
-}
-
-void
-cfg_shutdown_timeout (gsc_config_file_t *file, char *kw, char *val, void *unused)
-{
- char *p;
-
- shutdown_timeout = strtoul (val, &p, 10);
- if (*p)
- file->error_msg (file->file_name, file->line,
- "unrecognized timeout value, stopped near %s", p);
-}
-
-struct gsc_config_keyword kw_handler[] = {
- { "syslog-tag", cfg_syslog_tag },
- { "syslog-facility", cfg_syslog_facility },
- { "user", cfg_user },
- { "group", cfg_group },
- { "pidfile", cfg_pidfile },
- { "ctlfile", cfg_ctlfile },
- { "statfile", cfg_statfile },
- { "umask", cfg_umask },
- { "prog", cfg_prog },
- { "transport", cfg_transport },
- { "exec", cfg_transport },
- { "shutdown-timeout", cfg_shutdown_timeout },
- { NULL }
-};
-
-void
-jabber_cfg_error (const char *name, unsigned line, const char *fmt, ...)
-{
- va_list ap;
- size_t n;
- char buffer[128];
-
- n = snprintf (buffer, sizeof buffer, "%s:%u: ", name, line);
- va_start (ap, fmt);
- vsnprintf (buffer + n, sizeof buffer - n, fmt, ap);
- va_end (ap);
- logmsg (LOG_ERR, "%s", buffer);
-}
-
-void
-parse_config ()
-{
- switch (gsc_config_parse (config_file, jabber_cfg_error, kw_handler))
- {
- case gsc_config_success:
- break;
-
- case gsc_config_open:
- logmsg (LOG_EMERG, "cannot open config file `%s': %s",
- config_file, strerror (errno));
- exit (1);
-
- case gsc_config_error:
- exit (1);
- }
-}
-
-
-void
-pidfile_write ()
-{
- 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)
- {
- 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_ERR, "unexpected character %#03o in pidfile `%s'",
- c, pidfile);
- return -1;
- }
- }
- fclose (fp);
- if (kill (n, 0))
- {
- logmsg (LOG_ERR, "Cannot signal master process %lu: %s",
- (unsigned long) n, strerror (errno));
- if (errno == EPERM)
- return n; /* be on the safe side */
- return -1;
- }
- return n;
-}
-
-void
-pidfile_remove ()
-{
- if (unlink (pidfile))
- logmsg (LOG_ERR, "cannot remove pidfile `%s': %s",
- pidfile, strerror (errno));
-}
-
-
-/* Switch to the given UID/GID */
-int
-switch_to_privs (uid_t uid, gid_t gid)
-{
- int rc = 0;
- gid_t *emptygidset;
- size_t size = 1, j = 1;
- struct group_list *gp;
-
- if (uid == 0)
- {
- logmsg (LOG_EMERG, "refusing to run as root");
- return 1;
- }
-
- /* Create a list of supplementary groups */
- for (gp = group_list; gp; gp = gp->next)
- size++;
- emptygidset = emalloc (size * sizeof emptygidset[0]);
- emptygidset[0] = gid ? gid : getegid ();
-
- for (gp = group_list; gp; gp = gp->next)
- emptygidset[j++] = gp->gid;
-
- rc = gsc_userprivs (uid, emptygidset, j);
- free (emptygidset);
- if (rc)
- logmsg (LOG_ERR, "%s", gsc_userprivs_errstring ());
-
- return rc;
-}
-
-void
-priv_setup ()
-{
- if (getuid () == 0)
- {
- if (!user)
- {
- logmsg (LOG_ERR, "non-privileged user not given");
- exit (1);
- }
- else
- {
- struct passwd *pw = getpwnam (user);
- if (!pw)
- {
- logmsg (LOG_ERR, "No such user: %s", user);
- exit (1);
- }
- if (pw && switch_to_privs (pw->pw_uid, pw->pw_gid))
- exit (1);
- }
- }
-}
-
-
-#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;
-int got_alarm = 0;
-
-RETSIGTYPE
-sig_handler(int sig)
-{
- switch (sig)
- {
- case SIGCHLD:
- children_cleanup = 1;
- break;
-
- case SIGTERM:
- case SIGINT:
- case SIGQUIT:
- action = ACTION_STOP;
- logmsg (LOG_NOTICE, "received signal %d", sig);
- break;
-
- case SIGHUP:
- logmsg (LOG_NOTICE, "received signal %d", sig);
- if (x_argc == 0)
- {
- logmsg (LOG_NOTICE,
- "SIGHUP: not started with an absolute pathname");
- action = ACTION_STOP;
- }
- else
- action = ACTION_RESTART;
- break;
-
- case SIGALRM:
- got_alarm = 1;
- break;
-
- case SIGUSR1:
- action = ACTION_COMPRELOAD;
- break;
-
- case SIGUSR2:
- action = ACTION_DUMPSTATS;
- break;
- }
- signal (sig, sig_handler);
-}
-
-void
-signal_setup (RETSIGTYPE (*sf)(int))
-{
- signal (SIGCHLD, sf);
- signal (SIGTERM, sf);
- signal (SIGQUIT, sf);
- signal (SIGINT, sf);
- signal (SIGHUP, sf);
- signal (SIGALRM, sf);
- signal (SIGUSR1, sf);
- signal (SIGUSR2, sf);
-}
-
-void
-syslog_setup ()
-{
- log_printer = syslog_printer;
-}
-
-
-
-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 < 4 && 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_long (argc, argv, "c:Dfehrv", options, NULL)) != EOF)
- {
- switch (c)
- {
- case 'c':
- config_file = optarg;
- break;
-
- case 'D':
- debug_level++;
- break;
-
- case 'f':
- foreground = 1;
-
- case 'e':
- log_to_stderr = 1;
- break;
-
- case 'h':
- usage ();
- exit (0);
-
- case 'v':
- gsc_version ("jabberd");
- 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);
- exit (1);
- }
- }
-
- if (argc != optind && mode != 'r')
- {
- logmsg (LOG_CRIT, "extra command line arguments");
- exit (1);
- }
-
- parse_config ();
-
- if (!log_to_stderr)
- {
- openlog (syslog_tag, LOG_PID, log_facility);
- 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 started");
- if (!foreground && daemon (0, 0) == -1)
- {
- logmsg (LOG_CRIT, "cannot become a daemon: %s",
- strerror (errno));
- exit (1);
- }
- pidfile_write ();
-
- signal_setup (sig_handler);
-
- progman_start ();
-
- while (action == ACTION_CONT)
- {
- pause ();
- if (children_cleanup)
- {
- children_cleanup = 0;
- progman_cleanup (0);
- }
- if (got_alarm)
- {
- 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 ();
-
- pidfile_remove ();
- if (action == ACTION_RESTART)
- {
- int i;
-
- for (i = getmaxfd (); i > 0; i--)
- close (i);
-
- signal_setup (SIG_DFL);
-
- execv (x_argv[0], x_argv);
- openlog (syslog_tag, LOG_PID, log_facility);
- logmsg (LOG_EMERG, "cannot restart: %s", strerror (errno));
- }
- logmsg (LOG_NOTICE, "jabberd finished");
- exit (0);
-}

Return to:

Send suggestions and report system problems to the System administrator.