From: David Peterson (peterson@minerva.Prime.COM)
Date: 09/21/92


From: peterson@minerva.Prime.COM (David Peterson)
Subject: Mailpak 1.3: Fix for no bounce messages
Date: Mon, 21 Sep 1992 15:02:09 GMT

As distributed, smail2.5 does not generate 'bounce' messages when trying
to deliver mail to a nonexistent local user. This is because smail
(in deliver.c) expects pclose() to contain the exit status of the popen()-ed
command. The popen()/pclose() in libc do not provide this information,
so smail blithely assumes that the mail was delivered and never generates
bounce messages.

The following patch corrects this problem; popen.c was taken from
mailpak/mail/popen.c, and changes are made to deliver.c to use it.

[ I also removed getopt.o from OBJECTS in the Makefile and pick it up from
  libc ]

Library folks, can someone PLEASE fix popen()/pclose() to DTRT?

After applying this fix (along with the HAS_STRCASECMP fix); uucp and the
mail software is working like a chimp (err, champ. No monkeying around.)
uucico now times out when the remote end is busy (which the mailpak 1.2
version didn't).

Apply this patch in the smail3 directory.

*** Makefile~ Thu Sep 17 23:18:46 1992
--- Makefile Fri Sep 18 22:38:12 1992
***************
*** 8,14 ****
  #
  #LIBS = -lmalloc
  
! OBJECTS = main.o map.o resolve.o deliver.o misc.o alias.o pw.o headers.o getpath.o str.o getopt.o
  
  all: smail svbinmail lcasep pathproc mkfnames nptx
  
--- 8,14 ----
  #
  #LIBS = -lmalloc
  
! OBJECTS = main.o map.o resolve.o deliver.o misc.o alias.o pw.o headers.o getpath.o str.o popen.o
  
  all: smail svbinmail lcasep pathproc mkfnames nptx
  
*** /dev/null Thu Jul 30 19:31:47 1992
--- popen.c Fri Sep 18 22:38:49 1992
***************
*** 0 ****
--- 1,71 ----
+ /*
+ * Do system/popen with real gid, but retain 'mail' as egid afterwards
+ * uses the 'native' shell for system
+ */
+
+ #include <stdio.h>
+ #include <signal.h>
+
+ #define tst(a,b) (*mode == 'r'? (b) : (a))
+ #define RDR 0
+ #define WTR 1
+
+ extern FILE *fdopen();
+ extern int execl(), fork(), pipe(), close(), fcntl();
+ static int popen_pid[20];
+
+ FILE *
+ mypopen(cmd,mode)
+ char *cmd;
+ char *mode;
+ {
+ int p[2];
+ register int myside, hisside, pid;
+
+ if(pipe(p) < 0)
+ return NULL;
+ myside = tst(p[WTR], p[RDR]);
+ hisside = tst(p[RDR], p[WTR]);
+ if ((pid = fork()) == 0) {
+ /* myside and hisside reverse roles in child */
+ int stdio;
+ stdio = tst(0, 1);
+ (void) close(myside);
+ (void) close(stdio);
+ (void) fcntl(hisside, 0, stdio);
+ (void) close(hisside);
+ setgid(getgid()); /* restore real group ID in child */
+ execl("/bin/sh", "sh", "-c", cmd, 0);
+ _exit(1);
+ }
+ if(pid == -1) {
+ close(myside);
+ close(hisside);
+ return NULL;
+ }
+ popen_pid[myside] = pid;
+ close(hisside);
+ return(fdopen(myside, mode));
+ }
+
+ int
+ mypclose(ptr)
+ FILE *ptr;
+ {
+ register int f, r;
+ int status, (*hstat)(), (*istat)(), (*qstat)();
+
+ f = fileno(ptr);
+ (void) fclose(ptr);
+ istat = signal(SIGINT, SIG_IGN);
+ qstat = signal(SIGQUIT, SIG_IGN);
+ hstat = signal(SIGHUP, SIG_IGN);
+ while ((r = wait(&status)) != popen_pid[f] && r != -1)
+ ;
+ if (r == -1)
+ status = -1;
+ (void) signal(SIGINT, istat);
+ (void) signal(SIGQUIT, qstat);
+ (void) signal(SIGHUP, hstat);
+ return(status);
+ }

*** deliver.c~ Mon Sep 21 10:23:20 1992
--- deliver.c Mon Sep 21 10:26:04 1992
***************
*** 55,61 ****
  int costv[]; /* cost vector */
  {
        FILE *out; /* pipe to mailer */
! FILE *popen(); /* to fork a mailer */
  #ifdef RECORD
        void record(); /* record all transactions */
  #endif
--- 55,61 ----
  int costv[]; /* cost vector */
  {
        FILE *out; /* pipe to mailer */
! FILE *mypopen(); /* to fork a mailer */
  #ifdef RECORD
        void record(); /* record all transactions */
  #endif
***************
*** 235,241 ****
  /*
  ** We may try to write on a broken pipe, if the uux'd host
  ** is unknown to us. Ignore this signal, since we can use the
! ** return value of the pclose() as our indication of failure.
  */
                (void) signal(SIGPIPE, SIG_IGN);
  
--- 235,241 ----
  /*
  ** We may try to write on a broken pipe, if the uux'd host
  ** is unknown to us. Ignore this signal, since we can use the
! ** return value of the mypclose() as our indication of failure.
  */
                (void) signal(SIGPIPE, SIG_IGN);
  
***************
*** 244,250 ****
                } else {
                        failcount = 0;
                        do {
! out = popen(command, "w");
                                if (out) break;
                                /*
                                 * Fork failed. System probably overloaded.
--- 244,250 ----
                } else {
                        failcount = 0;
                        do {
! out = mypopen(command, "w");
                                if (out) break;
                                /*
                                 * Fork failed. System probably overloaded.
***************
*** 281,287 ****
                                size += strlen(buf);
                                (void) fputs(buf, out);
                        } else {
! *p = NULL;
                                (void) sprintf(buf, RFROM(p+1, nows, from));
                                size += strlen(buf);
                                (void) fputs(buf, out);
--- 281,287 ----
                                size += strlen(buf);
                                (void) fputs(buf, out);
                        } else {
! *p = '\0';
                                (void) sprintf(buf, RFROM(p+1, nows, from));
                                size += strlen(buf);
                                (void) fputs(buf, out);
***************
*** 325,332 ****
                if (debug != YES) {
                        if(form == ERROR) {
                                exitstat = EX_NOHOST;
! } else if (status = pclose(out)) {
! exitstat = status >> 8;
                        }
                        /*
                         * The 'retrying' check prevents a smail loop.
--- 325,332 ----
                if (debug != YES) {
                        if(form == ERROR) {
                                exitstat = EX_NOHOST;
! } else if (status = mypclose(out)) {
! exitstat = status;
                        }
                        /*
                         * The 'retrying' check prevents a smail loop.
***************
*** 419,425 ****
        char buf[SMLBUF];
        char domain[SMLBUF], user[SMLBUF];
        char *r;
! FILE *fp, *out, *popen();
        int i = 0;
  
        r = buf;
--- 419,425 ----
        char buf[SMLBUF];
        char domain[SMLBUF], user[SMLBUF];
        char *r;
! FILE *fp, *out, *mypopen();
        int i = 0;
  
        r = buf;
***************
*** 435,441 ****
  
        i = 0;
        do {
! out = popen(buf, "w");
                if (out) break;
                /*
                 * Fork failed. System probably overloaded.
--- 435,441 ----
  
        i = 0;
        do {
! out = mypopen(buf, "w");
                if (out) break;
                /*
                 * Fork failed. System probably overloaded.
***************
*** 475,479 ****
        while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
                (void) fputs(buf, out);
        }
! (void) pclose(out);
  }
--- 475,480 ----
        while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
                (void) fputs(buf, out);
        }
! (void) mypclose(out);
  }

-- 
| David Peterson                     | The American Republic  will last until |
| PrimeService, a Computervision Co. | its politicians discover that they can |
| peterson@primerd.Prime.COM         | bribe their own people  with their own |
| peterson@warpdrive.Milford.MA.US   | money.     -Alexis DeTouqueville, 1785 |
+------------------------------------+----------------------------------------+
| Opinions expressed are mine, all mine, but they can become yours too for a  |
| small monthly fee.                                                          |