int main(int argc, char **argv) { if (getuid() == 0) libmail_changeuidgid(MAILUID, MAILGID); /* Drop root privileges */ if (chdir(courierdir()) < 0) { perror("courierdir"); return (1); } if (argc > 1) { if (strcmp(argv[1], "stop") == 0) { stop(); return (0); } if (strcmp(argv[1], "start") == 0) { return (start()); } if (strcmp(argv[1], "restart") == 0) { return (restart()); } } fprintf(stderr, "Usage: %s (stop|restart|start)\n", argv[0]); return (1); }
int main(int argc, char **argv) { if (argc > 1 && strcmp(argv[1], "--version") == 0) { printf("%s\n", COURIER_COPYRIGHT); exit(0); } if (chdir(courierdir())) { perror("chdir"); return (1); } if (argc < 2) return (0); if (strcmp(argv[1], "stop") == 0) { int fd; trigger(TRIGGER_STOP); /* Wait until the exclusive lock goes away: */ signal(SIGHUP, SIG_DFL); if ((fd=open(TMPDIR "/courierd.lock", O_RDWR|O_CREAT, 0600)) < 0) clog_msg_errno(); alarm(15); /* But abort after 15 seconds. */ ll_lock_ex(fd); return (0); } if (strcmp(argv[1], "restart") == 0) { trigger(TRIGGER_RESTART); return (0); } if (strcmp(argv[1], "flush") == 0) { ino_t n; struct ctlfile ctf; if (getuid()) { /* ** We'll fail trying to open the pipe anyway, but let's ** give a meaningful error message now. */ fprintf(stderr, "courier flush can be executed only by the superuser.\n"); exit(1); } if (argc < 3) { trigger(TRIGGER_FLUSH); /* Everything */ exit(0); } if (comparseqid(argv[2], &n) == 0 && ctlfile_openi(n, &ctf, 1) == 0) { int c=ctlfile_searchfirst(&ctf, COMCTLFILE_MSGID); if (c >= 0 && strcmp(ctf.lines[c]+1, argv[2]) == 0) { char *s=courier_malloc(sizeof(TRIGGER_FLUSHMSG)+1+ strlen(argv[2])); strcat(strcat(strcpy(s, TRIGGER_FLUSHMSG), argv[2]), "\n"); trigger(s); ctlfile_close(&ctf); return (0); } ctlfile_close(&ctf); } fprintf(stderr, "No such message.\n"); exit(1); return (1); } /* Might as well... */ if (strcmp(argv[1], "start") == 0) { pid_t p; int waitstat; char dummy; /* ** Ok, courierd will close file descriptor 3 when it starts, so we ** put a pipe on there, and wait for it to close. */ int pipefd[2]; close(3); if (open("/dev/null", O_RDONLY) != 3 || pipe(pipefd)) { fprintf(stderr, "Cannot open pipe\n"); exit(1); } if (getuid()) { /* ** We'll fail trying to execute courierd anyway, but let's ** give a meaningful error message now. */ fprintf(stderr, "courier start can be executed only by the superuser.\n"); return (1); } signal(SIGCHLD, SIG_DFL); while ((p=fork()) == -1) { perror("fork"); sleep(10); } if (p == 0) { dup2(pipefd[1], 3); close(pipefd[1]); close(pipefd[0]); while ((p=fork()) == -1) { perror("fork"); sleep(10); } if (p == 0) { /* ** stdin from the bitbucket. stdout to ** /dev/null, or the bitbucket. */ signal(SIGHUP, SIG_IGN); close(0); open("/dev/null", O_RDWR); dup2(0, 1); dup2(0, 2); /* See if we can disconnect from the terminal */ #ifdef TIOCNOTTY { int fd=open("/dev/tty", O_RDWR); if (fd >= 0) { ioctl(fd, TIOCNOTTY, 0); close(fd); } } #endif /* Remove any process groups */ #if HAVE_SETPGRP #if SETPGRP_VOID setpgrp(); #else setpgrp(0, 0); #endif #endif execl( DATADIR "/courierctl.start", "courierctl.start", (char *)0); perror("exec"); _exit(1); } _exit(0); } close(pipefd[1]); while (wait(&waitstat) != p) ; if (read(pipefd[0], &dummy, 1) < 0) ; /* ignore */ close(pipefd[0]); close(3); return (0); } if (strcmp(argv[1], "clear") == 0 && argc > 2) { libmail_changeuidgid(MAILUID, MAILGID); if (strcmp(argv[2], "all") == 0) { courier_clear_all(); } else { track_save(argv[2], TRACK_ADDRACCEPTED); printf("%s cleared.\n", argv[2]); } return (0); } if (argc > 2 && strcmp(argv[1], "show") == 0 && strcmp(argv[2], "all") == 0) { libmail_changeuidgid(MAILUID, MAILGID); courier_show_all(); } return (0); }
void drvinfo::init() { unsigned cnt, i; struct rw_transport *p; module_dsn=0; queuelo=0; for (cnt=0, p=rw_transport_first; p; p=p->next) ++cnt; if ((modules=new drvinfo[cnt]) == 0) clog_msg_errno(); cnt=0; for (p=rw_transport_first; p; p=p->next) { char *namebuf=(char *)courier_malloc( sizeof( SYSCONFDIR "/module.")+strlen(p->name)); strcat(strcpy(namebuf, SYSCONFDIR "/module."), p->name); FILE *config=fopen(namebuf, "r"); if (!config) { clog_msg_start_err(); clog_msg_str("Cannot open "); clog_msg_str(namebuf); clog_msg_send(); exit(1); } free(namebuf); unsigned maxdels=1; unsigned maxhost=1; unsigned maxrcpt=1; char *prog=0; char buf[BUFSIZ]; while (fgets(buf, sizeof(buf), config) != 0) { char *p; if ((p=strchr(buf, '#')) != 0) *p=0; p=strtok(buf, " \t\r\n="); if (strcmp(p, "MAXDELS") == 0) { p=strtok(NULL, " \t\r\n="); if (p) maxdels=atoi(p); } else if (strcmp(p, "MAXHOST") == 0) { p=strtok(NULL, " \t\r\n="); if (p) maxhost=atoi(p); } else if (strcmp(p, "MAXRCPT") == 0) { p=strtok(NULL, " \t\r\n="); if (p) maxrcpt=atoi(p); } else if (strcmp(p, "PROG") == 0 && !prog) { p=strtok(NULL, "\t\r\n="); if (p) { prog=(char *) courier_malloc(strlen(p)+1); strcpy(prog, p); } } } fclose(config); if (!prog) continue; // Input only module modules[cnt].module=p; p->udata=(void *)&modules[cnt]; modules[cnt].delinfo_list.resize(maxdels); modules[cnt].hosts_list.resize(maxdels); queuelo += maxdels; modules[cnt].maxhost=maxhost; modules[cnt].maxrcpt=maxrcpt; modules[cnt].delpfreefirst=0; if (strcmp(p->name, DSN) == 0) module_dsn= &modules[cnt]; for (i=0; i<maxdels; i++) { modules[cnt].delinfo_list[i].delid=i; modules[cnt].delinfo_list[i].freenext= modules[cnt].delpfreefirst; modules[cnt].delpfreefirst= &modules[cnt].delinfo_list[i]; } modules[cnt].hdlvrpfree=0; for (i=0; i<maxdels; i++) { modules[cnt].hosts_list[i].next= modules[cnt].hdlvrpfree; modules[cnt].hdlvrpfree=&modules[cnt].hosts_list[i]; } modules[cnt].hdlvrpfirst=0; modules[cnt].hdlvrplast=0; int pipe0[2], pipe1[2]; if (pipe(pipe0) || pipe(pipe1)) clog_msg_errno(); switch (modules[cnt].module_pid=fork()) { case 0: #if 0 // replaced by close-on-exec, below for (i=cnt; i; ) { --i; fclose(modules[i].module_to); close(modules[i].module_from.fd); } #endif close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); close(pipe0[0]); close(pipe1[1]); signal(SIGCHLD, SIG_DFL); if (chdir(MODULEDIR) || chdir(modules[cnt].module->name)) { clog_msg_start_err(); clog_msg_str(MODULEDIR "/"); clog_msg_str(modules[cnt].module->name); clog_msg_str(" does not exist."); clog_msg_send(); clog_msg_errno(); } { char maxdels_buf[MAXLONGSIZE+15]; char maxhost_buf[MAXLONGSIZE+15]; char maxrcpt_buf[MAXLONGSIZE+15]; const char *sh=getenv("SHELL"); sprintf(maxdels_buf, "MAXDELS=%ld", (long)maxdels); sprintf(maxhost_buf, "MAXHOST=%ld", (long)maxhost); sprintf(maxrcpt_buf, "MAXRCPT=%ld", (long)maxrcpt); putenv(maxdels_buf); putenv(maxhost_buf); putenv(maxrcpt_buf); const char *ch=courierdir(); char *p=(char *)courier_malloc(strlen(ch)+ sizeof("COURIER_HOME=")); strcat(strcpy(p,"COURIER_HOME="), ch); putenv(p); if (!sh) sh="/bin/sh"; execl(sh, sh, "-c", prog, (char *)0); clog_msg_start_err(); clog_msg_str(MODULEDIR "/"); clog_msg_str(modules[cnt].module->name); clog_msg_str(": "); clog_msg_str(prog); clog_msg_send(); clog_msg_errno(); } case -1: clog_msg_errno(); break; } close(pipe0[0]); close(pipe1[1]); if (fcntl(pipe0[1], F_SETFD, FD_CLOEXEC) || fcntl(pipe1[0], F_SETFD, FD_CLOEXEC)) clog_msg_errno(); if ((modules[cnt].module_to=fdopen(pipe0[1], "w")) == NULL) clog_msg_errno(); mybuf_init( &modules[cnt].module_from, pipe1[0] ); clog_msg_start_info(); clog_msg_str("Started "); clog_msg_str(prog); clog_msg_str(", pid="); clog_msg_int(modules[cnt].module_pid); clog_msg_str(", maxdels="); clog_msg_int(maxdels); clog_msg_str(", maxhost="); clog_msg_int(maxhost); clog_msg_str(", maxrcpt="); clog_msg_int(maxrcpt); clog_msg_send(); free(prog); cnt++; } nmodules=cnt; if (queuelo < 200) queuelo=200; char *cfname=config_localfilename("queuelo"); char *conf=config_read1l(cfname); if (conf) { queuelo=atoi(conf); free(conf); } free(cfname); if (queuelo < 20) queuelo=20; cfname=config_localfilename("queuehi"); conf=config_read1l(cfname); if (conf) { queuehi=atoi(conf); free(conf); } else queuehi=queuelo < 500 ? queuelo * 2:queuelo+1000; if (queuehi < queuelo) queuehi=queuelo; free(cfname); clog_msg_start_info(); clog_msg_str("queuelo="); clog_msg_int(queuelo); clog_msg_str(", queuehi="); clog_msg_int(queuehi); clog_msg_send(); if (module_dsn == 0) { clog_msg_start_err(); clog_msg_str("Driver dsn not found."); clog_msg_send(); exit(1); } }
int submit_fork_virtual(char **args, char **env, void (*func)(const char *)) { int pipe0[2], pipe1[2]; printfunc=func; submit_error=1; log_error_prefix_func=0; if (pipe(pipe0)) { clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); return (-1); } if (pipe(pipe1)) { close(pipe0[0]); close(pipe0[1]); clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); return (-1); } submit_pid=fork(); if ( submit_pid == 0) { static char execfailed[]="400 Unable to submit message - service temporarily unavailable.\n"; close(pipe0[1]); close(pipe1[0]); dup2(pipe0[0], 0); dup2(pipe1[1], 1); close(pipe0[0]); close(pipe1[1]); if (chdir(courierdir())) exit(1); execve( LIBEXECDIR "/courier/submit", args, env ); clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); if (write(1, execfailed, sizeof(execfailed)-1) != 1) ; /* ignore */ exit(1); } close(pipe0[0]); close(pipe1[1]); if (submit_pid == -1) { clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); close(pipe0[1]); close(pipe1[0]); return (-1); } if (fcntl(pipe0[1], F_SETFD, FD_CLOEXEC) || (submit_to=fdopen(pipe0[1], "w")) == NULL) { clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); close(pipe0[1]); close(pipe1[0]); (void)submit_wait_noreset(); return (-1); } if (fcntl(pipe1[0], F_SETFD, FD_CLOEXEC) || (fromsubmit=fdopen(pipe1[0], "r")) == NULL) { clog_msg_start_err(); clog_msg_str(LIBEXECDIR "/courier/submit: "); clog_msg_str(strerror(errno)); clog_msg_send(); fclose(submit_to); close(pipe1[0]); (void)submit_wait_noreset(); return (-1); } submit_error=0; signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGHUP, sighandler); return (0); }