X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/e121e49643a86c4e7fb34dd75ed1542759aa16c9..f1920d78123667716f2321d37ce37628603b2700:/uip/slocal.c diff --git a/uip/slocal.c b/uip/slocal.c index b1760081..a26432c5 100644 --- a/uip/slocal.c +++ b/uip/slocal.c @@ -2,8 +2,6 @@ /* * slocal.c -- asynchronously filter and deliver new mail * - * $Id$ - * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. @@ -16,9 +14,6 @@ * * to their $HOME/.forward file. * - * Under MMDF-I, users should (symbolically) link - * /usr/local/nmh/lib/slocal to $HOME/bin/rcvmail. - * */ /* Changed to use getutent() and friends. Assumes that when getutent() exists, @@ -30,80 +25,59 @@ #include #include #include +#include #include #include +#include #include -#include #include #include -#ifdef INITGROUPS_HEADER -#include INITGROUPS_HEADER -#else -/* On AIX 4.1, initgroups() is defined and even documented (giving the parameter - types as char* and int), but doesn't have a prototype in any of the system - header files. AIX 4.3, SunOS 4.1.3, and ULTRIX 4.2A have the same - problem. */ -extern int initgroups(char*, int); -#endif - - -#ifdef HAVE_DB1_NDBM_H -#include -#else -#ifdef HAVE_GDBM_NDBM_H -#include -#else -#include -#endif -#endif - -#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 -#ifndef HAVE_GETUTENT -# ifndef UTMP_FILE -# ifdef _PATH_UTMP -# define UTMP_FILE _PATH_UTMP -# else -# define UTMP_FILE "/etc/utmp" -# endif -# endif +/* 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 + * harmless. + */ +#define DB_DBM_HSEARCH 1 +#ifdef DB_DBM_HSEARCH +#endif /* Use DB_DBM_HSEARCH to prevent warning from gcc -Wunused-macros. */ +#ifdef NDBM_HEADER +#include NDBM_HEADER #endif -static struct swit switches[] = { -#define ADDRSW 0 - { "addr address", 0 }, -#define USERSW 1 - { "user name", 0 }, -#define FILESW 2 - { "file file", 0 }, -#define SENDERSW 3 - { "sender address", 0 }, -#define MAILBOXSW 4 - { "mailbox file", 0 }, -#define HOMESW 5 - { "home directory", -4 }, -#define INFOSW 6 - { "info data", 0 }, -#define MAILSW 7 - { "maildelivery file", 0 }, -#define VERBSW 8 - { "verbose", 0 }, -#define NVERBSW 9 - { "noverbose", 0 }, -#define SUPPRESSDUP 10 - { "suppressdup", 0 }, -#define NSUPPRESSDUP 11 - { "nosuppressdup", 0 }, -#define DEBUGSW 12 - { "debug", 0 }, -#define VERSIONSW 13 - { "version", 0 }, -#define HELPSW 14 - { "help", 0 }, - { NULL, 0 } -}; +#ifdef HAVE_GETUTXENT +#include +#endif /* HAVE_GETUTXENT */ + +#define SLOCAL_SWITCHES \ + X("addr address", 0, ADDRSW) \ + X("user name", 0, USERSW) \ + X("file file", 0, FILESW) \ + X("sender address", 0, SENDERSW) \ + X("mailbox file", 0, MAILBOXSW) \ + X("home directory", -4, HOMESW) \ + X("info data", 0, INFOSW) \ + X("maildelivery file", 0, MAILSW) \ + X("verbose", 0, VERBSW) \ + X("noverbose", 0, NVERBSW) \ + X("suppressdup", 0, SUPPRESSDUP) \ + X("nosuppressdup", 0, NSUPPRESSDUP) \ + X("debug", 0, DEBUGSW) \ + X("version", 0, VERSIONSW) \ + X("help", 0, HELPSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(SLOCAL); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(SLOCAL, switches); +#undef X static int globbed = 0; /* have we built "vars" table yet? */ static int parsed = 0; /* have we built header field table yet */ @@ -195,7 +169,7 @@ static int timely (char *, char *); static int usr_file (int, char *, int); static int usr_pipe (int, char *, char *, char **, int); static int usr_folder (int, char *); -static RETSIGTYPE alrmser (int); +static void alrmser (int); static void get_sender (char *, char **); static int copy_message (int, char *, int); static void verbose_printf (char *fmt, ...); @@ -209,19 +183,12 @@ 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; -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (*argv, '/'); - - /* foil search of user profile/context */ - if (context_foil (NULL) == -1) - done (1); + if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } mts_init (invo_name); arguments = getarguments (invo_name, argc, argv, 0); @@ -238,13 +205,12 @@ main (int argc, char **argv) adios (NULL, "-%s unknown", cp); case HELPSW: - snprintf (buf, sizeof(buf), - "%s [switches] [address info sender]", invo_name); + snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 0); - done (1); + done (0); case VERSIONSW: print_version(invo_name); - done (1); + done (0); case ADDRSW: if (!(addr = *argp++))/* allow -xyz arguments */ @@ -300,20 +266,8 @@ main (int argc, char **argv) debug++; continue; } - } - - switch (argp - (argv + 1)) { - case 1: - addr = cp; - break; - - case 2: - info = cp; - break; - - case 3: - sender = cp; - break; + } else { + adios (NULL, "only switch arguments are supported"); } } @@ -325,15 +279,21 @@ main (int argc, char **argv) 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) { - setgid (pw->pw_gid); + 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); - setuid (pw->pw_uid); + if (setuid (pw->pw_uid) != 0) { + adios ("setuid", "unable to set user to %ld", (long) pw->pw_uid); + } } - + if (info == NULL) info = ""; @@ -356,14 +316,16 @@ main (int argc, char **argv) if (debug) debug_printf ("retrieving message from file \"%s\"\n", file); if ((fd = copy_message (tempfd, tmpfil, 1)) == -1) - adios (NULL, "unable to create temporary file"); + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); close (tempfd); } else { /* getting message from stdin */ if (debug) debug_printf ("retrieving message from stdin\n"); if ((fd = copy_message (fileno (stdin), tmpfil, 1)) == -1) - adios (NULL, "unable to create temporary file"); + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); } if (debug) @@ -380,7 +342,7 @@ main (int argc, char **argv) thing would be to delay this unlink() until later if debug == 1, but I'll leave that for someone who cares about the temp-file-accessing functionality (they'll have to watch out for cases where we adios()). */ - unlink (tmpfil); + (void) m_unlink (tmpfil); if (!(fp = fdopen (fd, "r+"))) adios (NULL, "unable to access temporary file"); @@ -415,7 +377,8 @@ main (int argc, char **argv) /* deliver the message */ status = localmail (fd, mdlvr); - return done (status != -1 ? RCV_MOK : RCV_MBX); + done (status != -1 ? RCV_MOK : RCV_MBX); + return 1; } @@ -443,11 +406,7 @@ localmail (int fd, char *mdlvr) verbose_printf ("(delivering to standard mail spool)\n"); /* last resort - deliver to standard mail spool */ -#ifdef SLOCAL_MBOX return usr_file (fd, mbox, MBOX_FORMAT); -#else - return usr_file (fd, mbox, MMDF_FORMAT); -#endif } @@ -460,7 +419,7 @@ localmail (int fd, char *mdlvr) static int usr_delivery (int fd, char *delivery, int su) { - int i, accept, status, won, vecp, next; + int i, accept, status=1, won, vecp, next; char *field, *pattern, *action, *result, *string; char buffer[BUFSIZ], tmpbuf[BUFSIZ]; char *cp, *vec[NVEC]; @@ -664,6 +623,8 @@ usr_delivery (int fd, char *delivery, int su) break; } + if (status) next = 0; /* action failed, mark for 'N' result */ + if (accept && status == 0) won++; } @@ -693,7 +654,7 @@ split (char *cp, char **vec) vec[i] = NULL; /* zap any whitespace and comma's */ - while (isspace (*s) || *s == ',') + while (isspace ((unsigned char) *s) || *s == ',') *s++ = 0; /* end of buffer, time to leave */ @@ -723,7 +684,7 @@ split (char *cp, char **vec) vec[i++] = s++; /* move forward to next field delimiter */ - while (*s && !isspace (*s) && *s != ',') + while (*s && !isspace ((unsigned char) *s) && *s != ',') s++; } vec[i] = NULL; @@ -746,6 +707,7 @@ parse (int fd) char name[NAMESZ], field[BUFSIZ]; struct pair *p, *q; FILE *in; + m_getfld_state_t gstate = 0; if (parsed++) return 0; @@ -769,14 +731,15 @@ parse (int fd) * Scan the headers of the message and build * a lookup table. */ - for (i = 0, state = FLD;;) { - switch (state = m_getfld (state, name, field, sizeof(field), in)) { + for (i = 0;;) { + int fieldsz = sizeof field; + switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) { case FLD: - case FLDEOF: case FLDPLUS: lp = add (field, NULL); while (state == FLDPLUS) { - state = m_getfld (state, name, field, sizeof(field), in); + fieldsz = sizeof field; + state = m_getfld (&gstate, name, field, &fieldsz, in); lp = add (field, lp); } for (p = hdrs; p->p_name; p++) { @@ -805,12 +768,9 @@ parse (int fd) p++, i++; p->p_name = NULL; } - if (state != FLDEOF) - continue; - break; + continue; case BODY: - case BODYEOF: case FILEEOF: break; @@ -826,6 +786,7 @@ parse (int fd) } break; } + m_getfld_state_destroy (&gstate); fclose (in); if ((p = lookup (vars, "reply-to"))) { @@ -946,58 +907,31 @@ lookup (struct pair *pairs, char *key) * logged in. */ -#ifdef HAVE_GETUTENT static int logged_in (void) { - struct utmp * utp; +#if HAVE_GETUTXENT + struct utmpx *utp; if (utmped) return utmped; - setutent(); + setutxent(); - while ((utp = getutent()) != NULL) { - if (utp->ut_type == USER_PROCESS - && utp->ut_user[0] != 0 + while ((utp = getutxent()) != NULL) { + if ( utp->ut_type == USER_PROCESS && utp->ut_user[0] != 0 && strncmp (user, utp->ut_user, sizeof(utp->ut_user)) == 0) { if (debug) continue; - endutent(); + endutxent(); return (utmped = DONE); } } - endutent(); - return (utmped = NOTOK); -} -#else -static int -logged_in (void) -{ - struct utmp ut; - FILE *uf; - - if (utmped) - return utmped; - - if ((uf = fopen (UTMP_FILE, "r")) == NULL) - return NOTOK; - - while (fread ((char *) &ut, sizeof(ut), 1, uf) == 1) { - if (ut.ut_name[0] != 0 - && strncmp (user, ut.ut_name, sizeof(ut.ut_name)) == 0) { - if (debug) - continue; - fclose (uf); - return (utmped = DONE); - } - } - - fclose (uf); + endutxent(); +#endif /* HAVE_GETUTXENT */ return (utmped = NOTOK); } -#endif #define check(t,a,b) if (t < a || t > b) return -1 #define cmpar(h1,m1,h2,m2) if (h1 < h2 || (h1 == h2 && m1 < m2)) return 0 @@ -1063,7 +997,11 @@ usr_file (int fd, char *mailbox, int mbx_style) } /* close and unlock file */ - mbx_close (mailbox, md); + if (mbx_close (mailbox, md) == NOTOK) { + if (verbose) + adorn ("", "error closing:"); + return -1; + } if (verbose) verbose_printf (", success.\n"); @@ -1097,18 +1035,6 @@ usr_folder (int fd, char *string) /* use rcvstore to put message in folder */ status = usr_pipe (fd, "rcvstore", rcvstoreproc, vec, 1); -#if 0 - /* - * Currently, verbose status messages are handled by usr_pipe(). - */ - if (verbose) { - if (status == 0) - verbose_printf (", success.\n"); - else - verbose_printf (", failed.\n"); - } -#endif - return status; } @@ -1117,8 +1043,9 @@ usr_folder (int fd, char *string) */ static int -usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress) +usr_pipe (int fd_arg, char *cmd, char *pgm, char **vec, int suppress) { + volatile int fd = fd_arg; pid_t child_id; int i, bytes, seconds, status; struct stat st; @@ -1142,8 +1069,12 @@ usr_pipe (int fd, 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); @@ -1167,7 +1098,7 @@ usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress) default: /* parent process */ - if (!setjmp (myctx)) { + if (! setjmp (myctx)) { SIGNAL (SIGALRM, alrmser); bytes = fstat (fd, &st) != -1 ? (int) st.st_size : 100; @@ -1185,10 +1116,6 @@ usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress) status = pidwait (child_id, 0); alarm (0); -#ifdef MMDFI - if (status == RP_MOK || status == RP_OK) - status = 0; -#endif if (verbose) { if (status == 0) verbose_printf (", success.\n"); @@ -1204,7 +1131,7 @@ usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress) * Ruthlessly kill the child and anything * else in its process group. */ - KILLPG(child_id, SIGKILL); + killpg(child_id, SIGKILL); if (verbose) verbose_printf (", timed-out; terminated\n"); return -1; @@ -1213,12 +1140,10 @@ usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress) } -static RETSIGTYPE +static void alrmser (int i) { -#ifndef RELIABLE_SIGNALS - SIGNAL (SIGALRM, alrmser); -#endif + NMH_UNUSED (i); longjmp (myctx, DONE); } @@ -1254,7 +1179,7 @@ get_sender (char *envelope, char **sender) *cp = 0; for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) - if (isspace (*cp)) + if (isspace ((unsigned char) *cp)) *cp = 0; else break; @@ -1274,19 +1199,18 @@ copy_message (int qd, char *tmpfil, int fold) int i, first = 1, fd1, fd2; char buffer[BUFSIZ]; FILE *qfp, *ffp; + char *tfile = NULL; - strcpy (tmpfil, m_tmpfil (invo_name)); - - /* open temporary file to put message in */ - if ((fd1 = open (tmpfil, O_RDWR | O_CREAT | O_TRUNC, 0600)) == -1) - return -1; + tfile = m_mktemp2(NULL, invo_name, &fd1, NULL); + if (tfile == NULL) return -1; + strncpy (tmpfil, tfile, BUFSIZ); if (!fold) { while ((i = read (qd, buffer, sizeof(buffer))) > 0) if (write (fd1, buffer, i) != i) { you_lose: close (fd1); - unlink (tmpfil); + (void) m_unlink (tmpfil); return -1; } if (i == -1) @@ -1333,46 +1257,9 @@ you_lose: if (first) { first = 0; if (!strncmp (buffer, "From ", i)) { -#ifdef RPATHS - char *fp, *cp, *hp, *ep; -#endif /* get copy of envelope information ("From " line) */ envelope = getcpy (buffer); -#if 0 - /* First go ahead and put "From " line in message */ - fputs (buffer, ffp); - if (ferror (ffp)) - goto fputs_error; -#endif - -#ifdef RPATHS - /* - * Now create a "Return-Path:" line - * from the "From " line. - */ - hp = cp = strchr(fp = envelope + i, ' '); - while ((hp = strchr(++hp, 'r'))) - if (uprf (hp, "remote from")) { - hp = strrchr(hp, ' '); - break; - } - if (hp) { - /* return path for UUCP style addressing */ - ep = strchr(++hp, '\n'); - snprintf (buffer, sizeof(buffer), "Return-Path: %.*s!%.*s\n", - ep - hp, hp, cp - fp, fp); - } else { - /* return path for standard domain addressing */ - snprintf (buffer, sizeof(buffer), "Return-Path: %.*s\n", - cp - fp, fp); - } - - /* Add Return-Path header to message */ - fputs (buffer, ffp); - if (ferror (ffp)) - goto fputs_error; -#endif /* Put the delivery date in message */ fputs (ddate, ffp); if (ferror (ffp)) @@ -1423,12 +1310,12 @@ trim (char *cp) bp = buffer; /* skip over leading whitespace */ - while (isspace(*bp)) + while (isspace((unsigned char) *bp)) bp++; /* start at the end and zap trailing whitespace */ for (sp = bp + strlen(bp) - 1; sp >= bp; sp--) { - if (isspace(*sp)) + if (isspace((unsigned char) *sp)) *sp = 0; else break; @@ -1436,7 +1323,7 @@ trim (char *cp) /* replace remaining whitespace with spaces */ for (sp = bp; *sp; sp++) - if (isspace(*sp)) + if (isspace((unsigned char) *sp)) *sp = ' '; /* now return a copy */ @@ -1522,6 +1409,7 @@ suppress_duplicates (int fd, char *file) datum key, value; DBM *db; FILE *in; + m_getfld_state_t gstate = 0; if ((fd1 = dup (fd)) == -1) return -1; @@ -1531,22 +1419,26 @@ suppress_duplicates (int fd, char *file) } rewind (in); - for (state = FLD;;) { - state = m_getfld (state, name, buf, sizeof(buf), in); + for (;;) { + int failed_to_lock = 0; + int bufsz = sizeof buf; + state = m_getfld (&gstate, name, buf, &bufsz, in); switch (state) { case FLD: case FLDPLUS: - case FLDEOF: /* Search for the message ID */ if (strcasecmp (name, "Message-ID")) { - while (state == FLDPLUS) - state = m_getfld (state, name, buf, sizeof(buf), in); + while (state == FLDPLUS) { + bufsz = sizeof buf; + state = m_getfld (&gstate, name, buf, &bufsz, in); + } continue; } cp = add (buf, NULL); while (state == FLDPLUS) { - state = m_getfld (state, name, buf, sizeof(buf), in); + bufsz = sizeof buf; + state = m_getfld (&gstate, name, buf, &bufsz, in); cp = add (buf, cp); } key.dptr = trimcpy (cp); @@ -1566,7 +1458,8 @@ suppress_duplicates (int fd, char *file) * This will fail if your Maildelivery file doesn't * exist. */ - if ((lockfd = lkopen(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); @@ -1587,14 +1480,12 @@ suppress_duplicates (int fd, char *file) } dbm_close (db); - lkclose(lockfd, file); + lkclosedata(lockfd, file); free (cp); fclose (in); return result; - break; case BODY: - case BODYEOF: case FILEEOF: break; @@ -1606,6 +1497,7 @@ suppress_duplicates (int fd, char *file) break; } + m_getfld_state_destroy (&gstate); fclose (in); return 0;