Subject: v23i001: Deliver 2.0 patches, Part01/10 Newsgroups: comp.sources.unix Approved: rsalz@uunet.UU.NET X-Checksum-Snefru: 420a22b9 f0656c8e 50c0a7df 099b941e Submitted-by: Chip Salzenberg Posting-number: Volume 23, Issue 1 Archive-name: deliver2.0pch/part01 [ The deliver in the archives was already at patchlevel1 --r$ ] Changes in patch #2 to Deliver 2.0: 1. Normal and error logs have been added. Their names are defined by the new configuration items LOG and ERRLOG. Note that the normal log will only be written if it already exists. This feature provides a convenient way to turn off logging: rename the log file. Error logging, however, is unconditional. Thanks to Goran Larsson for this idea. 2. Deliver now tracks recursive invocations, and aborts delivery if recursion gets too deep. Also, the current recursion depth is noted in the log files and error messages. Thanks for Ron McGrath for giving me the idea by putting a similar feature in GNU Make. 3. New configuration items: UMASK File creation mask. Not to be confused with the mailbox file mode, MBX_MODE. ENV_DPID Environment variable for deliver's pid. ENV_DLEVEL Environment variable for delivery recursion level. REC_LIMIT Limit on delivery recursion. 4. A bug in the 2.0 release caused unknown users to be reported as "context lost (should never happen)". They are now correctly reported as "no such user". 5. A new flag for the "header" program: "-v" reverses the test for printing, rather like grep's -v flag. For example, "header -vnf received" prints an entire header _except_ any Received: lines. Thanks to Tom Neff . This patch contains changes to the following files: patchlevel.h Makefile config.h deliver.8 deliver.h dfile.c header.c main.c mbox.c procs.c subs.c sysdep.c unctime.y uucp.c Index: patchlevel.h Prereq: 1 *************** *** 1,1 **** ! #define PATCHLEVEL 1 --- 1,1 ---- ! #define PATCHLEVEL 2 Index: Makefile *************** *** 1,3 **** ! # $Header: Makefile,v 2.4 89/10/02 10:58:56 network Exp $ # # Makefile for deliver --- 1,3 ---- ! # $Header: Makefile,v 2.5 89/11/10 12:23:47 network Exp $ # # Makefile for deliver *************** *** 177,181 **** # ! lint: deliver.lint uid.lint deliver.lint: $(HDRS) $(DELSRCC) $(COMSRCS) --- 177,181 ---- # ! lint: deliver.lint header.lint uid.lint deliver.lint: $(HDRS) $(DELSRCC) $(COMSRCS) *************** *** 182,185 **** --- 182,188 ---- lint $(DELSRCC) $(COMSRCS) -lc $(LIBS) >$@ + header.lint: $(HDRSRCS) $(COMSRCS) + lint $(HDRSRCS) $(COMSRCS) -lc $(LIBS) >$@ + uid.lint: config.h $(UIDSRCS) $(COMSRCS) lint $(UIDSRCS) $(COMSRCS) -lc $(LIBS) >$@ Index: config.h *************** *** 1,3 **** ! /* $Header: config.h,v 2.3 89/09/29 18:16:52 network Exp $ * * Deliver configuration. --- 1,3 ---- ! /* $Header: config.h,v 2.5 89/11/10 12:23:49 network Exp $ * * Deliver configuration. *************** *** 4,7 **** --- 4,13 ---- * * $Log: config.h,v $ + * Revision 2.5 89/11/10 12:23:49 network + * Handle recursion. + * + * Revision 2.4 89/11/01 10:33:36 network + * Add UMASK, LOG, ERRLOG. + * * Revision 2.3 89/09/29 18:16:52 network * Save message when delivery file produces no output, *************** *** 194,197 **** --- 200,220 ---- /*---------------------------------------------------------------------- + * File creation mask. + * Bits turned on here are turned off in newly created files. + * This mask is the default when executing delivery files, + * but mailboxes have their own mode value (MBX_MODE). + */ + + #define UMASK 022 + + /*---------------------------------------------------------------------- + * Recursion limit. + * If Deliver detects recursion deeper than this value, + * it will assume infinite recursion and abort. + */ + + #define REC_LIMIT 8 + + /*---------------------------------------------------------------------- * Characters that may not appear in addresses. * (This string should include all metacharacters for your chosen shell.) *************** *** 253,259 **** --- 276,293 ---- /*---------------------------------------------------------------------- + * Log file names. + * Errors and warnings are output to stderr and to this file. + * To disable logging, don't define LOGFILE. + */ + + #define LOG "/usr/adm/deliver.log" + #define ERRLOG "/usr/adm/deliver.errlog" + + /*---------------------------------------------------------------------- * Environment variables passed to child processes. */ + #define ENV_DPID "DELPID" /* Deliver process id */ + #define ENV_DLEVEL "DELLEVEL" /* Level of recursion */ #define ENV_DFLAGS "DELFLAGS" /* Flags: [-[Avdt]] */ #define ENV_SYSDEL "SYSDELFILE" /* System delivery file */ Index: deliver.8 *************** *** 1,3 **** ! .\" $Header: deliver.8,v 2.2 89/10/04 10:49:10 network Exp $ .\" .\" Man page for deliver. --- 1,3 ---- ! .\" $Header: deliver.8,v 2.4 89/11/10 14:09:46 network Exp $ .\" .\" Man page for deliver. *************** *** 4,7 **** --- 4,13 ---- .\" .\" $Log: deliver.8,v $ + .\" Revision 2.4 89/11/10 14:09:46 network + .\" Document cases in which the log files are not written. + .\" + .\" Revision 2.3 89/11/10 13:34:58 network + .\" Document recursion and logging. + .\" .\" Revision 2.2 89/10/04 10:49:10 network .\" Document the "Undel.mail" and "DROP" features. *************** *** 248,251 **** --- 254,272 ---- are: .TP + .B DELPID + The process id of the running + .I deliver + process. Used by a child + .I deliver + to determine its parent's process id. + .B DELLEVEL + The + .I deliver + recursion level. Each time + .I deliver + is called recursively, this value is incremented. When the maximum + recursion level (default: eight) is exceeded, + .I deliver + assumes infinite recursion and aborts. .B DELFLAGS The command line flags, if any, specified on the *************** *** 337,340 **** --- 358,399 ---- file unless they are output by the given user's delivery file. In other words, no user can request writing a mailbox as another user. + .SH LOGGING + .I Deliver + records its activity in two files: the "delivery log", named + .IR /usr/adm/deliver.log, + and the "error log", named + .IR /usr/adm/deliver.errlog. + .PP + The deliver log is a record of activity of each + .I deliver + process. + Each delivery log entry include the users or mailboxes named on the command + line, the users and/or mailboxes where delivery succeeded, and those where + it failed. Note that + .I deliver + will write to the delivery log only if it already exists. + .PP + The error log is a record of any problems encounted during delivery. Each + error log entry includes all diagnostic output, a copy of the message + header, and other miscellaneous information that might prove helpful. + .PP + If + .I deliver + is performing a "dry run" -- that is, if the + .B \-d + (debug) or + .B \-A + (print address) flag is specified -- it will not write to either log file. + .PP + If you want a delivery log, you must create the delivery log file yourself. + If the delivery log file does not exist, + .I deliver + will not create it. + .PP + If the + .B \-v + (verbose) flag is specified, + .I deliver + will not write to the error log. .SH LOCKING Several preprocessor labels may be defined during compilation to control *************** *** 375,378 **** --- 434,441 ---- ~user/.deliver user delivery file(s) .br + /usr/adm/deliver.log delivery log + .br + /usr/adm/deliver.errlog error log + .br /etc/systemid system name (Xenix only) .SH SUPPORT Index: deliver.h *************** *** 1,3 **** ! /* $Header: deliver.h,v 2.2 89/09/29 18:17:56 network Exp $ * * General pull-it-together include file. --- 1,3 ---- ! /* $Header: deliver.h,v 2.5 89/11/10 12:23:51 network Exp $ * * General pull-it-together include file. *************** *** 4,7 **** --- 4,16 ---- * * $Log: deliver.h,v $ + * Revision 2.5 89/11/10 12:23:51 network + * Handle recursion. + * + * Revision 2.4 89/11/01 12:18:59 network + * Delintify. + * + * Revision 2.3 89/11/01 11:51:40 network + * Add logging. + * * Revision 2.2 89/09/29 18:17:56 network * Save message when delivery file produces no output, *************** *** 36,48 **** extern int leavetemps; /* Leave temp files for later perusal */ extern int boxdelivery; /* Args are mailboxes, not addresses */ - extern char *sender; /* Who is sending this message? */ extern char *progname; /* Name this program was invoked under */ ! extern char *hostname; /* Name of this host */ extern char *sys_deliver; /* Systemwide delivery file */ extern char *post_deliver; /* Post-user delivery file */ extern char *user_deliver; /* User delivery file */ ! extern char *shell; /* Shell used to run delivery files */ extern int eff_uid; /* Returned by geteuid() */ --- 45,60 ---- extern int leavetemps; /* Leave temp files for later perusal */ extern int boxdelivery; /* Args are mailboxes, not addresses */ extern char *progname; /* Name this program was invoked under */ ! extern char version[]; /* Version and patchlevel */ ! extern char *shell; /* Shell used to run delivery files */ + extern int rec_parent; /* If recursing, parent deliver's pid */ + extern int rec_level; /* If recursing, recursion level */ extern char *sys_deliver; /* Systemwide delivery file */ extern char *post_deliver; /* Post-user delivery file */ extern char *user_deliver; /* User delivery file */ ! extern char *sender; /* Who is sending this message? */ ! extern char *hostname; /* Name of this host */ extern int eff_uid; /* Returned by geteuid() */ *************** *** 57,60 **** --- 69,79 ---- extern int trust_delfiles; /* Do we trust the delivery files? */ + extern FILE *log; /* File to log deliveries */ + extern FILE *errlog; /* File to log messages and errors */ + extern int errused; /* Error log used flag */ + + extern int tty_input; /* Is our input coming from a tty? */ + extern SIGFLAG got_sig; /* Did we catch a deadly signal? */ + /* Temp file indices: */ #define T_HDR 0 /* Message header */ Index: dfile.c *************** *** 1,3 **** ! /* $Header: dfile.c,v 2.2 89/09/29 18:17:59 network Exp $ * * Filter destination(s) through delivery file(s). --- 1,3 ---- ! /* $Header: dfile.c,v 2.4 89/11/10 12:23:52 network Exp $ * * Filter destination(s) through delivery file(s). *************** *** 4,7 **** --- 4,13 ---- * * $Log: dfile.c,v $ + * Revision 2.4 89/11/10 12:23:52 network + * Be more selective about trying to deliver to MBX_UNDEL. + * + * Revision 2.3 89/11/01 12:31:11 network + * Use the new exists() function. + * * Revision 2.2 89/09/29 18:17:59 network * Save message when delivery file produces no output, *************** *** 30,34 **** char **fav; int fac, a; - struct stat st; /* --- 36,39 ---- *************** *** 36,40 **** */ ! if (stat(relpath(eff_ct->ct_home, sys_deliver), &st) == -1) { if (verbose) --- 41,45 ---- */ ! if (!exists(relpath(eff_ct->ct_home, sys_deliver))) { if (verbose) *************** *** 98,102 **** */ ! if (do_dfile(eff_ct, fav, (DEST *)NULL) <= 0) { if (verbose) --- 103,107 ---- */ ! if (do_dfile(eff_ct, fav, (DEST *)NULL) == 0) { if (verbose) *************** *** 122,126 **** char **fav; int num_dests, fac; - struct stat st; /* --- 127,130 ---- *************** *** 128,132 **** */ ! if (stat(relpath(eff_ct->ct_home, post_deliver), &st) == -1) { if (verbose) --- 132,136 ---- */ ! if (!exists(relpath(eff_ct->ct_home, post_deliver))) { if (verbose) *************** *** 179,183 **** */ ! if (do_dfile(eff_ct, fav, (DEST *)NULL) <= 0) { if (verbose) --- 183,187 ---- */ ! if (do_dfile(eff_ct, fav, (DEST *)NULL) == 0) { if (verbose) *************** *** 283,287 **** s = relpath(ct->ct_home, user_deliver); ! if (stat(s, &st) == -1) { if (verbose) --- 287,291 ---- s = relpath(ct->ct_home, user_deliver); ! if (!exists(s)) { if (verbose) *************** *** 307,311 **** fav[3] = NULL; ! if (do_dfile(ct, fav, d) <= 0) { /* --- 311,315 ---- fav[3] = NULL; ! if (do_dfile(ct, fav, d) == 0) { /* *************** *** 326,329 **** --- 330,335 ---- * Process a delivery file. * Return the count of valid destinations we got back from it. + * If delivering to MBX_UNDEL is possible, errors return zero. + * Otherwise, errors return -1. */ *************** *** 384,388 **** { error("can't execute delivery file as %s\n", ct->ct_name); ! return -1; } --- 390,394 ---- { error("can't execute delivery file as %s\n", ct->ct_name); ! return 0; } Index: header.c *************** *** 1,7 **** ! /* $Header: header.c,v 2.2 89/06/09 13:08:07 network Exp $ * * A program to parse RFC 822 mail/news headers. * ! * usage: header [-c] [-n] [-f field] ... files * * Default action is to print entire header. If one or more -f options --- 1,7 ---- ! /* $Header: header.c,v 2.5 89/11/10 12:23:54 network Exp $ * * A program to parse RFC 822 mail/news headers. * ! * usage: header [-c] [-n] [-v] [-f field] ... files * * Default action is to print entire header. If one or more -f options *************** *** 8,12 **** * are given, only the specified fields are printed. The field names are * not printed unless -n is specified. Field name comparisons are case ! * insensitive unless -c is specified. * * Output lines are preceeded by the filename if more than one file is --- 8,13 ---- * are given, only the specified fields are printed. The field names are * not printed unless -n is specified. Field name comparisons are case ! * insensitive unless -c is specified. If -v is specified, all headers ! * except those specified with -f are printed. NOTE: -v implies -n. * * Output lines are preceeded by the filename if more than one file is *************** *** 17,20 **** --- 18,31 ---- * * $Log: header.c,v $ + * Revision 2.5 89/11/10 12:23:54 network + * Delintify. + * + * Revision 2.4 89/10/30 16:08:48 network + * Don't automatically print field names with "-v". (Sorry, Tom.) + * + * Revision 2.3 89/10/30 16:03:29 network + * Add "-v" (everything except) option. + * Submitted by Tom Neff . + * * Revision 2.2 89/06/09 13:08:07 network * Adapt to BSD quirks. *************** *** 74,77 **** --- 85,89 ---- int nocasematch = TRUE; /* ignore case in header matches */ int printnames = FALSE; /* print field names with data */ + int except = FALSE; /* reverse sense of -f */ /*---------------------------------------------------------------------- *************** *** 91,95 **** errors = FALSE; ! while ((c = getopt(argc, argv, "cnf:")) != EOF) { switch (c) --- 103,107 ---- errors = FALSE; ! while ((c = getopt(argc, argv, "cnvf:")) != EOF) { switch (c) *************** *** 101,104 **** --- 113,119 ---- printnames = TRUE; break; + case 'v': + except = TRUE; + break; case 'f': if (field_count >= field_alloc) *************** *** 140,144 **** header(fp, (filenames ? argv[a] : (char *)NULL)); ! fclose(fp); } } --- 155,159 ---- header(fp, (filenames ? argv[a] : (char *)NULL)); ! (void) fclose(fp); } } *************** *** 145,148 **** --- 160,164 ---- exit(errors ? 1 : 0); + /* NOTREACHED */ } *************** *** 149,153 **** usage() { ! fprintf(stderr, "usage: header [-c] [-f fieldname] ... files\n"); exit(1); } --- 165,170 ---- usage() { ! (void) fprintf(stderr, ! "usage: header [-c] [-n] [-v] [-f fieldname] ... files\n"); exit(1); } *************** *** 155,159 **** nomem() { ! fprintf(stderr, "header: out of memory\n"); exit(1); } --- 172,176 ---- nomem() { ! (void) fprintf(stderr, "header: out of memory\n"); exit(1); } *************** *** 187,190 **** --- 204,209 ---- break; print_this = field(buf, p - buf); + if (except) + print_this = !print_this; if (print_this) { *************** *** 191,196 **** if (filename) { ! fputs(filename, stdout); ! putc(':', stdout); } ++p; --- 210,215 ---- if (filename) { ! (void) fputs(filename, stdout); ! (void) fputc(':', stdout); } ++p; *************** *** 198,204 **** ++p; if (field_count == 0 || printnames) ! fputs(buf, stdout); else ! fputs(p, stdout); } --- 217,223 ---- ++p; if (field_count == 0 || printnames) ! (void) fputs(buf, stdout); else ! (void) fputs(p, stdout); } *************** *** 214,221 **** if (filename) { ! fputs(filename, stdout); ! putc(':', stdout); } ! fputs(buf, stdout); } --- 233,240 ---- if (filename) { ! (void) fputs(filename, stdout); ! (void) fputc(':', stdout); } ! (void) fputs(buf, stdout); } Index: main.c *************** *** 1,3 **** ! /* $Header: main.c,v 2.1 89/06/09 12:25:32 network Exp $ * * A program to deliver local mail with some flexibility. --- 1,3 ---- ! /* $Header: main.c,v 2.4 89/11/10 12:23:55 network Exp $ * * A program to deliver local mail with some flexibility. *************** *** 4,7 **** --- 4,16 ---- * * $Log: main.c,v $ + * Revision 2.4 89/11/10 12:23:55 network + * Handle recursion. Enhance logging. + * + * Revision 2.3 89/11/01 12:19:02 network + * Delintify. + * + * Revision 2.2 89/11/01 11:51:47 network + * Add logging. + * * Revision 2.1 89/06/09 12:25:32 network * Update RCS revisions. *************** *** 48,51 **** --- 57,62 ---- char *shell = SHELL; + int rec_level = 0; + int rec_parent = -1; char *sys_deliver = sys_dfl; char *post_deliver = post_dfl; *************** *** 62,71 **** CONTEXT *real_ct = NULL; - int tty_input = FALSE; - SIGFLAG got_sig = FALSE; - int trust_user = FALSE; int trust_delfiles = FALSE; char *ttype[T_MAX] = { "header", "body", "header copy", "body copy" }; char *tfile[T_MAX] = { NULL, NULL, NULL, NULL }; --- 73,86 ---- CONTEXT *real_ct = NULL; int trust_user = FALSE; int trust_delfiles = FALSE; + FILE *log = NULL; + FILE *errlog = NULL; + int errused = FALSE; + + int tty_input = FALSE; + SIGFLAG got_sig = FALSE; + char *ttype[T_MAX] = { "header", "body", "header copy", "body copy" }; char *tfile[T_MAX] = { NULL, NULL, NULL, NULL }; *************** *** 88,92 **** { char *p; ! int u, c, errcount, copy; /* Make sure that stdout and stderr are interleaved correctly */ --- 103,107 ---- { char *p; ! int i, c, errcount, copy; /* Make sure that stdout and stderr are interleaved correctly */ *************** *** 99,115 **** progname = basename(argv[0]); ! /* What version of the program is this? */ ! (void) sprintf(version + strlen(version), ".%02d", PATCHLEVEL); ! /* Figure out the name of this host */ ! if ((hostname = gethost()) == NULL) { ! hostname = "unknown"; ! error("unable to determine host name; using \"%s\"\n", ! hostname); } /* Find effective and real uids and gids. */ --- 114,144 ---- progname = basename(argv[0]); ! /* Special hack -- handle the recursion level and parent first. */ ! if ((p = getenv(ENV_DLEVEL)) != NULL && (i = atoi(p)) > 0) ! rec_level = i; ! if ((p = getenv(ENV_DPID)) != NULL && (i = atoi(p)) > 0) ! rec_parent = i; ! /* If recursion level is non-zero, append it to the program name. */ ! ! if (rec_level > 0) { ! char *np; ! ! np = zalloc((unsigned) strlen(progname) + 16); ! (void) sprintf(np, "%s[%d]", progname, rec_level); ! progname = np; } + /* What version of the program is this? */ + + (void) sprintf(version + strlen(version), ".%02d", PATCHLEVEL); + + /* Let's be sane about the file creation mask. */ + + (void) umask(UMASK); + /* Find effective and real uids and gids. */ *************** *** 119,122 **** --- 148,153 ---- real_gid = getgid(); + /* Make sure that setuidness is reasonable. */ + if (eff_uid != real_uid && eff_uid != 0) { *************** *** 125,129 **** } ! /* Process environment: handle recursive invocation */ if ((p = getenv(ENV_DFLAGS)) != NULL) --- 156,160 ---- } ! /* Process environment: handle recursive invocation. */ if ((p = getenv(ENV_DFLAGS)) != NULL) *************** *** 216,219 **** --- 247,264 ---- } + #ifdef LOG + /* If we're delivering and the log file exists, open it. */ + + if (!dryrun && exists(LOG)) + log = fopen(LOG, "a"); + #endif + + #ifdef ERRLOG + /* If we're delivering and not being verbose, open the error log. */ + + if (!dryrun && !verbose) + errlog = fopen(ERRLOG, "a"); + #endif + /* If no destinations were given, forget it. */ *************** *** 224,227 **** --- 269,281 ---- } + /* Figure out the name of this host */ + + if ((hostname = gethost()) == NULL) + { + hostname = "unknown"; + error("unable to determine host name; using \"%s\"\n", + hostname); + } + /* Print a debugging message */ *************** *** 274,284 **** } - /* Let's be sane about the file creation mask. */ - - u = umask(0); - u &= ~0700; /* Let's not deprive ourselves of permissions. */ - u |= 022; /* Let's be reasonably paranoid about writing. */ - (void) umask(u); - /* * Where is the message coming from? --- 328,331 ---- *************** *** 332,340 **** /* ! * Perhaps we should consider all arguments as mailbox names... */ ! if (boxdelivery) { int a; --- 379,399 ---- /* ! * If recursion is too deep, consider mail undeliverable. */ ! if (rec_level > REC_LIMIT) { + error("recursion limit (%d) exceeded; writing to %s:%s", + REC_LIMIT, eff_ct->ct_name, MBX_UNDEL); + + (void) dest(eff_ct->ct_name, MBX_UNDEL); + } + + /* + * Else, if all arguments are mailbox names... + */ + + else if (boxdelivery) + { int a; *************** *** 354,358 **** /* ! * They're not mailbox names, so they should be mail addresses. */ --- 413,417 ---- /* ! * Else, arguments are addresses. */ *************** *** 423,429 **** /* ! * Report any errors, and leave. */ errcount = report_errors(); --- 482,495 ---- /* ! * Report all results in log file. */ + if (log) + logreport(argc - optind, argv + optind); + + /* + * Report any errors. + */ + errcount = report_errors(); *************** *** 466,469 **** --- 532,537 ---- int code; { + errinfo(); + if (! leavetemps) { *************** *** 479,482 **** --- 547,552 ---- } + errend(); + exit(code); } *************** *** 529,532 **** --- 599,661 ---- /*---------------------------------------------------------------------- + * Write a report to the log file. + */ + + logreport(ac, av) + int ac; + char **av; + { + int a; + + if (!log) + return; + + timestamp(log); + + if (sender && *sender) + (void) fprintf(log, "sender: %s\n", sender); + if (boxdelivery) + (void) fprintf(log, "mailbox%s:", (ac > 1) ? "es" : ""); + else + (void) fprintf(log, "destination%s:", (ac > 1) ? "s" : ""); + for (a = 0; a < ac; ++a) + (void) fprintf(log, " \"%s\"", av[a]); + (void) fputc('\n', log); + + logstate("delivered", ST_DONE); + logstate("failed", ST_ERROR); + + (void) fflush(log); + } + + /*---------------------------------------------------------------------- + * Log the destinations with the given state. + * If any are found, the list is prefixed with the given description. + */ + + logstate(desc, state) + char *desc; + DSTATE state; + { + DEST *d; + int count; + + count = 0; + for (d = first_dest(); d; d = next_dest(d)) + { + if (d->d_state != state) + continue; + + if (++count == 1) + (void) fprintf(log, "%s:", desc); + (void) fprintf(log, " %s", d->d_name); + if (d->d_mailbox) + (void) fprintf(log, ":%s", d->d_mailbox); + } + if (count) + (void) fputc('\n', log); + } + + /*---------------------------------------------------------------------- * Report any errors to stderr. * Return an error count. *************** *** 547,551 **** { error( ! "delivery to the following address(es) failed on host %s\n", hostname); } --- 676,680 ---- { error( ! "delivery to the following address(es) failed on host %s:\n", hostname); } *************** *** 587,603 **** setup_environ() { ! char flags[8]; int f = 0; ! flags[f++] = '-'; if (verbose) ! flags[f++] = (dryrun ? 'd' : 'v'); if (printaddrs) ! flags[f++] = 'A'; if (leavetemps) ! flags[f++] = 't'; ! flags[f] = 0; - alloc_env(ENV_DFLAGS, (f > 1) ? flags : ""); if (sys_deliver && *sys_deliver) alloc_env(ENV_SYSDEL, sys_deliver); --- 716,738 ---- setup_environ() { ! char s[8]; int f = 0; ! (void) sprintf(s, "%d", getpid()); ! alloc_env(ENV_DPID, s); ! ! (void) sprintf(s, "%d", rec_level + 1); ! alloc_env(ENV_DLEVEL, s); ! ! s[f++] = '-'; if (verbose) ! s[f++] = (dryrun ? 'd' : 'v'); if (printaddrs) ! s[f++] = 'A'; if (leavetemps) ! s[f++] = 't'; ! s[f] = 0; ! alloc_env(ENV_DFLAGS, (f > 1) ? s : ""); if (sys_deliver && *sys_deliver) alloc_env(ENV_SYSDEL, sys_deliver); Index: mbox.c *************** *** 1,3 **** ! /* $Header: mbox.c,v 2.1 89/06/09 12:25:33 network Exp $ * * Finally! Put the message in the specified mailbox(es). --- 1,3 ---- ! /* $Header: mbox.c,v 2.2 89/11/01 11:51:05 network Exp $ * * Finally! Put the message in the specified mailbox(es). *************** *** 4,7 **** --- 4,10 ---- * * $Log: mbox.c,v $ + * Revision 2.2 89/11/01 11:51:05 network + * Fix error code; unknown user is now reported correctly. + * * Revision 2.1 89/06/09 12:25:33 network * Update RCS revisions. *************** *** 77,81 **** if ((ct = name_context(d->d_name)) == NULL) { ! dest_err(d, E_CTLOST); return; } --- 80,84 ---- if ((ct = name_context(d->d_name)) == NULL) { ! dest_err(d, E_NSUSER); return; } Index: procs.c *************** *** 1,3 **** ! /* $Header: procs.c,v 2.2 89/09/29 18:18:03 network Exp $ * * Process management and misc support. --- 1,3 ---- ! /* $Header: procs.c,v 2.4 89/11/01 12:19:05 network Exp $ * * Process management and misc support. *************** *** 4,7 **** --- 4,13 ---- * * $Log: procs.c,v $ + * Revision 2.4 89/11/01 12:19:05 network + * Delintify. + * + * Revision 2.3 89/11/01 11:51:50 network + * Add logging. + * * Revision 2.2 89/09/29 18:18:03 network * Save message when delivery file produces no output, *************** *** 132,135 **** --- 138,145 ---- for (t = 0; t < T_MAX; ++t) (void) close(tfd[t]); + if (log) + (void) fclose(log); + if (errlog) + (void) fclose(errlog); (void) execv(prog, av); *************** *** 233,236 **** --- 243,250 ---- (void) fflush(stdout); (void) fflush(stderr); + if (log) + (void) fflush(log); + if (errlog) + (void) fflush(errlog); /* Index: subs.c *************** *** 1,3 **** ! /* $Header: subs.c,v 2.2 89/09/29 18:18:05 network Exp $ * * Miscellaneous subroutines. --- 1,3 ---- ! /* $Header: subs.c,v 2.3 89/11/01 10:37:58 network Exp $ * * Miscellaneous subroutines. *************** *** 4,7 **** --- 4,10 ---- * * $Log: subs.c,v $ + * Revision 2.3 89/11/01 10:37:58 network + * Add exists() function. + * * Revision 2.2 89/09/29 18:18:05 network * Save message when delivery file produces no output, *************** *** 18,23 **** --- 21,40 ---- #include "deliver.h" + #include /*---------------------------------------------------------------------- + * Report as to whether a file exists or not. + */ + + int + exists(path) + char *path; + { + struct stat st; + + return (stat(path, &st) == 0); + } + + /*---------------------------------------------------------------------- * Allocate memory for an environment variable, and putenv() it. */ Index: sysdep.c *************** *** 1,3 **** ! /* $Header: sysdep.c,v 2.1 89/06/09 12:25:40 network Exp $ * * Routines which are (or might well be) system-dependant. --- 1,3 ---- ! /* $Header: sysdep.c,v 2.4 89/11/10 12:23:58 network Exp $ * * Routines which are (or might well be) system-dependant. *************** *** 6,9 **** --- 6,18 ---- * * $Log: sysdep.c,v $ + * Revision 2.4 89/11/10 12:23:58 network + * Log recursion depth, undelivered mail and failed headers. + * + * Revision 2.3 89/11/01 12:19:06 network + * Delintify. + * + * Revision 2.2 89/11/01 11:51:51 network + * Add logging. + * * Revision 2.1 89/06/09 12:25:40 network * Update RCS revisions. *************** *** 16,19 **** --- 25,29 ---- #include "deliver.h" #include + #include #ifdef HAS_STDARG #include *************** *** 57,84 **** extern char *sys_errlist[]; ! /*---------------------------------------------------------------------- ! * Print a message. */ ! /* VARARGS */ ! #ifdef HAS_STDARG ! message(char *fmt, ...) ! #else ! message(va_alist) va_dcl ! #endif ! { ! va_list ap; #ifdef HAS_STDARG ! va_start(ap, fmt); #else ! char *fmt; ! va_start(ap); ! fmt = va_arg(ap, char *); #endif (void) vfprintf(stderr, fmt, ap); ! va_end(ap); } --- 67,109 ---- extern char *sys_errlist[]; ! /* ! * Locally useful macros. */ ! /* Wrapper macros to hide stdarg/vararg differences. */ #ifdef HAS_STDARG ! #define FMT_PARAM (char *fmt, ...) ! #define FMT_VARS va_list ap; ! #define FMT_START va_start(ap, fmt); ! #define FMT_END va_end(ap); #else ! #define FMT_PARAM (va_alist) va_dcl ! #define FMT_VARS va_list ap; char *fmt; ! #define FMT_START va_start(ap); fmt = va_arg(ap, char *); ! #define FMT_END va_end(ap); #endif + /*---------------------------------------------------------------------- + * Print a message. + */ + + /* VARARGS */ + message + FMT_PARAM + { + FMT_VARS + + FMT_START (void) vfprintf(stderr, fmt, ap); + FMT_END ! if (errlog) ! { ! errstart(); ! FMT_START ! (void) vfprintf(errlog, fmt, ap); ! FMT_END ! } } *************** *** 88,111 **** /* VARARGS */ ! #ifdef HAS_STDARG ! error(char *fmt, ...) ! #else ! error(va_alist) va_dcl ! #endif { ! va_list ap; ! #ifdef HAS_STDARG ! va_start(ap, fmt); ! #else ! char *fmt; ! va_start(ap); ! fmt = va_arg(ap, char *); ! #endif ! (void) fprintf(stderr, "%s: ", progname); (void) vfprintf(stderr, fmt, ap); ! va_end(ap); } --- 113,134 ---- /* VARARGS */ ! error ! FMT_PARAM { ! FMT_VARS ! FMT_START (void) fprintf(stderr, "%s: ", progname); (void) vfprintf(stderr, fmt, ap); + FMT_END ! if (errlog) ! { ! errstart(); ! FMT_START ! (void) fprintf(errlog, "%s: ", progname); ! (void) vfprintf(errlog, fmt, ap); ! FMT_END ! } } *************** *** 115,146 **** /* VARARGS */ ! #ifdef HAS_STDARG ! syserr(char *fmt, ...) ! #else ! syserr(va_alist) va_dcl ! #endif { int e = errno; ! va_list ap; ! #ifdef HAS_STDARG ! va_start(ap, fmt); ! #else ! char *fmt; ! va_start(ap); ! fmt = va_arg(ap, char *); ! #endif ! (void) fprintf(stderr, "%s: ", progname); ! (void) vfprintf(stderr, fmt, ap); if (e <= sys_nerr) ! (void) fprintf(stderr, ": %s\n", sys_errlist[e]); else ! (void) fprintf(stderr, ": unknown system error %d\n", e); ! va_end(ap); } /*---------------------------------------------------------------------- * Sleep for the given number of seconds. */ --- 138,355 ---- /* VARARGS */ ! syserr ! FMT_PARAM { int e = errno; ! FMT_VARS ! FMT_START (void) fprintf(stderr, "%s: ", progname); ! vsyserr(stderr, fmt, ap, e); ! FMT_END ! ! if (errlog) ! { ! errstart(); ! FMT_START ! (void) fprintf(errlog, "%s: ", progname); ! vsyserr(errlog, fmt, ap, e); ! FMT_END ! } ! } ! ! vsyserr(fp, fmt, ap, e) ! FILE *fp; ! char *fmt; ! va_list ap; ! int e; ! { ! (void) vfprintf(fp, fmt, ap); if (e <= sys_nerr) ! (void) fprintf(fp, ": %s\n", sys_errlist[e]); else ! (void) fprintf(fp, ": unknown system error %d\n", e); ! } ! /*---------------------------------------------------------------------- ! * Record any interesting information in the error log file. ! */ ! ! errinfo() ! { ! if (!errlog) ! return; ! ! /* Log undelivered mail. */ ! ! errundel(); ! ! /* If any errors have been logged, record the failed header. */ ! ! if (errused) ! errheader(); } /*---------------------------------------------------------------------- + * Log undelivered mail. + * + * Note that this algorithm assumes that delivery to the MBX_UNDEL mailbox + * is always worth reporting. + */ + + errundel() + { + DEST *d; + + if (!errlog) + return; + + for (d = first_dest(); d; d = next_dest(d)) + { + if (d->d_state == ST_DONE + && d->d_class == CL_MBOX + && strcmp(d->d_mailbox, MBX_UNDEL) == 0) + { + CONTEXT *ct; + char *home; + + if ((ct = name_context(d->d_name)) != NULL) + home = ct->ct_home; + else + home = "~"; /* should never happen */ + + errstart(); + (void) fprintf(errlog, + "Undelivered mail for %s put in %s/%s\n", + d->d_name, home, MBX_UNDEL); + } + } + } + + /*---------------------------------------------------------------------- + * Log the message header. + */ + + errheader() + { + FILE *hfp; + int hfd; + + if (!errlog) + return; + + /* Copy the failed message's header. */ + + hfd = dup(tfd[T_HDR]); + hfp = (hfd < 0) ? NULL : fdopen(hfd, "r"); + if (hfp == NULL) + { + (void) fprintf(errlog, "%s: can't open header file %s\n", + progname, tfile[T_HDR]); + } + else + { + int c, oc; + + (void) fprintf(errlog, "+ Header:\n"); + + (void) fseek(hfp, 0L, 0); + oc = '\n'; + while ((c = getc(hfp)) != EOF) + { + if (oc != '\n' || c != '\n') + { + if (oc == '\n') + (void) fputs("| ", errlog); + (void) putc(c, errlog); + } + oc = c; + } + + (void) fclose(hfp); + } + } + + /*---------------------------------------------------------------------- + * Record a time stamp in the error log file. + */ + + errstart() + { + /* For the sake of V7, manually seek to EOF. */ + + (void) fseek(errlog, 0L, 2); + + /* If we've already written a time stamp, don't do it again. */ + + if (errused) + return; + + /* Write a time stamp and various useful info. */ + + timestamp(errlog); + (void) fprintf(errlog, "process %d", getpid()); + if (rec_parent > 0) + (void) fprintf(errlog, ", parent %d", rec_parent); + (void) fprintf(errlog, ": %s %s\n", progname, version); + + /* Remember that we've written the time stamp. */ + + errused = TRUE; + } + + /*---------------------------------------------------------------------- + * Record the end of this process's error log entry. + */ + + errend() + { + /* If we never wrote to the error log file, do nothing. */ + + if (!errused) + return; + + /* Write a simple closing line for the error log entry. */ + + (void) fprintf(errlog, "process %d", getpid()); + if (rec_parent > 0) + (void) fprintf(errlog, ", parent %d", rec_parent); + (void) fprintf(errlog, ": exit\n"); + (void) fflush(errlog); + } + + /*---------------------------------------------------------------------- + * Write a timestamp to the given file. + */ + + timestamp(fp) + FILE *fp; + { + struct tm *lt; + time_t now; + static char month[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + + (void) time(&now); + lt = localtime(&now); + + (void) fputc('\n', fp); + if (rec_level) + (void) fprintf(fp, "[%d]", rec_level); + (void) fputs("======================== ", fp); + (void) fprintf(fp, "%d %s %d, %02d:%02d:%02d %s\n", + lt->tm_mday, month[lt->tm_mon], lt->tm_year + 1900, + lt->tm_hour, lt->tm_min, lt->tm_sec, + #ifdef LTZNMAX + lt->tm_name + #else + lt->tm_zone + #endif + ); + } + + /*---------------------------------------------------------------------- * Sleep for the given number of seconds. */ Index: unctime.y *************** *** 1,4 **** /* ! * $Header: unctime.y,v 2.1 89/06/09 12:25:42 network Exp $ * * Conversion of ctime-style date string back to a time_t. --- 1,4 ---- /* ! * $Header: unctime.y,v 2.2 89/10/31 12:15:45 network Exp $ * * Conversion of ctime-style date string back to a time_t. *************** *** 7,10 **** --- 7,13 ---- * * $Log: unctime.y,v $ + * Revision 2.2 89/10/31 12:15:45 network + * Fix erroneous cast in BSD-specific code. + * * Revision 2.1 89/06/09 12:25:42 network * Update RCS revisions. *************** *** 463,467 **** /* The cast is required to shut lint up. Berkeley goes to all the effort to define time_t, why don't they use it? */ ! tm = localtime(&(time_t) tv.tv_sec); #else (void) time(&now); --- 466,470 ---- /* The cast is required to shut lint up. Berkeley goes to all the effort to define time_t, why don't they use it? */ ! tm = localtime((time_t *) &tv.tv_sec); #else (void) time(&now); Index: uucp.c *************** *** 1,3 **** ! /* $Header: uucp.c,v 2.1 89/06/09 12:25:44 network Exp $ * * Handle mail destined for other hosts via UUCP. --- 1,3 ---- ! /* $Header: uucp.c,v 2.2 89/11/01 12:31:17 network Exp $ * * Handle mail destined for other hosts via UUCP. *************** *** 6,9 **** --- 6,12 ---- * * $Log: uucp.c,v $ + * Revision 2.2 89/11/01 12:31:17 network + * Use the new exists() function. + * * Revision 2.1 89/06/09 12:25:44 network * Update RCS revisions. *************** *** 15,19 **** #include "deliver.h" - #include /* --- 18,21 ---- *************** *** 30,34 **** uucp_deliver() { - struct stat st; DEST *d; char *uux; --- 32,35 ---- *************** *** 36,42 **** static char uux2[] = "/usr/bin/uux"; ! if (stat(uux1, &st) == 0) uux = uux1; ! else if (stat(uux2, &st) == 0) uux = uux2; else --- 37,43 ---- static char uux2[] = "/usr/bin/uux"; ! if (exists(uux1)) uux = uux1; ! else if (exists(uux2)) uux = uux2; else exit 0 # Just in case...