chip@ateng.ateng.com (Chip Salzenberg) (11/29/88)
This is an offical patch for deliver 1.00. Please apply it. Patch number: 1 Date: 13 Oct 1988 Priority: MEDIUM Changes: A new command line option "-n" allows delivery to users' default mailboxes without executing any delivery files. This option is very useful for invoking deliver recursively -- that is, when deliver is called in a delivery file. Also, miscellaneous bug fixes, especially in message output. Index: patchlevel.h Prereq: 0 *************** *** 1 **** ! #define PATCHLEVEL 0 --- 1 ---- ! #define PATCHLEVEL 1 Index: deliver.8 *************** *** 1,8 **** ! .\" $Header: deliver.8,v 1.3 88/09/14 19:41:44 network Exp $ .\" .\" Man page for deliver. .\" .\" $Log: deliver.8,v $ .\" Revision 1.3 88/09/14 19:41:44 network .\" Portability to System V and BSD. .\" General fixup. --- 1,14 ---- ! .\" $Header: deliver.8,v 1.5 88/10/13 13:44:03 network Exp $ .\" .\" Man page for deliver. .\" .\" $Log: deliver.8,v $ + .\" Revision 1.5 88/10/13 13:44:03 network + .\" patch1: rework the whole man page. + .\" + .\" Revision 1.4 88/10/13 12:18:43 network + .\" patch1: add "-n" option, and general bug fixes. + .\" .\" Revision 1.3 88/09/14 19:41:44 network .\" Portability to System V and BSD. .\" General fixup. *************** *** 25,102 **** The .I deliver program collects a mail message from the standard input and delivers it. ! It is intended to take over the delivery of all local mail, a job which ! is usually handled by .I /bin/mail ! (that's .I /usr/lib/mail/mail.local ! on Xenix systems). .PP - A mail system which uses .I deliver ! becomes very flexible in its handling of local mail delivery. All files used to control .I deliver ! are shell scripts. Thus anything you can express in a shell script can ! be used to control mail delivery. ! .PP ! .I deliver ! was designed for use in two environments. If your Unix system uses ! .I smail(8) ! to handle incoming mail, then you can change the LMAIL macro to call ! .I deliver. ! Or, if you have a Xenix system, ! .I deliver ! can be used as a direct replacement for ! .IR /usr/lib/mail/mail.local. ! (If you are using ! .I smail ! under Xenix, either of these approaches will work.) ! .I deliver ! can also be used with ! .I sendmail ! or ! .I smail ! version 3, through the use of ! .I .forward ! files. ! .PP ! By default, ! .I deliver ! deposits mail in the system mailbox for the named user(s). However, ! .I deliver ! is useful specifically because of its ability to vary its behavior ! depending on the recipient(s) and content of mail messages. ! .PP ! When ! .I deliver ! starts execution, it interprets its arguments in one of three ways. If the ! .B \-b ! (mailbox) option was specified, then all arguments are interpreted as ! mailbox pathnames. Otherwise, if a system delivery file exists, ! .I deliver ! executes it with all of deliver's arguments, interpreting the output as ! described below; this procedure gives the postmaster control over delivery ! to non-existent user names. If ! .I deliver ! cannot find a system delivery file, it interprets all its arguments as ! user names. ! .PP ! After executing the system delivery file (if any), ! .I deliver ! looks in its list of destinations for valid user names without explicitly ! named mailboxes. If any of those users have user delivery files in their ! home directories, ! .I deliver ! executes each delivery file with the name of the user for its only argument. ! .bp .SH OPTIONS .TP .B \-b ! Interpret all arguments as mailboxes instead of addresses. .TP .B \-A ! Print the resolved addresses; don't deliver to any mailboxes. Note that .I deliver still collects a message from the standard input, since delivery files may do different things depending on message content. For simple testing, --- 31,70 ---- The .I deliver program collects a mail message from the standard input and delivers it. ! It is intended to take over the delivery of all local mail, a job usually ! handled by .I /bin/mail ! (System V), ! .I /usr/lib/sendmail ! (BSD), or .I /usr/lib/mail/mail.local ! (Xenix). .PP .I deliver ! introduces flexibility in the handling of local mail delivery. All files used to control .I deliver ! are Bourne shell scripts. Thus anything that can be called by a shell ! script can be used to control mail delivery. .SH OPTIONS .TP .B \-b ! Interpret all arguments as mailbox filenames instead of addresses. Note ! that the user running ! .I deliver ! must have write permissions on the given mailbox files. He may also need ! write permissions on their parent directories, depending on the existence ! of the mailbox file and the local locking protocol. .TP + .B \-n + Interpret arguments as addresses, but do not run any delivery files; simply + deliver the message to the mailbox(es) of the given user(s). This option is + most useful when + .I deliver + is executed recursively, since it prevents further recursion. + .TP .B \-A ! Print resolved addresses; do not deliver the message. Note that .I deliver still collects a message from the standard input, since delivery files may do different things depending on message content. For simple testing, *************** *** 132,144 **** (in each user's home directory). For security reasons, this option disables setuid privileges. .PP ! All command line options are put into environment variables, which .I deliver ! examines on startup; thus all flags are propagated when .I deliver is invoked recursively. ! .bp ! .SH DELIVERY FILES Delivery files are shell scripts. They are executed by .I deliver to control delivery to users. Note that delivery files do --- 100,189 ---- (in each user's home directory). For security reasons, this option disables setuid privileges. .PP ! All command line options are put into environment variables, examined by .I deliver ! on startup; thus all flags are propagated when .I deliver is invoked recursively. ! .SH ENVIRONMENT ! For mail systems based on ! .I smail ! 2.x, the LMAIL (local mailer) macro can be changed to call ! .I deliver. ! For mail systems based on ! .I smail ! 3.x or ! .I sendmail, ! a similar arrangement may be made; or individual users can invoke ! .I deliver ! by mentioning it in their ! .I .forward ! files. ! .PP ! For Xenix systems, ! .I deliver ! may be used as a direct replacement for ! .IR /usr/lib/mail/mail.local. ! .PP ! For stock Unix systems, it may be possible to make ! .I /bin/rmail ! a link to ! .I deliver; ! however, this configuration has not been tested and is not recommended. ! Any postmaster motivated enough to install ! .I deliver, ! and who wants something better than the standard ! .I /bin/rmail, ! should install ! .I smail. ! .SH OPERATION ! By default, ! .I deliver ! deposits mail in the system mailbox for the named user(s). Also, as a ! necessity for use with ! .I smail ! 2.x, ! .I deliver ! also understands UUCP-style bang addresses well enough to forward the ! message correctly, using ! .I uux. ! .PP ! However, this basic behavior only scratches the surface: the usefulness of ! .I deliver ! derives from its flexibility; its behavior can be made to depend on the ! recipient(s), content or any other aspect of mail messages. ! .PP ! When ! .I deliver ! starts execution, it interprets its arguments in one of three ways. If the ! .B \-b ! (mailbox) option was specified, then all arguments are interpreted as ! mailbox pathnames. Otherwise, if a system delivery file exists and the ! .B \-n ! (no delivery files) option was not specified, ! .I deliver ! executes the system delivery file with all of deliver's arguments ! as its arguments. ! .I deliver ! interprets the delivery file's output as described below. This procedure ! gives the postmaster control over delivery to non-existent hosts and users. ! If the ! .B \-n ! option is specified or if there is no system delivery file, ! .I deliver ! interprets all its arguments as mail addresses. ! .PP ! After possibly executing the system delivery file, ! .I deliver ! looks in its list of destinations for valid user names without explicitly ! named mailboxes. If any of the named users have user delivery files in ! their home directories, and if the ! .B \-n ! option was not specified, ! .I deliver ! executes each user delivery file with the name of the given user as its ! only argument. ! .SH "DELIVERY FILES" Delivery files are shell scripts. They are executed by .I deliver to control delivery to users. Note that delivery files do *************** *** 159,164 **** --- 204,224 ---- one argument: the name of the user in whose home directory the file is found. .PP + Recursive execution of + .I deliver + is useful, especially with the + .B \-b + (mailbox) and + .B \-n + (no delivery files) flags. For example, a user may wish to transform a + message body before it is stored in a mailbox. This may be done with a user + delivery file and recursive execution of + .I deliver. + For example, the following user delivery file translates all incoming + message bodies to lower case, and stores them in the user's default mailbox: + .TP + (cat $HEADER; tr '[A-Z]' '[a-z]' <$BODY) | deliver -n "$1" + .PP When .I deliver executes a delivery file, it sets several environment variables, listed *************** *** 167,177 **** .I deliver; therefore, all command line options automatically propagate when .I deliver ! is run recursively (within a delivery file). Recursive execution of .I deliver ! is quite useful, especially with the ! .B \-b ! (mailbox) flag. .TP .B DELFLAGS The command line flags, if any, specified on the --- 227,236 ---- .I deliver; therefore, all command line options automatically propagate when .I deliver ! is run recursively (within a delivery file). The environment variable ! names set and used by .I deliver ! are: .TP .B DELFLAGS The command line flags, if any, specified on the *************** *** 185,191 **** The user delivery filename. .TP .B HOSTNAME ! The local host name, either the actual hostname or a name specified with the .B \-h option to .I deliver. --- 244,250 ---- The user delivery filename. .TP .B HOSTNAME ! The local host name, either the real hostname or a name specified with the .B \-h option to .I deliver. *************** *** 216,229 **** When .I deliver executes a delivery file, it expects that delivery file to explicitly name ! all users (and, optionally, mailboxes) which should receive the message. ! If a delivery file does not name any users in its output, then the message ! will not be delivered to anyone whose mail delivery is controlled by that ! delivery file. .PP ! Therefore, a user delivery file which contains only "exit" will keep the ! given user from receiving any mail. A system delivery file which contains ! only "exit" will cause .B all mail to disappear. So be careful! .PP --- 275,288 ---- When .I deliver executes a delivery file, it expects that delivery file to explicitly name ! all users (and, optionally, mailboxes) where the message should be ! delivered. If a delivery file does not name any users in its output, then ! the message will not be delivered to anyone whose mail delivery is ! controlled by that delivery file. .PP ! Therefore, a user delivery file containing only "exit" will keep the given ! user from receiving any mail. A system delivery file containing only "exit" ! will cause .B all mail to disappear. So be careful! .PP *************** *** 232,240 **** .I deliver is setuid root -- which it should be for normal operation -- then the system delivery file is executed as root. Be ! .I very careful ! about its permissions and its contents! If you are not careful, it can ! easily become a security hole. .PP .B NOTE 3: All user delivery files are executed in the context of the user in whose --- 291,299 ---- .I deliver is setuid root -- which it should be for normal operation -- then the system delivery file is executed as root. Be ! .I "very careful" ! about its permissions and its contents! Carelessness here can easily ! create a security problem. .PP .B NOTE 3: All user delivery files are executed in the context of the user in whose *************** *** 290,302 **** .br /etc/systemid system name (Xenix only) .SH SUPPORT ! Enhancements, enhancement requests, trouble reports, etc., ! should be sent to ! .sp ! .ce ! bugs-deliver@ateng.UUCP. ! .sp .SH "SEE ALSO" .IR uux (1), .IR smail (8), ! .IR mail (1) --- 349,359 ---- .br /etc/systemid system name (Xenix only) .SH SUPPORT ! Enhancements, enhancement requests, trouble reports, etc., should be mailed ! to <bugs-deliver@ateng.com>; or for UUCP-only sites, ! <uunet!ateng!bugs-deliver>. .SH "SEE ALSO" + .IR mail (1), .IR uux (1), .IR smail (8), ! .IR sendmail (8) Index: deliver.h *************** *** 1,8 **** ! /* $Header: deliver.h,v 1.3 88/09/14 19:41:50 network Exp $ * * General pull-it-together include file. * * $Log: deliver.h,v $ * Revision 1.3 88/09/14 19:41:50 network * Portability to System V and BSD. * General fixup. --- 1,11 ---- ! /* $Header: deliver.h,v 1.4 88/10/13 12:19:18 network Exp $ * * General pull-it-together include file. * * $Log: deliver.h,v $ + * Revision 1.4 88/10/13 12:19:18 network + * patch1: add "-n" option, and general bug fixes. + * * Revision 1.3 88/09/14 19:41:50 network * Portability to System V and BSD. * General fixup. *************** *** 30,35 **** --- 33,39 ---- extern int verbose; /* Print debugging messages? */ extern int dryrun; /* Are we making a dry run? */ + extern int rundfiles; /* Run delivery files at all? */ extern int printaddrs; /* Address resolution only? */ extern int leavetemps; /* Leave temp files for later perusal */ extern int boxdelivery; /* Args are mailboxes, not addresses */ Index: dfile.c *************** *** 1,8 **** ! /* $Header: dfile.c,v 1.2 88/08/25 15:23:56 network Exp $ * * Filter destination(s) through delivery file(s). * * $Log: dfile.c,v $ * Revision 1.2 88/08/25 15:23:56 network * Add third parameter to do_dfile(), so that if the delivery file cannot * be executed, the given destination can be recorded as an error. --- 1,11 ---- ! /* $Header: dfile.c,v 1.3 88/10/13 12:19:22 network Exp $ * * Filter destination(s) through delivery file(s). * * $Log: dfile.c,v $ + * Revision 1.3 88/10/13 12:19:22 network + * patch1: add "-n" option, and general bug fixes. + * * Revision 1.2 88/08/25 15:23:56 network * Add third parameter to do_dfile(), so that if the delivery file cannot * be executed, the given destination can be recorded as an error. *************** *** 29,47 **** struct stat st; /* ! * If there is no global delivery file, then take all the named ! * addresses verbatim and return. */ if (stat(sys_deliver, &st) == -1) { if (verbose) ! message("%s: no system delivery file\n", ! progname); ! for (a = 0; a < dac; ++a) ! (void) dest(dav[a], (char *) NULL); ! return; } /* --- 32,58 ---- struct stat st; /* ! * If we've been asked not to run delivery files, forget it. */ + if (!rundfiles) + { + if (verbose) + message("system delivery file disabled\n"); + + return -1; + } + + /* + * If there is no global delivery file, forget it. + */ + if (stat(sys_deliver, &st) == -1) { if (verbose) ! message("no system delivery file\n"); ! return -1; } /* *************** *** 94,99 **** --- 105,112 ---- (void) do_dfile(eff_ct, fav, (DEST *)NULL); free((char *) fav); + + return 0; } /*---------------------------------------------------------------------- *************** *** 106,111 **** --- 119,137 ---- int nfound; /* + * If we've been asked not to run delivery files, forget it. + */ + + if (!rundfiles) + { + if (verbose) + message("user delivery files disabled\n"); + + return -1; + } + + + /* * Continue to loop through all addresses until no destination * that needs expanding can be found. */ *************** *** 123,128 **** --- 149,156 ---- } } } while (nfound > 0); + + return 0; } /*---------------------------------------------------------------------- *************** *** 155,161 **** || (st.st_mode & S_IFMT) != S_IFDIR) { if (verbose) ! message("%s: home directory %s is missing!\n", ct->name, ct->home); return; } --- 183,189 ---- || (st.st_mode & S_IFMT) != S_IFDIR) { if (verbose) ! message("user %s: home directory %s is missing!\n", ct->name, ct->home); return; } *************** *** 163,169 **** if (st.st_mode & 02) { if (verbose) ! message("%s: home directory is writable to the world!\n", ct->name); return; } --- 191,197 ---- if (st.st_mode & 02) { if (verbose) ! message("user %s: home directory is writable to the world!\n", ct->name); return; } Index: main.c *************** *** 1,8 **** ! /* $Header: main.c,v 1.5 88/09/14 20:00:03 network Exp $ * * A program to deliver local mail with some flexibility. * * $Log: main.c,v $ * Revision 1.5 88/09/14 20:00:03 network * Add version string, including patchlevel. * --- 1,11 ---- ! /* $Header: main.c,v 1.6 88/10/13 12:19:27 network Exp $ * * A program to deliver local mail with some flexibility. * * $Log: main.c,v $ + * Revision 1.6 88/10/13 12:19:27 network + * patch1: add "-n" option, and general bug fixes. + * * Revision 1.5 88/09/14 20:00:03 network * Add version string, including patchlevel. * *************** *** 43,48 **** --- 46,52 ---- int verbose = FALSE; int dryrun = FALSE; + int rundfiles = TRUE; int printaddrs = FALSE; int leavetemps = FALSE; int boxdelivery = FALSE; *************** *** 77,83 **** char **argv; { char *p; ! int u, c, errcount, insecure; /* Make sure that stdout and stderr are interleaved correctly */ --- 81,87 ---- char **argv; { char *p; ! int u, c, errcount; /* Make sure that stdout and stderr are interleaved correctly */ *************** *** 90,96 **** /* What version of the program is this? */ ! sprintf(version + strlen(version), ".%02d", PATCHLEVEL); /* Figure out the name of this host */ --- 94,100 ---- /* What version of the program is this? */ ! (void) sprintf(version + strlen(version), ".%02d", PATCHLEVEL); /* Figure out the name of this host */ *************** *** 120,125 **** --- 124,132 ---- printaddrs = TRUE; dryrun = TRUE; break; + case 'n': + rundfiles = FALSE; + break; case 't': leavetemps = TRUE; break; *************** *** 137,143 **** /* Parse command line arguments */ ! while ((c = getopt(argc, argv, "vdAtbs:u:r:h:")) != EOF) { switch (c) { --- 144,150 ---- /* Parse command line arguments */ ! while ((c = getopt(argc, argv, "vdAntbs:u:r:h:")) != EOF) { switch (c) { *************** *** 152,157 **** --- 159,167 ---- printaddrs = TRUE; dryrun = TRUE; break; + case 'n': + rundfiles = FALSE; + break; case 't': leavetemps = TRUE; break; *************** *** 179,185 **** if (optind >= argc) { ! message("%s: no recipients specified\n", progname); usage(); } --- 189,195 ---- if (optind >= argc) { ! error("no recipients specified\n"); usage(); } *************** *** 202,208 **** if (eff_uid != real_uid && eff_uid != 0) { ! message("%s: if setuid, must be setuid root\n"); leave(1); } --- 212,218 ---- if (eff_uid != real_uid && eff_uid != 0) { ! error("if setuid, must be setuid root\n"); leave(1); } *************** *** 213,219 **** if (setgid(eff_gid = real_gid) == -1 || setuid(eff_uid = real_uid) == -1) { ! syserr("%s: can't renounce setuid privileges"); leave(1); } } --- 223,229 ---- if (setgid(eff_gid = real_gid) == -1 || setuid(eff_uid = real_uid) == -1) { ! syserr("can't renounce setuid privileges"); leave(1); } } *************** *** 306,330 **** else { ! /* ! * Run all destinations though the system delivery file. ! * If sys_dfile() doesn't find one, it will call dest() ! * on each address. ! */ ! sys_dfile(argc - optind, argv + optind); ! if (verbose) ! dumpdests("after running system delivery file"); /* * Run each user destination through his delivery file. */ ! user_dfiles(); ! ! if (verbose) ! dumpdests("after running user delivery files"); } /* --- 316,353 ---- else { ! /* Run all destinations though the system delivery file. */ ! if (sys_dfile(argc - optind, argv + optind) >= 0) ! { ! if (verbose) ! dumpdests("after running system delivery file"); ! } ! else ! { ! int a; ! /* ! * System delivery file is missing or ignored. ! * Use the argument list verbatim. ! */ + for (a = optind; a < argc; ++a) + (void) dest(argv[a], (char *) NULL); + + if (verbose) + dumpdests("as taken from argument list"); + } + /* * Run each user destination through his delivery file. */ ! if (user_dfiles() >= 0) ! { ! if (verbose) ! dumpdests("after running user delivery files"); ! } } /* *************** *** 365,376 **** usage() { ! message("Usage: %s [-b][-A][-d][-v][-t][-r from][-h host] args\n", progname); message("-b All arguments are mailbox filenames.\n"); message(" (Default: arguments are user names.)\n"); message("-A Resolve addresses but do not deliver.\n"); message("-d Be verbose but do not deliver.\n"); message("-v Be verbose and deliver.\n"); message("-t Do not remote temp files before exiting.\n"); message("-r from Specify the address to appear in the \"From \" line.\n"); message("-h host Specify the host name.\n"); --- 388,400 ---- usage() { ! message("Usage: %s [-b][-A][-d][-v][-n][-t][-r from][-h host] args\n", progname); message("-b All arguments are mailbox filenames.\n"); message(" (Default: arguments are user names.)\n"); message("-A Resolve addresses but do not deliver.\n"); message("-d Be verbose but do not deliver.\n"); message("-v Be verbose and deliver.\n"); + message("-n Do not run any delivery files.\n"); message("-t Do not remote temp files before exiting.\n"); message("-r from Specify the address to appear in the \"From \" line.\n"); message("-h host Specify the host name.\n"); Index: subs.c *************** *** 1,8 **** ! /* $Header: subs.c,v 1.3 88/09/14 19:42:33 network Exp $ * * Miscellaneous subroutines. * * $Log: subs.c,v $ * Revision 1.3 88/09/14 19:42:33 network * Portability to System V and BSD. * General fixup. --- 1,11 ---- ! /* $Header: subs.c,v 1.4 88/10/13 12:20:34 network Exp $ * * Miscellaneous subroutines. * * $Log: subs.c,v $ + * Revision 1.4 88/10/13 12:20:34 network + * patch1: add "-n" option, and general bug fixes. + * * Revision 1.3 88/09/14 19:42:33 network * Portability to System V and BSD. * General fixup. *************** *** 94,100 **** nomem() { ! message("%s: out of memory\n", progname); leave(1); } --- 97,103 ---- nomem() { ! error("out of memory\n"); leave(1); } Index: sysdep.c *************** *** 1,4 **** ! /* $Header: sysdep.c,v 1.3 88/09/14 20:00:24 network Exp $ * * Routines which are (or might well be) system-dependant. * I've put the message routines here since you may need to use --- 1,4 ---- ! /* $Header: sysdep.c,v 1.4 88/10/13 12:20:39 network Exp $ * * Routines which are (or might well be) system-dependant. * I've put the message routines here since you may need to use *************** *** 5,10 **** --- 5,13 ---- * the ANSI <stdarg.h> instead of <varargs.h>. * * $Log: sysdep.c,v $ + * Revision 1.4 88/10/13 12:20:39 network + * patch1: add "-n" option, and general bug fixes. + * * Revision 1.3 88/09/14 20:00:24 network * Fix type of gethostname() for BSD. * *************** *** 195,201 **** g = va_arg(ap, int); h = va_arg(ap, int); ! printf(fmt, a,b,c,d,e,f,g,h); } vfprintf(fp, fmt, ap) --- 198,204 ---- g = va_arg(ap, int); h = va_arg(ap, int); ! (void) printf(fmt, a,b,c,d,e,f,g,h); } vfprintf(fp, fmt, ap) *************** *** 214,220 **** g = va_arg(ap, int); h = va_arg(ap, int); ! fprintf(fp, fmt, a,b,c,d,e,f,g,h); } vsprintf(s, fmt, ap) --- 217,223 ---- g = va_arg(ap, int); h = va_arg(ap, int); ! (void) fprintf(fp, fmt, a,b,c,d,e,f,g,h); } vsprintf(s, fmt, ap) *************** *** 233,239 **** g = va_arg(ap, int); h = va_arg(ap, int); ! sprintf(s, fmt, a,b,c,d,e,f,g,h); } #endif /* HAS_VPRINTF */ --- 236,242 ---- g = va_arg(ap, int); h = va_arg(ap, int); ! (void) sprintf(s, fmt, a,b,c,d,e,f,g,h); } #endif /* HAS_VPRINTF */ -- Chip Salzenberg <chip@ateng.com> or <uunet!ateng!chip> A T Engineering Me? Speak for my company? Surely you jest! Beware of programmers carrying screwdrivers.