X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/05dba91fcb152e1941e7f7f145b1d830c5e8f6d0..c3238c0e:/uip/slocal.c?ds=inline diff --git a/uip/slocal.c b/uip/slocal.c index a807d816..4174d4a0 100644 --- a/uip/slocal.c +++ b/uip/slocal.c @@ -1,6 +1,4 @@ - -/* - * slocal.c -- asynchronously filter and deliver new mail +/* slocal.c -- asynchronously filter and deliver new mail * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for @@ -34,6 +32,10 @@ #include #include +/* Hopefully, grp.h declares initgroups(). If we run into a platform + where it doesn't, we could consider declaring it here as well. */ +#include + /* This define is needed for Berkeley db v2 and above to * make the header file expose the 'historical' ndbm APIs. * We define it unconditionally because this is simple and @@ -179,14 +181,14 @@ int main (int argc, char **argv) { int fd, status; - FILE *fp = stdin; + FILE *fp; char *cp, *mdlvr = NULL, buf[BUFSIZ]; char mailbox[BUFSIZ], tmpfil[BUFSIZ]; char **argp, **arguments; if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } - mts_init (invo_name); + mts_init (); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; @@ -269,15 +271,28 @@ main (int argc, char **argv) if (addr == NULL) addr = getusername (); - if (user == NULL) - user = (cp = strchr(addr, '.')) ? ++cp : addr; + if (user == NULL) { + user = getusername (); + } if ((pw = getpwnam (user)) == NULL) adios (NULL, "no such local user as %s", user); if (chdir (pw->pw_dir) == -1) - chdir ("/"); + if (chdir ("/") < 0) { + advise ("/", "chdir"); + } umask (0077); + if (geteuid() == 0) { + if (setgid (pw->pw_gid) != 0) { + adios ("setgid", "unable to set group to %ld", (long) pw->pw_gid); + } + initgroups (pw->pw_name, pw->pw_gid); + if (setuid (pw->pw_uid) != 0) { + adios ("setuid", "unable to set user to %ld", (long) pw->pw_uid); + } + } + if (info == NULL) info = ""; @@ -406,7 +421,7 @@ usr_delivery (int fd, char *delivery, int su) int i, accept, status=1, won, vecp, next; char *field, *pattern, *action, *result, *string; char buffer[BUFSIZ], tmpbuf[BUFSIZ]; - char *cp, *vec[NVEC]; + char *vec[NVEC]; struct stat st; struct pair *p; FILE *fp; @@ -435,9 +450,7 @@ usr_delivery (int fd, char *delivery, int su) if (*buffer == '#' || *buffer == '\n') continue; - /* zap trailing newline */ - if ((cp = strchr(buffer, '\n'))) - *cp = 0; + trim_suffix_c(buffer, '\n'); /* split buffer into fields */ vecp = split (buffer, vec); @@ -469,7 +482,8 @@ usr_delivery (int fd, char *delivery, int su) * do this - else fall through */ if (!next) - continue; /* else fall */ + continue; + /* FALLTHRU */ case '?': /* @@ -477,7 +491,8 @@ usr_delivery (int fd, char *delivery, int su) * consider delivered if action is successful. */ if (won) - continue; /* else fall */ + continue; + /* FALLTHRU */ case 'A': case 'a': @@ -523,7 +538,8 @@ usr_delivery (int fd, char *delivery, int su) if (won) continue; break; - } /* else fall */ + } + /* FALLTHRU */ default: /* parse message and build lookup table */ @@ -550,7 +566,8 @@ usr_delivery (int fd, char *delivery, int su) case 'q': /* deliver to quoted pipe */ if (strcasecmp (action, "qpipe")) - continue; /* else fall */ + continue; + /* FALLTHRU */ case '^': expand (tmpbuf, string, fd); if (split (tmpbuf, vec) < 1) @@ -561,7 +578,8 @@ usr_delivery (int fd, char *delivery, int su) case 'p': /* deliver to pipe */ if (strcasecmp (action, "pipe")) - continue; /* else fall */ + continue; + /* FALLTHRU */ case '|': vec[2] = "sh"; vec[3] = "-c"; @@ -579,7 +597,8 @@ usr_delivery (int fd, char *delivery, int su) } /* deliver to nmh folder */ else if (strcasecmp (action, "folder")) - continue; /* else fall */ + continue; + /* FALLTHRU */ case '+': status = usr_folder (fd, string); break; @@ -592,7 +611,8 @@ usr_delivery (int fd, char *delivery, int su) } /* mbox format */ else if (strcasecmp (action, "mbox")) - continue; /* else fall */ + continue; + /* FALLTHRU */ case '>': /* mbox format */ @@ -688,7 +708,7 @@ parse (int fd) int i, state; int fd1; char *cp, *dp, *lp; - char name[NAMESZ], field[BUFSIZ]; + char name[NAMESZ], field[NMH_BUFSIZ]; struct pair *p, *q; FILE *in; m_getfld_state_t gstate = 0; @@ -720,7 +740,7 @@ parse (int fd) switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) { case FLD: case FLDPLUS: - lp = add (field, NULL); + lp = mh_xstrdup(field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, in); @@ -746,7 +766,7 @@ parse (int fd) } } if (p->p_name == NULL && i < NVEC) { - p->p_name = getcpy (name); + p->p_name = mh_xstrdup(name); p->p_value = lp; p->p_flags = P_NIL; p++, i++; @@ -760,11 +780,11 @@ parse (int fd) case LENERR: case FMTERR: - advise (NULL, "format error in message"); + inform("format error in message"); break; default: - advise (NULL, "internal error in m_getfld"); + inform("internal error in m_getfld"); fclose (in); return -1; } @@ -857,7 +877,7 @@ glob (int fd) if ((p = lookup (vars, "size"))) { snprintf (buffer, sizeof(buffer), "%d", fstat (fd, &st) != -1 ? (int) st.st_size : 0); - p->p_value = getcpy (buffer); + p->p_value = mh_xstrdup(buffer); } if ((p = lookup (vars, "info"))) p->p_value = getcpy (info); @@ -1053,8 +1073,12 @@ usr_pipe (int fd_arg, char *cmd, char *pgm, char **vec, int suppress) /* child process */ if (fd != 0) dup2 (fd, 0); - freopen ("/dev/null", "w", stdout); - freopen ("/dev/null", "w", stderr); + if (freopen ("/dev/null", "w", stdout) == NULL) { + advise ("stdout", "freopen"); + } + if (freopen ("/dev/null", "w", stderr) == NULL) { + advise ("stderr", "freopen"); + } if (fd != 3) dup2 (fd, 3); closefds (4); @@ -1069,9 +1093,9 @@ usr_pipe (int fd_arg, char *cmd, char *pgm, char **vec, int suppress) setpgid ((pid_t) 0, getpid ()); /* put in own process group */ *environ = NULL; - m_putenv ("USER", pw->pw_name); - m_putenv ("HOME", pw->pw_dir); - m_putenv ("SHELL", pw->pw_shell); + setenv("USER", pw->pw_name, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("SHELL", pw->pw_shell, 1); execvp (pgm, vec); _exit (-1); @@ -1106,16 +1130,15 @@ usr_pipe (int fd_arg, char *cmd, char *pgm, char **vec, int suppress) pidstatus (status, stdout, ", failed"); } return (status == 0 ? 0 : -1); - } else { - /* - * Ruthlessly kill the child and anything - * else in its process group. - */ - killpg(child_id, SIGKILL); - if (verbose) - verbose_printf (", timed-out; terminated\n"); - return -1; } + /* + * Ruthlessly kill the child and anything + * else in its process group. + */ + killpg(child_id, SIGKILL); + if (verbose) + verbose_printf (", timed-out; terminated\n"); + return -1; } } @@ -1142,11 +1165,11 @@ get_sender (char *envelope, char **sender) char buffer[BUFSIZ]; if (envelope == NULL) { - *sender = getcpy (""); + *sender = mh_xstrdup(""); return; } - i = strlen ("From "); + i = LEN("From "); strncpy (buffer, envelope + i, sizeof(buffer)); if ((cp = strchr(buffer, '\n'))) { *cp = 0; @@ -1163,7 +1186,7 @@ get_sender (char *envelope, char **sender) *cp = 0; else break; - *sender = getcpy (buffer); + *sender = mh_xstrdup(buffer); } @@ -1232,13 +1255,12 @@ you_lose: * and massage the headers. Save * a copy of the "From " line for later. */ - i = strlen ("From "); while (fgets (buffer, sizeof(buffer), qfp)) { if (first) { first = 0; - if (!strncmp (buffer, "From ", i)) { + if (has_prefix(buffer, "From ")) { /* get copy of envelope information ("From " line) */ - envelope = getcpy (buffer); + envelope = mh_xstrdup(buffer); /* Put the delivery date in message */ fputs (ddate, ffp); @@ -1307,7 +1329,7 @@ trim (char *cp) *sp = ' '; /* now return a copy */ - return getcpy(bp); + return mh_xstrdup(bp); } /* @@ -1320,7 +1342,7 @@ verbose_printf (char *fmt, ...) va_list ap; va_start(ap, fmt); - vfprintf (stdout, fmt, ap); + vprintf(fmt, ap); va_end(ap); fflush (stdout); /* now flush output */ @@ -1340,22 +1362,22 @@ adorn (char *what, char *fmt, ...) char *s; eindex = errno; /* save the errno */ - fprintf (stdout, ", "); + printf(", "); va_start(ap, fmt); - vfprintf (stdout, fmt, ap); + vprintf(fmt, ap); va_end(ap); if (what) { if (*what) - fprintf (stdout, " %s: ", what); + printf(" %s: ", what); if ((s = strerror (eindex))) - fprintf (stdout, "%s", s); + fputs(s, stdout); else - fprintf (stdout, "Error %d", eindex); + printf("Error %d", eindex); } - fputc ('\n', stdout); + putchar('\n'); fflush (stdout); } @@ -1385,7 +1407,7 @@ static int suppress_duplicates (int fd, char *file) { int fd1, lockfd, state, result; - char *cp, buf[BUFSIZ], name[NAMESZ]; + char *cp, buf[NMH_BUFSIZ], name[NAMESZ]; datum key, value; DBM *db; FILE *in; @@ -1400,6 +1422,7 @@ suppress_duplicates (int fd, char *file) rewind (in); for (;;) { + int failed_to_lock = 0; int bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); switch (state) { @@ -1414,7 +1437,7 @@ suppress_duplicates (int fd, char *file) continue; } - cp = add (buf, NULL); + cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); @@ -1437,7 +1460,8 @@ suppress_duplicates (int fd, char *file) * This will fail if your Maildelivery file doesn't * exist. */ - if ((lockfd = lkopendata(file, O_RDWR, 0)) == -1) { + if ((lockfd = lkopendata(file, O_RDWR, 0, &failed_to_lock)) + == -1) { advise (file, "unable to perform file locking on"); free (cp); fclose (in);