static void stop() { FILE *f; unsigned long pid; int fd; if ((f=fopen(PIDFILE, "r")) == 0) return; if (fscanf(f, "%lu", &pid) <= 0) { fclose(f); return; } fclose(f); kill (pid, SIGTERM); /* ** Wait until the daemon goes away by attempting to lock the lock file ** ourselves. */ alarm(15); fd=open(LOCKFILE, O_RDWR); if (fd < 0) return; ll_lock_ex(fd); close(fd); }
static void stop1(const char *lockfile, const char *pidfile) { int lockfd; pid_t p; if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0) { perror(lockfile); exit(1); } if ( ll_lock_ex_test(lockfd) == 0) /* No daemon process running */ { close(lockfd); exit (0); /* That was easy! */ } signal(SIGCHLD, sigexit); if ((p=fork()) == -1) { perror("fork"); exit(1); } if (p) /* Parent - first sends a SIGTERM, then a SIGKILL */ { int signum=SIGTERM; close(lockfd); for (;; sleep(10)) { FILE *fp; int c; if ((fp=fopen(pidfile, "r")) == NULL) continue; p=0; while ((c=getc(fp)) != EOF && c != '\n') { if (isdigit(c)) p=p*10+(c-'0'); } fclose(fp); if (p) kill(p, signum); signum=SIGKILL; } } if (ll_lock_ex(lockfd)) perror("lock"); close(lockfd); exit(0); }
static FILE *open_and_lock_cached_policy_file(const char *filename, int *readwrite) { int fd; int save_errno; *readwrite=1; fd=open(filename, O_RDWR | O_CREAT, 0644); if (fd >= 0 && ll_lock_ex(fd) >= 0) { FILE *fp=fdopen(fd, "r+"); if (fp) return fp; } /* ** Non-root will not be able to write to the cache. ** ** Do not pollute terminal output, but if this is run from the ** script let's bark this somewhere where someone will hopefully ** notice this. */ save_errno=errno; if (!isatty(2)) { errno=save_errno; perror(filename); } if (fd >= 0) close(fd); *readwrite=0; fd=open(filename, O_RDONLY); if (fd >= 0 && ll_lockfd(fd, ll_readlock|ll_whence_start|ll_wait, 0, 0) >= 0) { FILE *fp=fdopen(fd, "r"); if (fp) return fp; } if (fd >= 0) close(fd); return NULL; }
static void check_db() { char *dbname; char *lockname; int lockfd; struct dbobj db; time_t now; char *sender_key, *p; size_t val_len; char *val; if (!dbfile || !*dbfile) return; sender_key=strdup(sender); dbname=malloc(strlen(dbfile)+ sizeof( "." DBNAME)); lockname=malloc(strlen(dbfile)+ sizeof(".lock")); for (p=sender_key; *p; p++) *p=tolower((int)(unsigned char)*p); if (!dbname || !lockname || !sender) { perror("malloc"); exit(EX_TEMPFAIL); } strcat(strcpy(dbname, dbfile), "." DBNAME); strcat(strcpy(lockname, dbfile), ".lock"); lockfd=open(lockname, O_RDWR|O_CREAT, 0666); if (lockfd < 0 || ll_lock_ex(lockfd)) { perror(lockname); exit(EX_TEMPFAIL); } dbobj_init(&db); if (dbobj_open(&db, dbname, "C") < 0) { perror(dbname); exit(EX_TEMPFAIL); } time(&now); val=dbobj_fetch(&db, sender_key, strlen(sender_key), &val_len, ""); if (val) { time_t t; if (val_len >= sizeof(t)) { memcpy(&t, val, sizeof(t)); if (t >= now - interval * 60 * 60 * 24) { free(val); dbobj_close(&db); close(lockfd); exit(0); } } free(val); } dbobj_store(&db, sender_key, strlen(sender_key), (void *)&now, sizeof(now), "R"); dbobj_close(&db); close(lockfd); }
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); }