static void control_sig_handler(int sig, short event, void *p) { switch (sig) { case SIGINT: case SIGTERM: control_shutdown(); break; default: fatalx("control_sig_handler: unexpected signal"); } }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //plugin_reconfigure //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static void _restart_specific_systems(void) { //Shutdown specific systems module_shutdown(); variables_shutdown(); control_shutdown(); agent_shutdown(); style_shutdown(); plugin_controls_shutdown(); plugin_agents_shutdown(); //Restart agent and control masters style_startup(); control_startup(); agent_startup(); plugin_controls_startup(); plugin_agents_startup(); module_startup(); variables_startup(); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //plugin_shutdown //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void plugin_shutdown(bool save) { message_interpret(globalmodule.actions[MODULE_ACTION_ONUNLOAD], false, &globalmodule); //Save config settings if (save) config_save(config_path_mainscript); //Shutdown the message & dialog system message_shutdown(); dialog_shutdown(); //Shutdown agents and controls variables_shutdown(); module_shutdown(); control_shutdown(); agent_shutdown(); //Shutdown the windowing system window_shutdown(); //Shutdown the style system. style_shutdown(); //Shutdown control types plugin_controls_shutdown(); //Shutdown agents plugin_agents_shutdown(); tooltip_shutdown(); //Shutdown the configuration system config_shutdown(); menu_shutdown(); }
pid_t control(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: post_fork(PROC_CONTROL); break; default: return (pid); } purge_config(PURGE_EVERYTHING); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); stat_backend = env->sc_stat; stat_backend->init(); if (chroot(PATH_CHROOT) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); config_process(PROC_CONTROL); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); tree_init(&ctl_conns); tree_init(&ctl_count); memset(&digest, 0, sizeof digest); digest.startup = time(NULL); config_peer(PROC_SCHEDULER); config_peer(PROC_QUEUE); config_peer(PROC_PARENT); config_peer(PROC_LKA); config_peer(PROC_PONY); config_peer(PROC_CA); config_done(); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }
pid_t control(void) { struct sockaddr_un sun; int fd; mode_t old_umask; pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; struct peer peers [] = { { PROC_RUNNER, imsg_dispatch }, { PROC_QUEUE, imsg_dispatch }, { PROC_SMTP, imsg_dispatch }, { PROC_MFA, imsg_dispatch }, { PROC_PARENT, imsg_dispatch }, }; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: break; default: return (pid); } purge_config(PURGE_EVERYTHING); pw = env->sc_pw; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("control: socket"); bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; if (strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) fatal("control: socket name too long"); if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) fatalx("control socket already listening"); if (unlink(SMTPD_SOCKET) == -1) if (errno != ENOENT) fatal("control: cannot unlink socket"); old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { (void)umask(old_umask); fatal("control: bind"); } (void)umask(old_umask); if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { (void)unlink(SMTPD_SOCKET); fatal("control: chmod"); } session_socket_blockmode(fd, BM_NONBLOCK); control_state.fd = fd; if (chroot(pw->pw_dir) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); smtpd_process = PROC_CONTROL; setproctitle("%s", env->sc_title[smtpd_process]); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); TAILQ_INIT(&ctl_conns); config_pipes(peers, nitems(peers)); config_peers(peers, nitems(peers)); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }
static void control_imsg(struct mproc *p, struct imsg *imsg) { struct ctl_conn *c; struct stat_value val; struct msg m; const char *key; const void *data; size_t sz; if (imsg == NULL) { if (p->proc != PROC_CLIENT) control_shutdown(); return; } if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_CTL_SMTP_SESSION: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; m_compose(&c->mproc, IMSG_CTL_OK, 0, 0, imsg->fd, NULL, 0); return; } } if (p->proc == PROC_SCHEDULER) { switch (imsg->hdr.type) { case IMSG_CTL_OK: case IMSG_CTL_FAIL: case IMSG_CTL_LIST_MESSAGES: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; imsg->hdr.peerid = 0; m_forward(&c->mproc, imsg); return; } } if (p->proc == PROC_QUEUE) { switch (imsg->hdr.type) { case IMSG_CTL_LIST_ENVELOPES: case IMSG_CTL_DISCOVER_EVPID: case IMSG_CTL_DISCOVER_MSGID: case IMSG_CTL_UNCORRUPT_MSGID: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; m_forward(&c->mproc, imsg); return; } } if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_CTL_OK: case IMSG_CTL_FAIL: case IMSG_CTL_MTA_SHOW_HOSTS: case IMSG_CTL_MTA_SHOW_RELAYS: case IMSG_CTL_MTA_SHOW_ROUTES: case IMSG_CTL_MTA_SHOW_HOSTSTATS: case IMSG_CTL_MTA_SHOW_BLOCK: c = tree_get(&ctl_conns, imsg->hdr.peerid); if (c == NULL) return; imsg->hdr.peerid = 0; m_forward(&c->mproc, imsg); return; } } switch (imsg->hdr.type) { case IMSG_STAT_INCREMENT: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); if (sz != sizeof(val)) fatalx("control: IMSG_STAT_INCREMENT size mismatch"); memmove(&val, data, sz); if (stat_backend) stat_backend->increment(key, val.u.counter); control_digest_update(key, val.u.counter, 1); return; case IMSG_STAT_DECREMENT: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); if (sz != sizeof(val)) fatalx("control: IMSG_STAT_DECREMENT size mismatch"); memmove(&val, data, sz); if (stat_backend) stat_backend->decrement(key, val.u.counter); control_digest_update(key, val.u.counter, 0); return; case IMSG_STAT_SET: m_msg(&m, imsg); m_get_string(&m, &key); m_get_data(&m, &data, &sz); m_end(&m); if (sz != sizeof(val)) fatalx("control: IMSG_STAT_SET size mismatch"); memmove(&val, data, sz); if (stat_backend) stat_backend->set(key, &val); return; } errx(1, "control_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
pid_t control(void) { struct sockaddr_un sun; int fd; mode_t old_umask; pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: break; default: return (pid); } purge_config(PURGE_EVERYTHING); pw = env->sc_pw; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("control: socket"); bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; if (strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) fatal("control: socket name too long"); if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) fatalx("control socket already listening"); if (unlink(SMTPD_SOCKET) == -1) if (errno != ENOENT) fatal("control: cannot unlink socket"); old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { (void)umask(old_umask); fatal("control: bind"); } (void)umask(old_umask); if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { (void)unlink(SMTPD_SOCKET); fatal("control: chmod"); } session_socket_blockmode(fd, BM_NONBLOCK); control_state.fd = fd; stat_backend = env->sc_stat; stat_backend->init(); if (chroot(PATH_CHROOT) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); config_process(PROC_CONTROL); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); tree_init(&ctl_conns); bzero(&digest, sizeof digest); digest.startup = time(NULL); config_peer(PROC_SCHEDULER); config_peer(PROC_QUEUE); config_peer(PROC_SMTP); config_peer(PROC_MFA); config_peer(PROC_PARENT); config_peer(PROC_LKA); config_peer(PROC_MDA); config_peer(PROC_MTA); config_done(); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }