chip@tct.uucp (Chip Salzenberg) (03/08/90)
NOTE: THIS IS PART OF A COMBINED PATCH. APPLY PATCHES 7-9 TOGETHER. This patch contains changes to the following files: patchlevel.h main.c mbox.c procs.c subs.c sysdep.c uucp.c Index: patchlevel.h Prereq: 8 *************** *** 1,1 **** ! #define PATCHLEVEL 8 --- 1,1 ---- ! #define PATCHLEVEL 9 Index: main.c *************** *** 1,3 **** ! /* $Header: main.c,v 2.7 90/02/06 11:56:40 chip Exp $ * * A program to deliver local mail with some flexibility. --- 1,3 ---- ! /* $Header: main.c,v 2.12 90/03/07 11:00:58 chip Exp $ * * A program to deliver local mail with some flexibility. *************** *** 4,7 **** --- 4,28 ---- * * $Log: main.c,v $ + * Revision 2.12 90/03/07 11:00:58 chip + * Debugging messages only when verbose. (Sigh.) + * + * Revision 2.11 90/03/06 13:11:53 chip + * Run error delivery file after normal delivery; + * then call delivery routines again afterward. + * + * Revision 2.10 90/03/06 12:21:13 chip + * Move logging into log.c and address parsing into addr.c. + * New: error delivery file for messages that fail. + * Major rearrangement of delivery file code. + * + * Revision 2.9 90/02/23 15:05:15 chip + * Clean up the setuid/setgid renunciation logic. + * + * Revision 2.8 90/02/23 14:16:47 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.7 90/02/06 11:56:40 chip * Enforce MBX_MODE regardless of UMASK. *************** *** 35,39 **** #include "patchlevel.h" #include <signal.h> - #include <time.h> /* --- 56,59 ---- *************** *** 50,56 **** */ ! static char sys_dfl[] = SYS_DELIVER; ! static char post_dfl[] = POST_DELIVER; ! static char user_dfl[] = USER_DELIVER; /* --- 70,77 ---- */ ! static char dfl_sys[] = SYS_DELIVER; ! static char dfl_post[] = POST_DELIVER; ! static char dfl_err[] = ERR_DELIVER; ! static char dfl_user[] = USER_DELIVER; /* *************** *** 71,77 **** int rec_level = 0; int rec_parent = -1; ! char *sys_deliver = sys_dfl; ! char *post_deliver = post_dfl; ! char *user_deliver = user_dfl; char *sender = NULL; char *hostname = NULL; --- 92,99 ---- int rec_level = 0; int rec_parent = -1; ! char *sys_deliver = dfl_sys; ! char *post_deliver = dfl_post; ! char *err_deliver = dfl_err; ! char *user_deliver = dfl_user; char *sender = NULL; char *hostname = NULL; *************** *** 87,91 **** int trust_user = FALSE; int trust_delfiles = FALSE; - FILE *log = NULL; char *logfile = NULL; --- 109,112 ---- *************** *** 127,136 **** progname = basename(argv[0]); - #ifdef USG - /* System V requires that we ask for the time zone. Used later. */ - - tzset(); - #endif - /* Special hack -- handle the recursion level and parent first. */ --- 148,151 ---- *************** *** 208,213 **** --- 223,231 ---- if ((p = getenv(ENV_POSTDEL)) != NULL && *p) post_deliver = p; + if ((p = getenv(ENV_ERRDEL)) != NULL && *p) + err_deliver = p; if ((p = getenv(ENV_USERDEL)) != NULL && *p) user_deliver = p; + if ((p = getenv(ENV_SENDER)) != NULL && *p) sender = p; *************** *** 217,221 **** /* Parse command line arguments */ ! while ((c = getopt(argc, argv, "vdAntbs:p:u:r:h:")) != EOF) { switch (c) --- 235,239 ---- /* Parse command line arguments */ ! while ((c = getopt(argc, argv, "vdAntbs:p:e:u:r:h:")) != EOF) { switch (c) *************** *** 249,252 **** --- 267,274 ---- post_deliver = optarg; break; + case 'e': + if (*optarg) + err_deliver = optarg; + break; case 'u': if (*optarg) *************** *** 266,290 **** } ! #ifdef ERRLOG ! /* If we're delivering and not being verbose, keep an error log. */ ! if (!dryrun && !verbose) { ! errlogfile = tempfile(); ! if ((errlog = ftcreate(errlogfile)) == NULL) ! syserr("can't create %s", errlogfile); ! } ! #endif ! ! #ifdef LOG ! /* If we're delivering and the log file exists, keep data for it. */ ! ! if (!dryrun && exists(LOG)) ! { ! logfile = tempfile(); ! if ((log = ftcreate(logfile)) == NULL) ! syserr("can't create %s", logfile); } - #endif /* If no destinations were given, forget it. */ --- 288,303 ---- } ! /* Open temporary log files. */ ! ! openlogs(); ! /* Figure out the name of this host, unless we've been told. */ ! ! if (!hostname && (hostname = gethost()) == NULL) { ! hostname = "unknown"; ! error("unable to determine host name; using \"%s\"\n", ! hostname); } /* If no destinations were given, forget it. */ *************** *** 296,309 **** } ! /* 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 */ if (verbose) --- 309,313 ---- } ! /* If debugging, print a nice banner. */ if (verbose) *************** *** 313,317 **** } ! /* Do we trust our caller? */ if (trusted_uid(real_uid)) --- 317,325 ---- } ! /* ! * Renounce setuid privileges if: ! * 1. We don't trust the real user id, OR ! * 2. The caller is using non-default delivery file names. ! */ if (trusted_uid(real_uid)) *************** *** 318,334 **** trust_user = TRUE; ! /* Do we trust our delivery files? */ ! ! if (strcmp(sys_dfl, sys_deliver) == 0 ! && strcmp(post_dfl, post_deliver) == 0 ! && strcmp(user_dfl, user_deliver) == 0) trust_delfiles = TRUE; ! /* Renounce special privileges if something insecure was requested. */ ! ! if (!trust_user && !trust_delfiles) { ! if (setgid(eff_gid = real_gid) == -1 ! || setuid(eff_uid = real_uid) == -1) { syserr("can't renounce setuid privileges"); --- 326,339 ---- trust_user = TRUE; ! if (strcmp(dfl_sys, sys_deliver) == 0 ! && strcmp(dfl_post, post_deliver) == 0 ! && strcmp(dfl_err, err_deliver) == 0 ! && strcmp(dfl_user, user_deliver) == 0) trust_delfiles = TRUE; ! if ((!trust_user && !trust_delfiles) ! && (eff_uid != real_uid || eff_gid != real_gid)) { ! if (setuid(real_uid) == -1) { syserr("can't renounce setuid privileges"); *************** *** 335,338 **** --- 340,358 ---- leave(1); } + if (setgid(real_gid) == -1) + { + syserr("can't renounce setgid privileges"); + leave(1); + } + + if ((eff_uid = geteuid()) != real_uid + || (eff_gid = getegid()) != real_gid) + { + error("kernel bug: can't renounce setuid/setgid"); + leave(1); + } + + if (verbose) + message("renounced setuid privileges\n"); } *************** *** 410,530 **** 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; ! if (verbose) ! message("mailbox delivery as %s\n", real_ct->ct_name); ! /* ! * Consider all arguments as mailbox filenames. ! */ ! for (a = optind; a < argc; ++a) ! (void) dest(real_ct->ct_name, argv[a]); if (verbose) ! dumpdests("(should all be mailboxes)"); } /* ! * Else, arguments are addresses. */ ! 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"); ! } ! /* ! * Run each remaining destination though the post-user ! * delivery file. ! */ ! if (post_dfile() >= 0) ! { ! if (verbose) ! dumpdests("after running post-user delivery file"); ! } } ! /* ! * Drop mail in mailbox(es). ! */ ! mbox_deliver(); ! if (verbose) ! dumpdests("after delivery to all mailboxes"); /* ! * Send mail to UUCP address(es). ! */ ! uucp_deliver(); if (verbose) ! dumpdests("after delivery to UUCP addresses"); ! ! /* ! * Report all results in log file. ! */ ! if (log) ! logreport(argc - optind, argv + optind); ! /* ! * Report any errors. ! */ ! errcount = report_errors(); ! /* ! * All done. ! */ ! leave(errcount ? 1 : 0); ! /* NOTREACHED */ } --- 430,583 ---- if (rec_level > REC_LIMIT) ! main_toodeep(); /* ! * Else if the "-b" flag was specified, arguments are mailboxes. */ else if (boxdelivery) ! main_boxes(argc - optind, argv + optind); ! /* ! * Otherwise, arguments are addresses. ! */ ! else ! main_addrs(argc - optind, argv + optind); ! /* ! * Do all delivery. ! * If anything happens, print a debugging message. ! */ ! ! i = 0; ! i += (mbox_deliver() > 0); ! i += (prog_deliver() > 0); ! i += (uucp_deliver() > 0); ! if (i > 0 && verbose) ! dumpdests("after delivery"); ! ! /* ! * If we're not in mailbox mode, and if the error delivery file ! * executes, deliver to any destination(s) that it generated. ! */ + if (!boxdelivery + && (i = err_dfile()) > 0) + { if (verbose) ! dumpdests("after running error delivery file"); ! ! i = 0; ! i += (mbox_deliver() > 0); ! i += (prog_deliver() > 0); ! i += (uucp_deliver() > 0); ! if (i > 0 && verbose) ! dumpdests("after delivery to error destinations"); } /* ! * Report all results in log file. */ ! logreport(argc - optind, argv + optind); ! /* ! * Report any errors. ! */ ! errcount = report_errors(argc - optind, argv + optind); ! /* ! * All done. ! */ ! leave(errcount ? 1 : 0); ! /* NOTREACHED */ ! } ! /*---------------------------------------------------------------------- ! * Normal address handling. ! * Call system delivery file, user delivery files, ! * post-user delivery file, error delivery file. ! */ ! main_addrs(ac, av) ! int ac; ! char **av; ! { ! int n; ! ! /* Run all destinations though the system delivery file. */ ! ! if (sys_dfile(ac, av) >= 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 = 0; a < ac; ++a) ! (void) addr_dest(av[a], (CONTEXT *)NULL); ! if (verbose) ! dumpdests("as taken from argument list"); ! } /* ! * Run each user destination through his delivery file. ! */ ! ! n = user_dfiles(); ! if (n > 0 && verbose) ! dumpdests("after running user delivery files"); ! ! /* ! * Run each remaining destination though the post-user ! * delivery file. ! */ ! ! n = post_dfile(); ! if (n > 0 && verbose) ! dumpdests("after running post-user delivery file"); ! } ! ! /*---------------------------------------------------------------------- ! * Consider all arguments as mailbox filenames. ! */ ! main_boxes(ac, av) ! int ac; ! char **av; ! { ! int a; if (verbose) ! message("mailbox delivery as %s\n", real_ct->ct_name); ! for (a = 0; a < ac; ++a) ! (void) dest(real_ct->ct_name, CL_MBOX, av[a]); ! if (verbose) ! dumpdests("(should all be mailboxes)"); ! } ! /*---------------------------------------------------------------------- ! * Recursion too deep. Bail out. ! */ ! main_toodeep() ! { ! error("recursion limit (%d) exceeded; writing to %s:%s", ! REC_LIMIT, eff_ct->ct_name, MBX_UNDEL); ! dest_undel(eff_ct->ct_name); } *************** *** 545,548 **** --- 598,602 ---- message("-s file Specify the system delivery filename.\n"); message("-p file Specify the post-user delivery filename.\n"); + message("-e file Specify the error delivery filename.\n"); message("-u file Specify the user delivery filename.\n"); message("-r from Specify the address to appear in the \"From \" line.\n"); *************** *** 582,594 **** savelogs(); ! /* Discard temporary logs. */ ! if (! leavetemps) ! { ! if (logfile && unlink(logfile) == -1) ! (void) syserr("can't remove %s", logfile); ! if (errlogfile && unlink(errlogfile) == -1) ! (void) syserr("can't remove %s", logfile); ! } /* "I am outa here." */ --- 636,643 ---- savelogs(); ! /* Discard temporary logs unless user requested otherwise. */ ! if (!leavetemps) ! tosslogs(); /* "I am outa here." */ *************** *** 644,706 **** /*---------------------------------------------------------------------- - * Write a report to the log file. - */ - - logreport(ac, av) - int ac; - char **av; - { - int a; - - if (!log) - return; - - logstart(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); - - logdone(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. --- 693,696 ---- *************** *** 708,726 **** int ! report_errors() { ! DEST *d; ! int count = 0; ! for (d = first_dest(); d; d = next_dest(d)) ! { if (d->d_state != ST_ERROR) continue; ! if (++count == 1) { ! error( ! "delivery to the following address(es) failed on host %s:\n", ! hostname); } --- 698,734 ---- int ! report_errors(ac, av) ! int ac; ! char **av; { ! DEST **dv; ! int i, count, errcount; ! ! if ((dv = dest_array(&count)) == NULL) ! return 0; ! ! errcount = 0; ! for (i = 0; i < count; ++i) ! { ! DEST *d; ! char *e; ! int len; ! d = dv[i]; ! if (d->d_state != ST_ERROR) continue; ! if (++errcount == 1) { ! int a; ! ! error("delivery error on host %s.\n", hostname); ! message("Delivery to %s address%s failed:\n", ! ac ? "these" : "this", ! ac ? "es" : ""); ! for (a = 0; a < ac; ++a) ! message("\t%s\n", av[a]); ! message("Reason(s) for failure:\n"); } *************** *** 727,833 **** message("\t\"%s\"", d->d_name); if (d->d_class == CL_MBOX) ! message(", mailbox \"%s\"", d->d_mailbox); ! message(": %s\n", derrmsg(d->d_error)); ! } ! ! return count; ! } ! ! /*---------------------------------------------------------------------- ! * Save log data in the real logfiles. ! */ ! ! savelogs() ! { ! /* If logs weren't kept, forget it. */ ! ! if (!log && !errlog) ! return; ! ! /* If temporary logs contain anything, append them to real logs. */ ! ! if ((log && ftell(log) > 0) ! || (errlog && ftell(errlog) > 0)) ! { ! if (create_lockfile(LOGLOCK) == 0) ! { ! applog(&log, LOG); ! errdone(); ! applog(&errlog, ERRLOG); ! (void) remove_lockfile(LOGLOCK); ! } ! } ! } ! ! /*---------------------------------------------------------------------- ! * Append a temporary log file to a real logfile. ! * We pass a FILE **, so that it can be set to NULL when closed; ! * this is important, since errlog is used by syserr(). ! * Note: The logfile is ass_u_med to be locked already! ! */ ! ! applog(fpp, realfile) ! FILE **fpp; ! char *realfile; ! { ! FILE *fp = fpp ? *fpp : NULL; ! int fd, realfd; ! ! /* If log data weren't kept, never mind. */ ! ! if (fp == NULL) ! return; ! ! /* Flush buffered data. */ ! ! (void) fflush(fp); ! ! /* If the file is empty, never mind. */ ! ! if (ftell(fp) == 0) ! { ! (void) fclose(fp); ! *fpp = NULL; ! return; ! } ! ! /* Get an fd and close the stream. */ ! ! if ((fd = dup(fileno(fp))) == -1) ! { ! syserr("can't dup log fd"); ! (void) fclose(fp); ! *fpp = NULL; ! return; ! } ! (void) fclose(fp); ! *fpp = NULL; ! ! /* ! * Open the real logfile, creating it if necessary. ! * Note that there is no race condition since the logs are locked. ! */ ! ! #ifdef O_CREAT ! realfd = open(realfile, O_WRONLY|O_CREAT, 0666); ! #else ! if ((realfd = open(realfile, O_WRONLY)) == -1) ! realfd = creat(realfile, 0666); ! #endif ! if (realfd == -1) ! syserr("can't open %s for writing", logfile); ! else ! { ! /* Append the temporary log to the real log. */ ! (void) lseek(fd, 0L, 0); ! (void) lseek(realfd, 0L, 2); ! (void) copyfd(fd, realfd); ! (void) close(realfd); } ! /* Close the temporary log. */ ! (void) close(fd); } --- 735,752 ---- message("\t\"%s\"", d->d_name); if (d->d_class == CL_MBOX) ! message(", mailbox \"%s\"", d->d_param); ! else if (d->d_class == CL_PROG) ! message(", program \"%s\"", d->d_param); ! e = derrmsg(d); ! len = strlen(d->d_name) + strlen(e); ! if (d->d_param) ! len += strlen(d->d_param); ! message(":%s%s\n", (len > 60) ? "\n\t\t" : " ", derrmsg(d)); } ! free((char *) dv); ! return errcount; } Index: mbox.c *************** *** 1,3 **** ! /* $Header: mbox.c,v 2.3 90/02/06 11:56:42 chip Exp $ * * Finally! Put the message in the specified mailbox(es). --- 1,3 ---- ! /* $Header: mbox.c,v 2.5 90/02/23 16:35:55 chip Exp $ * * Finally! Put the message in the specified mailbox(es). *************** *** 4,7 **** --- 4,16 ---- * * $Log: mbox.c,v $ + * Revision 2.5 90/02/23 16:35:55 chip + * \Fix problems determining legality of user references. + * + * Revision 2.4 90/02/23 14:16:50 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.3 90/02/06 11:56:42 chip * Enforce MBX_MODE regardless of UMASK. *************** *** 34,37 **** --- 43,47 ---- */ + static prog_one(); static mbox_one(); static int mbox_write(); *************** *** 38,63 **** /*---------------------------------------------------------------------- ! * Deliver mail to all valid destinations. */ mbox_deliver() { DEST *d; for (d = first_dest(); d; d = next_dest(d)) { ! switch (d->d_class) { ! case CL_USER: ! case CL_MBOX: ! if (d->d_state == ST_WORKING) ! mbox_one(d); ! break; } } } /*---------------------------------------------------------------------- ! * Deliver mail to one destination. */ --- 48,160 ---- /*---------------------------------------------------------------------- ! * Deliver mail to all valid program (pipe) destinations. ! * Return count of programs to which we tried to write. ! */ ! ! int ! prog_deliver() ! { ! DEST *d; ! int progcount; ! ! progcount = 0; ! for (d = first_dest(); d; d = next_dest(d)) ! { ! if (d->d_state != ST_WORKING) ! continue; ! ! if (d->d_class == CL_PROG) ! { ! prog_one(d); ! ++progcount; ! } ! } ! ! return progcount; ! } ! ! /*---------------------------------------------------------------------- ! * Deliver mail to one program. ! */ ! ! static ! prog_one(d) ! DEST *d; ! { ! CONTEXT *ct; ! char *av[4]; ! int fd; ! ! if (printaddrs) ! (void) printf("%s|%s\n", d->d_name, d->d_param); ! ! if (dryrun) ! { ! d->d_state = ST_DONE; ! return; ! } ! ! if ((ct = name_context(d->d_name)) == NULL) ! { ! dest_err(d, E_NSUSER); ! return; ! } ! ! if (! ok_context(eff_uid, real_uid, real_gid, ct)) ! { ! dest_err(d, E_CTPERM); ! return; ! } ! ! av[0] = SHELL; ! av[1] = "-c"; ! av[2] = d->d_param; ! av[3] = NULL; ! if ((fd = ct_openv(ct, av[0], av, O_WRONLY)) == -1) ! { ! dest_err(d, E_PIPE); ! return; ! } ! ! (void) lseek(tfd[T_HDR], 0L, 0); ! (void) lseek(tfd[T_BODY], 0L, 0); ! if (copyfd(tfd[T_HDR], fd) < 0 || copyfd(tfd[T_BODY], fd) < 0) ! dest_err(d, E_PIPE); ! ! if (ct_close(fd)) ! dest_err(d, E_PROG); ! else ! d->d_state = ST_DONE; ! } ! ! /*---------------------------------------------------------------------- ! * Deliver mail to all valid mailbox destinations. ! * Return count of mailboxes to which we tried to write. */ + int mbox_deliver() { DEST *d; + int mboxcount; + mboxcount = 0; for (d = first_dest(); d; d = next_dest(d)) { ! if (d->d_state != ST_WORKING) ! continue; ! ! if (d->d_class == CL_USER || d->d_class == CL_MBOX) { ! mbox_one(d); ! ++mboxcount; } } + + return mboxcount; } /*---------------------------------------------------------------------- ! * Deliver mail to one mailbox destination. */ *************** *** 73,77 **** (void) printf("%s", d->d_name); if (d->d_class == CL_MBOX) ! (void) printf(":%s", d->d_mailbox); (void) printf("\n"); } --- 170,174 ---- (void) printf("%s", d->d_name); if (d->d_class == CL_MBOX) ! (void) printf(":%s", d->d_param); (void) printf("\n"); } *************** *** 89,93 **** } ! if (! ok_context(ct)) { dest_err(d, E_CTPERM); --- 186,190 ---- } ! if (! ok_context(eff_uid, real_uid, real_gid, ct)) { dest_err(d, E_CTPERM); *************** *** 101,105 **** if (become(ct, !boxdelivery) < 0) exit(1); ! if (mbox_write(d->d_mailbox, ct, FALSE) < 0) exit(1); exit(0); --- 198,202 ---- if (become(ct, !boxdelivery) < 0) exit(1); ! if (mbox_write(d->d_param, ct, FALSE) < 0) exit(1); exit(0); Index: procs.c *************** *** 1,3 **** ! /* $Header: procs.c,v 2.4 89/11/01 12:19:05 network Exp $ * * Process management and misc support. --- 1,3 ---- ! /* $Header: procs.c,v 2.6 90/02/23 16:35:59 chip Exp $ * * Process management and misc support. *************** *** 4,7 **** --- 4,16 ---- * * $Log: procs.c,v $ + * Revision 2.6 90/02/23 16:35:59 chip + * \Fix problems determining legality of user references. + * + * Revision 2.5 90/02/23 14:16:51 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.4 89/11/01 12:19:05 network * Delintify. *************** *** 46,50 **** FILE * ! ct_popenv(ct, prog, av, mode) CONTEXT *ct; char *prog; --- 55,59 ---- FILE * ! ct_fopenv(ct, prog, av, mode) CONTEXT *ct; char *prog; *************** *** 52,55 **** --- 61,116 ---- char *mode; { + FILE *fp; + int fd, m; + + if (mode && mode[0] == 'r' && mode[1] == 0) + m = O_RDONLY; + else if (mode && mode[0] == 'w' && mode[1] == 0) + m = O_WRONLY; + else + return NULL; + + if ((fd = ct_openv(ct, prog, av, m)) == -1) + return NULL; + + if ((fp = fdopen(fd, mode)) == NULL) + (void) ct_close(fd); + + return fp; + } + + /*---------------------------------------------------------------------- + * Close the stream opened by ct_fopen(). + */ + + ct_fclose(fp) + FILE *fp; + { + int fd; + + if (fp) + { + fd = dup(fileno(fp)); + (void) fclose(fp); + } + else + fd = -1; + + return ct_close(fd); + } + + /*---------------------------------------------------------------------- + * Like popen(), but execute the child in a specific context. + * Also, the argument list is already a vector. + * And return a file descriptor instead of a FILE *. + */ + + int + ct_openv(ct, prog, av, mode) + CONTEXT *ct; + char *prog; + char **av; + int mode; + { char ch; int child, parent; *************** *** 56,68 **** int pfd[2]; ! if (!ct || !prog || !av || !mode) return NULL; ! if (mode[0] == 'r' && mode[1] == 0) child = 1, parent = 0; ! else if (mode[0] == 'w' && mode[1] == 0) child = 0, parent = 1; else ! return NULL; /* We can't have more than one child at a time. */ --- 117,132 ---- int pfd[2]; ! if (!ct || !prog || !av) return NULL; ! if (mode == O_RDONLY) child = 1, parent = 0; ! else if (mode == O_WRONLY) child = 0, parent = 1; else ! { ! error("in ct_open: invalid mode"); ! return -1; ! } /* We can't have more than one child at a time. */ *************** *** 70,75 **** if (child_pid >= 0) { ! error("in ct_popen: a process is already open\n"); ! return NULL; } --- 134,139 ---- if (child_pid >= 0) { ! error("in ct_open: a process is already open"); ! return -1; } *************** *** 76,84 **** /* Make a stab at predicting uid-related failure. */ ! if (! ok_context(ct)) { ! error("in ct_popen: no permissions to become %s\n", ! ct->ct_name); ! return NULL; } --- 140,147 ---- /* Make a stab at predicting uid-related failure. */ ! if (! ok_context(eff_uid, real_uid, real_gid, ct)) { ! error("in ct_open: no permissions to become %s", ct->ct_name); ! return -1; } *************** *** 88,92 **** { syserr("can't create a pipe"); ! return NULL; } --- 151,155 ---- { syserr("can't create a pipe"); ! return -1; } *************** *** 97,101 **** int a; ! message("Spawning"); for (a = 0; av[a]; ++a) message(" %s", av[a]); --- 160,164 ---- int a; ! message("%s: spawning", progname); for (a = 0; av[a]; ++a) message(" %s", av[a]); *************** *** 161,180 **** (void) close(pfd[1]); (void) await_child(); ! return NULL; } (void) close(pfd[child]); ! return fdopen(pfd[parent], mode); } /*---------------------------------------------------------------------- ! * Close the stream opened by ct_popen(). */ ! ct_pclose(fp) ! FILE *fp; { ! if (fp) ! (void) fclose(fp); return await_child(); } --- 224,243 ---- (void) close(pfd[1]); (void) await_child(); ! return -1; } (void) close(pfd[child]); ! return pfd[parent]; } /*---------------------------------------------------------------------- ! * Close the file descriptor opened by ct_open(). */ ! ct_close(fd) ! int fd; { ! if (fd != -1) ! (void) close(fd); return await_child(); } *************** *** 298,305 **** if (st & 0xFF) { ! error("child process died%s due to signal %d.\n", ((st & 0x80) ? " and dumped core" : ""), (st & 0x7F)); - return -1; } --- 361,367 ---- if (st & 0xFF) { ! error("child process died%s due to signal %d.", ((st & 0x80) ? " and dumped core" : ""), (st & 0x7F)); return -1; } *************** *** 307,312 **** if (verbose) { ! message("child process exited with status %d.\n", ! (st >> 8) & 0xFF); } --- 369,374 ---- if (verbose) { ! message("%s: child process exited with status %d.\n", ! progname, (st >> 8) & 0xFF); } Index: subs.c *************** *** 1,3 **** ! /* $Header: subs.c,v 2.4 90/02/06 11:56:46 chip Exp $ * * Miscellaneous subroutines. --- 1,3 ---- ! /* $Header: subs.c,v 2.6 90/03/06 12:21:17 chip Exp $ * * Miscellaneous subroutines. *************** *** 4,7 **** --- 4,18 ---- * * $Log: subs.c,v $ + * Revision 2.6 90/03/06 12:21:17 chip + * Move logging into log.c and address parsing into addr.c. + * New: error delivery file for messages that fail. + * Major rearrangement of delivery file code. + * + * Revision 2.5 90/02/23 14:16:56 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.4 90/02/06 11:56:46 chip * Enforce MBX_MODE regardless of UMASK. *************** *** 286,307 **** return path; - } - - /*---------------------------------------------------------------------- - * Check an address for validity. - */ - - valid_address(addr) - char *addr; - { - char *p; - static char sanitize[] = SANITIZE; - - for (p = addr; *p; ++p) - { - if (strchr(sanitize, *p)) - return FALSE; - } - - return TRUE; } --- 297,299 ---- Index: sysdep.c *************** *** 1,3 **** ! /* $Header: sysdep.c,v 2.6 90/02/06 11:56:43 chip Exp $ * * Routines which are (or might well be) system-dependant. --- 1,3 ---- ! /* $Header: sysdep.c,v 2.8 90/03/06 12:21:16 chip Exp $ * * Routines which are (or might well be) system-dependant. *************** *** 6,9 **** --- 6,20 ---- * * $Log: sysdep.c,v $ + * Revision 2.8 90/03/06 12:21:16 chip + * Move logging into log.c and address parsing into addr.c. + * New: error delivery file for messages that fail. + * Major rearrangement of delivery file code. + * + * Revision 2.7 90/02/23 14:16:52 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.6 90/02/06 11:56:43 chip * Enforce MBX_MODE regardless of UMASK. *************** *** 33,37 **** #include "deliver.h" #include <errno.h> - #include <time.h> #ifdef HAS_STDARG #include <stdarg.h> --- 44,47 ---- *************** *** 178,368 **** 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 (ftell(errlog) > 0) - 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() - { - /* If we've already written a time stamp, don't do it again. */ - - if (!errlog || ftell(errlog) > 0) - return; - - /* Write a time stamp and various useful info. */ - - logstart(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); - } - - /*---------------------------------------------------------------------- - * Record the end of this process's error log entry. - */ - - errdone() - { - /* If we never wrote to the error log file, do nothing. */ - - if (!errlog || ftell(errlog) == 0) - 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"); - - logdone(errlog); - } - - /*---------------------------------------------------------------------- - * Start a log entry. - * Various useful info goes here -- especially a timestamp. - */ - - logstart(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); - else - (void) fputs("---", fp); - (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 USG - tzname[lt->tm_isdst ? 1 : 0] - #else - lt->tm_zone - #endif - ); - } - - /*---------------------------------------------------------------------- - * Write a concluding marker to the given logfile. - * This marker separates instances of Deliver at recursion level zero. - */ - - logdone(fp) - FILE *fp; - { - if (rec_level == 0) - (void) fputs("===========================\n\n", fp); } --- 188,191 ---- Index: uucp.c *************** *** 1,3 **** ! /* $Header: uucp.c,v 2.3 89/12/19 16:26:41 network Exp $ * * Handle mail destined for other hosts via UUCP. --- 1,3 ---- ! /* $Header: uucp.c,v 2.4 90/02/23 14:16:54 chip Exp $ * * Handle mail destined for other hosts via UUCP. *************** *** 6,9 **** --- 6,15 ---- * * $Log: uucp.c,v $ + * Revision 2.4 90/02/23 14:16:54 chip + * Support "#!" in delivery files. + * Support "user|program" and "user?error" from delivery files. + * Improve debugging and error message formatting. + * Rearrange code for clarity. + * * Revision 2.3 89/12/19 16:26:41 network * Execute UUCP in real, not effective, context. *************** *** 31,37 **** --- 37,45 ---- /*---------------------------------------------------------------------- * Send mail to UUCP addresses (if any). + * Return count of UUCP addresses for which delivery was attempted. * This is a simple implementation: invoke uux once per address. */ + int uucp_deliver() { *************** *** 38,41 **** --- 46,50 ---- DEST *d; char *uux; + int uucpcount; static char uux1[] = "/bin/uux"; static char uux2[] = "/usr/bin/uux"; *************** *** 48,54 **** { error("can't find uux!?\n"); ! return; } for (d = first_dest(); d; d = next_dest(d)) { --- 57,64 ---- { error("can't find uux!?\n"); ! return -1; } + uucpcount = 0; for (d = first_dest(); d; d = next_dest(d)) { *************** *** 62,65 **** --- 72,77 ---- continue; + ++uucpcount; + if (printaddrs) (void) printf("%s\n", d->d_name); *************** *** 82,92 **** av[3] = who; av[4] = NULL; ! if ((uux_fp = ct_popenv(real_ct, uux, av, "w")) == NULL) continue; if (uucp_copy(uux_fp) < 0) ! dest_err(d, E_UUX); ! if (ct_pclose(uux_fp)) { /* "No such host" overrides piping problems. */ --- 94,104 ---- av[3] = who; av[4] = NULL; ! if ((uux_fp = ct_fopenv(real_ct, uux, av, "w")) == NULL) continue; if (uucp_copy(uux_fp) < 0) ! dest_err(d, E_PIPE); ! if (ct_fclose(uux_fp)) { /* "No such host" overrides piping problems. */ *************** *** 96,99 **** --- 108,113 ---- d->d_state = ST_DONE; } + + return uucpcount; } -- Chip Salzenberg at ComDev/TCT <chip%tct@ateng.com>, <uunet!ateng!tct!chip> "The Usenet, in a very real sense, does not exist."
kv56962@tut.fi (V{{r{nen Kari) (03/09/90)
Would someone, please, tell me what Deliver is and what it does. -- SO LONG AND THANKS FOR ALL THE FISH (The dolphins) Kari Vaaranen Tampere University of Technology Majakkakatu 30, kv56962@tut.fi SF-33410 Tampere, FINLAND (These opinions are mine and mine ONLY!)