Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / sendmail.c,v
1 head    1.9;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.9
9 date    92.11.24.18.37.01;      author jromine; state Exp;
10 branches;
11 next    1.8;
12
13 1.8
14 date    92.11.04.01.02.39;      author jromine; state Exp;
15 branches;
16 next    1.7;
17
18 1.7
19 date    92.10.20.17.27.08;      author jromine; state Exp;
20 branches;
21 next    1.6;
22
23 1.6
24 date    92.05.19.21.07.35;      author jromine; state Exp;
25 branches;
26 next    1.5;
27
28 1.5
29 date    92.01.24.22.36.27;      author jromine; state Exp;
30 branches;
31 next    1.4;
32
33 1.4
34 date    92.01.24.22.31.43;      author jromine; state Exp;
35 branches;
36 next    1.3;
37
38 1.3
39 date    91.05.22.17.59.50;      author erickson;        state Exp;
40 branches;
41 next    1.2;
42
43 1.2
44 date    91.05.20.17.31.04;      author erickson;        state Exp;
45 branches;
46 next    1.1;
47
48 1.1
49 date    91.05.17.15.31.52;      author jromine; state Exp;
50 branches;
51 next    ;
52
53
54 desc
55 @@
56
57
58 1.9
59 log
60 @add decl
61 @
62 text
63 @/* sendmail.c - */
64 #ifndef lint
65 static char Id[] = "$Id: sendmail.c,v 1.8 1992/11/04 01:02:39 jromine Exp jromine $";
66 #endif
67 /*
68  **  A Sendmail fake.
69  *
70  * Contributed by Scott Erickson <erickson@@ics.uci.edu>
71  */
72 /* Include files glommed from post.c */
73
74 #include "../h/mh.h"
75 #include "../h/addrsbr.h"
76 #include "../h/aliasbr.h"
77 #include "../h/dropsbr.h"
78 #include "../zotnet/tws.h"
79 #ifndef MMDFMTS
80 #include <ctype.h>
81 #include <errno.h>
82 #include <setjmp.h>
83 #include <stdio.h>
84 #include <sys/types.h>
85 #else   MMDFMTS
86 #include "../mts/mmdf/util.h"
87 #include "../mts/mmdf/mmdf.h"
88 #endif  MMDFMTS
89 #include "../zotnet/mts.h"
90 #ifdef  MHMTS
91 #ifndef V7
92 #include <sys/ioctl.h>
93 #endif  not V7
94 #include <sys/stat.h>
95 #endif  MHMTS
96 #ifdef  SENDMTS
97 #include "../mts/sendmail/smail.h"
98 #undef  MF
99 #endif  SENDMTS
100 #include <signal.h>
101 #ifdef LOCALE
102 #include        <locale.h>
103 #endif
104
105 char    *SMTPSRVR = "smtpsrvr";
106
107 char    msgfname[50];   /* name of message file */
108 char    *FullName;      /* sender's full name */
109 char    *from;          /* sender's mail address */
110 int     verbose;
111 int     verify;
112 int     extract;
113 int     dodist;
114 int     rewritefrom;
115 int     status;         /* return value from procedures */
116 static int childid;     /* id from smtp child process */
117 TYPESIG die();
118 long    lclock = 0L;    /* the time we started (more or less) */
119
120
121 FILE *fp;               /* file pointer for message file */
122 extern FILE *tmpfile();
123
124 static struct swit switches[] = {
125 #define ARPASW    0
126     "ba", -2,
127 #define DAEMONSW  1
128     "bd", -2,
129 #define INITALSW  2
130     "bi", -2,
131 #define DELIVSW   3
132     "bm", -2,
133 #define QSUMSW    4
134     "bp", -2,
135 #define SMTPSW    5
136     "bs", -2,
137 #define ADRTSTSW  6
138     "bt", -2,
139 #define ADRVRFSW  7
140     "bv", -2,
141 #define CFGFRZSW  8
142     "bz", -2,
143 #define ALTCFGSW  9
144     "C", -1,
145 #define DBGVALSW 10
146     "d", -1,
147 #define FULLSW   11
148     "F", -1,
149 #define FROMSW   12
150     "f", -1,
151 #define HOPCNTSW 13
152     "h", -1,
153 #define MSGIDSW  14
154     "M", -1,
155 #define NOALISW  15
156     "n", -1,
157 #define QTIMESW  16
158     "q", -1,
159 #define OBSFRMSW 17
160     "r", -1,
161 #define EXTHDRSW 18
162     "t", -1,
163 #define VERBSW   19
164     "v", -1,
165 #define ALTALISW 20
166     "oA", -2,
167 #define NOCONSW   21
168     "oc", -2,
169 #define DLVMODSW 22
170     "od", -2,
171 #define NEWALISW 23
172     "oD", -2,
173 #define ERRMODSW 24
174     "oe", -2,
175 #define TMPMODSW 25
176     "oF", -2,
177 #define UFROMSW  26
178     "of", -2,
179 #define GIDSW    27
180     "og", -2,
181 #define HLPFILSW 28
182     "oH", -2,
183 #define NODOTSW  29
184     "oi", -2,
185 #define LOGLEVSW 30
186     "oL", -2,
187 #define MEOKSW   31
188     "om", -2,
189 #define OLDHDRSW 32
190     "oo", -2,
191 #define QDIRSW   33
192     "oQ", -2,
193 #define RTMOUTSW 34
194     "or", -2,
195 #define SFILESW  35
196     "oS", -2,
197 #define QMSGSW   36
198     "os", -2,
199 #define MTMOUTSW 37
200     "oT", -2,
201 #define TZSW     38
202     "ot", -2,
203 #define UIDSW    39
204     "ou", -2,
205     
206     NULL, 0
207     };
208
209 #if !defined(POSIX) && !defined(_POSIX_SOURCE)
210 extern char *mktemp();
211 #endif
212
213 static void removemsg();
214 static int  isheader(), sendfile();
215
216 /*ARGSUSED*/
217 main (argc, argv)
218 int    argc;
219 char **argv;
220 {
221     register char *cp;
222     char **argp = argv + 1;
223     
224 #ifdef LOCALE
225         setlocale(LC_ALL, "");
226 #endif
227     invo_name = r1bindex (argv[0], '/');
228     mts_init(argv[0]);
229     
230     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
231         (void) signal(SIGINT, die);
232     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
233         (void) signal(SIGHUP, die);
234     (void) signal(SIGTERM, die);
235     (void) signal(SIGPIPE, die);
236     
237     FullName = getfullname();
238     from = adrsprintf(NULLCP,NULLCP);
239     (void) time (&lclock);
240     
241     while ( (cp = *argp) &&  *cp == '-' ) {
242         argp++;
243         switch (smatch ( ++cp, switches )) {
244         case ARPASW:    /* smtp on stdin */
245         case SMTPSW:    /* smtp on stdin */
246             smtp();
247             exit(98);   /* should never happen */
248             
249         case DELIVSW:   /* just send mail */
250             continue;
251             
252         case ADRVRFSW:  /* verify mode */
253             verify = 1;
254             continue;
255             
256         case FROMSW:    /* from address */
257         case OBSFRMSW:  /* obsolete -f flag */
258             if (*(++cp) == '\0' &&
259                 (!(cp = *argp++) || *cp == '-'))
260                 adios (NULLCP, "missing argument to %s", argp[-2]);
261             /* At this point, cp points to the from name */
262             if (rewritefrom) {
263                 adios (NULLCP, "More than one \"from\" person");
264                 continue;
265             }
266             from = cp;
267             rewritefrom = 1;
268             continue;
269             
270         case EXTHDRSW:  /* read recipients from message */
271             extract = 1;
272             continue;
273             
274         case VERBSW:    /* give blow-by-blow description */
275             verbose = 1;
276             continue;
277             
278             /* These switches have no args. */
279         case QMSGSW:    /* always queue the message */
280         case DAEMONSW:  /* run as a daemon & wait for SMTP */
281         case INITALSW:  /* initialize the alias database */
282         case QSUMSW:    /* print summary of mail queue */
283         case ADRTSTSW:  /* test the addresses to debug config file */
284         case CFGFRZSW:  /* create the configuration freeze file */
285         case NOALISW:   /* do not do aliasing */
286         case NOCONSW:   /* do not initiate immediate host connection */
287         case NEWALISW:  /* run newaliases to rebuild db */
288         case UFROMSW:   /* save UNIX-style From lines at front of msg*/
289         case NODOTSW:   /* dots on line are not msg terminators */
290         case MEOKSW:    /* ok to send to me if I'm in an alias */
291         case OLDHDRSW:  /* msg may have old-style headers */
292             continue;
293             
294             /* These switches have string args. */
295         case ALTALISW:  /* use alternate alias file */
296         case ALTCFGSW:  /* use alternate configuration file */
297         case DBGVALSW:  /* set the debug value */
298         case FULLSW:    /* set full name */
299         case MSGIDSW:   /* try to deliver queued msg with msg-id */
300         case QTIMESW:   /* interval between queue passes */
301         case DLVMODSW:  /* set the delivery mode */
302         case ERRMODSW:  /* set the error mode */
303         case TMPMODSW:  /* the mode to use when creating tmp files */
304         case HLPFILSW:  /* the SMTP help file */
305         case QDIRSW:    /* directory into which to queue messages */
306         case RTMOUTSW:  /* timeout on reads */
307         case SFILESW:   /* save statistics in this file */
308         case MTMOUTSW:  /* timeout on messages in the queue */
309         case TZSW:      /* set the name of the timezone */
310             if (*(++cp) == '\0' &&
311                 (!(cp = *argp++) || *cp == '-'))
312                 adios (NULLCP, "missing argument to %s", argp[-2]);
313             /* At this point, cp points to the argument */
314             continue;   /* Ignore */
315             
316             /* These switches have numeric args. */
317         case HOPCNTSW:  /* hop count */
318         case GIDSW:     /* gid when calling mailers */
319         case LOGLEVSW:  /* the log level */
320         case UIDSW:     /* uid when calling mailers */
321             if (*(++cp) == '\0' &&
322                 (!(cp = *argp++) || *cp == '-'))
323                 adios (NULLCP, "missing argument to %s", argp[-2]);
324             /* At this point, cp points to the numeric arg */
325             if (!isdigit(*cp))
326                 adios (NULLCP, "non-numeric argument to %s", argp[-2]);
327             continue;   /* Ignore */
328         }
329     }
330     
331     (void) setuid(getuid());
332     
333     if (verify && extract)
334         adios (NULLCP, "mode not supported on header components");
335     
336     if (*argp == NULL && !extract)
337         adios (NULLCP, "usage: /usr/lib/sendmail [flags] addr...");
338     
339     strcpy (msgfname, "/tmp/sendmhXXXXXX");
340     if ( mktemp(msgfname) == NULL )
341         adios (msgfname, "can't create msg file ");
342     
343     if ( (fp = fopen(msgfname,"w") ) == NULL ) {
344         adios (msgfname, "error opening ");
345     }
346     
347     doheader(argp);
348     if ( verify ) {
349         (void) fclose(fp);
350         status = doverify();
351         removemsg();
352         exit ( status ) ;
353     }
354     dobody();
355     status = sendfile();
356     removemsg();
357     exit ( status );
358 }
359
360 static void removemsg()
361 {
362   if ( unlink(msgfname) != 0 )
363       perror("unlink");
364 }
365
366 doheader(argp)
367 char **argp;
368 {
369     char        line[BUFSIZ];
370     int         gotdate, gotfrom, gotsender, gotto;
371     
372     /* if we're not extracting the headers from the message, then we
373      * need to check to see if we need to do a "send" or a "dist".
374      */
375     
376     if ( !extract ) {
377         /* If we're doing a verify, just create a "To:" header. */
378         if ( ! verify ) {
379             gotdate = gotfrom = gotto = gotsender = dodist = 0;
380             while (fgets (line, BUFSIZ, stdin) != NULL) {
381                 if (line[0] == '\n')            /* end of header */
382                     break;
383                 if ( !isheader(line) )
384                     break;
385
386                 /* if any of the following headers are present, then we
387                  * want to do a dist.
388                  */
389                 if ( !gotdate && uprf(line, "date") )
390                     gotdate = dodist = 1;
391
392                 else if ( !gotto && (uprf(line, "to") || uprf(line, "cc")) )
393                     gotto = dodist = 1;
394
395                 else if ( uprf(line, "message-id") )
396                     dodist = 1;
397
398                 else if ( !gotsender && uprf(line, "sender") )
399                     gotsender = dodist = 1;
400                 
401                 else if ( uprf ( line, "resent-" ) ) {
402                     dodist = 1;
403                     (void) fputs("Prev-", fp);
404                 }
405                 
406                 /* See if we are re-writing the from line */
407                 if ( uprf(line, "from") ) {
408                     gotfrom = 1;
409                     if ( rewritefrom )
410                         dofrom();
411                     else
412                         (void) fputs(line,fp);
413                 }
414                 else
415                     (void) fputs(line,fp);
416             }
417         }
418         /* Now, generate a "to" line.  The first line is easy.
419          * Write the rest of the lines with a newline/tab so that we
420          * don't accidentally write a line that's too long to be parsed
421          * by post.
422          */
423         (void) fprintf (fp, "%sTo: %s", (dodist ? "Resent-" : "" ), *argp++);
424         while ( *argp )
425             (void) fprintf ( fp, ",\n\t%s", *argp++ );
426         (void) fputs("\n",fp);
427
428         /* If we're doing a dist, we must have a "Date:" and "From:" field.
429          */
430         if ( dodist ) {
431             if ( !gotdate )
432                 (void) fprintf (fp, "Date: %s\n", dtime (&lclock));
433             if ( !gotfrom )
434                 dofrom();
435         }
436 #ifdef  MMDFI                   /* sigh */
437         if ( !gotsender )
438             (void) fprintf (fp, "Sender: %s\n", from);
439 #endif  MMDFI
440     } else {    /* we're verifying, so just pass everything through */
441         while (fgets (line, BUFSIZ, stdin) != NULL) {
442             if (line[0] == '\n')                /* end of header */
443                 break;
444             
445             if ( rewritefrom && uprf(line, "from"))
446                 dofrom();
447             else
448                 (void) fputs(line,fp);
449         }
450     }
451     /* At this point, line is either a newline (end of header) or the
452      * first line of the body (poorly formatted message).  If line
453      * contains a line of body from a poorly formatted message, then
454      * print a newline to separate the header correctly, then print
455      * the body line.
456      */
457     if ( line[0] != '\n' )      /* i.e. a "body" line */
458         (void) fputc('\n', fp);
459     (void) fputs(line, fp);
460 }
461
462 static int isheader(s)
463 char *s;
464 {
465     register char *cp;
466
467     /* If the first character is a space, assume a continuation of a header */
468     if ( isspace(*s) )
469         return 1;
470
471     /* If there's no ':', it's not a header */
472     if ( (cp = index(s,':')) == NULL )
473         return 0;
474
475     /* If there's a space between BOL and ':', it's not a header */
476     while ( s < cp ) {
477         if ( isspace(*s) )
478             return 0;
479         s++;
480     }
481     return 1;
482 }
483
484 /* This procedure does the verify and returns the status */
485 doverify() {
486     char *command, buf[BUFSIZ], *bp;
487     FILE *verfp, *popen();
488     
489     /* set up the command line for post */
490     if ( (command = (char *)malloc((strlen(postproc) +
491                                     strlen(" -whom -check -verbose ") +
492                                     strlen(msgfname) + 1 )*sizeof(char)))
493         == NULL ) {
494         perror("malloc");
495         return NOTOK;
496     }
497     
498     (void) strcpy(command,postproc);
499     (void) strcat(command," -whom -check ");
500     if ( verbose )
501         (void) strcat(command, "-verbose " );
502     (void) strcat(command, msgfname);
503     
504     /* open up the pipe */
505     if ( (verfp = popen(command,"r")) == NULL )
506         return NOTOK;
507     
508     while ( fgets(buf, BUFSIZ, verfp) != NULL )
509         /* sendmail returns:
510          *   address:  result
511          * so we need to strip the extra post headers.
512          */
513         if ( verbose ) {
514             bp = buf;
515             while (isspace(*bp))
516                 bp++;
517             if ( *bp != '-' )
518                 (void) fputs(bp,stdout);
519         }
520     
521     /* return the error status of post */
522     return( pclose(verfp) >> 8 );
523 }
524
525 static int sendfile()
526 {
527     char *command, buf[BUFSIZ];
528     FILE *verfp, *popen();
529     
530     /* set up the command line for post */
531     if ( (command = (char *)malloc((strlen(postproc) +
532                                     strlen(" -dist -verbose ") +
533                                     strlen(msgfname) + 1 )*sizeof(char)))
534         == NULL ) {
535         perror("malloc");
536         return NOTOK;
537     }
538     
539     (void) strcpy(command,postproc);
540     (void) strcat(command," ");
541     if ( verbose )
542         (void) strcat(command, "-verbose " );
543     if ( dodist )
544         (void) strcat(command, "-dist " );
545     (void) strcat(command, msgfname);
546     
547     /* open up the pipe */
548     if ( (verfp = popen(command,"r")) == NULL )
549         return NOTOK;
550     
551     while ( fgets(buf, BUFSIZ, verfp) != NULL )
552         (void) fputs(buf,stdout);
553
554     /* return the error status of post */
555     return( pclose(verfp) >> 8 );
556 }
557
558 dofrom() {
559     char        line[128];
560     
561     if (FullName)
562         (void) sprintf(line, "From: %s <%s>\n", FullName, from);
563     else
564         (void) sprintf(line, "From: %s\n", from);
565     (void) fputs(line, fp);
566 }
567
568 dobody() {
569     register int    i;
570     char    buffer[BUFSIZ];
571     
572     while (!feof (stdin) && !ferror (stdin) &&
573            (i = fread (buffer, sizeof (char), sizeof (buffer), stdin)) > 0)
574         if (fwrite (buffer, sizeof (char), i , fp) != i )
575             adios (NULLCP, "Problem writing body");
576     
577     if (ferror (stdin))
578         adios (NULLCP, "Problem reading body");
579     
580     if ( fclose(fp) != 0 )
581         adios (NULLCP, "problem ending submission");
582 }
583
584 TYPESIG silentdie();
585
586 smtp()
587 {
588     int sd,len;
589     char buf[BUFSIZ], response[BUFSIZ];
590
591     if ((sd = client(NULLCP, "tcp", "smtp", 0, response)) == NOTOK)
592         adios (NULLCP, "cannot open smtp client process");
593
594     (void) signal(SIGCHLD, silentdie);
595
596     switch ((childid = fork())) {
597         case NOTOK:
598             adios (NULLCP, "unable to fork smtp process");
599         
600         case OK:        /* i.e. child */
601             (void) dup2(sd,0);
602             break;
603
604         default:        /* i.e. parent */
605             (void) dup2(sd,1);
606             break;
607     }
608     while ( (len = read(0, buf, BUFSIZ)) > 0)
609         (void) write (1, buf, len);
610
611     if (childid)
612         (void) kill(childid, SIGHUP);
613
614     exit(9);
615 }
616
617 /* ARGSUSED */
618 TYPESIG die(sig)
619 int sig;
620 {
621     if (fp) {
622         (void) fclose(fp);
623         (void) unlink(msgfname);
624     }
625     if (sig != SIGHUP)
626         (void) fprintf(stderr, "sendmail: dying from signal %d\n", sig);
627     exit(99);
628 }
629
630 /* ARGSUSED */
631
632 TYPESIG silentdie(sig)
633 int sig;
634 {
635     pidwait (childid, OK);
636     exit(0);
637 }
638 @
639
640
641 1.8
642 log
643 @TYPESIG
644 LOCALE
645 @
646 text
647 @d3 1
648 a3 1
649 static char Id[] = "$Id: sendmail.c,v 1.7 1992/10/20 17:27:08 jromine Exp jromine $";
650 d151 3
651 d155 4
652 a158 1
653 main(argc, argv) int argc; char **argv; {
654 d298 2
655 a299 1
656 static removemsg() {
657 d304 3
658 a306 1
659 doheader(argp) char **argp; {
660 d400 3
661 a402 1
662 static isheader(s) char *s; {
663 d463 2
664 a464 1
665 static sendfile() {
666 @
667
668
669 1.7
670 log
671 @remove debugging print
672 @
673 text
674 @d3 1
675 a3 1
676 static char Id[] = "$Id: sendmail.c,v 1.6 1992/05/19 21:07:35 jromine Exp jromine $";
677 d39 3
678 d55 1
679 a55 1
680 int     die();
681 d156 3
682 d510 1
683 a510 1
684 int silentdie();
685 d544 1
686 a544 1
687 die(sig)
688 d558 1
689 a558 1
690 silentdie(sig)
691 @
692
693
694 1.6
695 log
696 @AIX
697 >
698 @
699 text
700 @d3 1
701 a3 1
702 static char Id[] = "$Id: sendmail.c,v 1.5 1992/01/24 22:36:27 jromine Exp jromine $";
703 a286 2
704   puts(msgfname);
705   /*
706 a288 1
707     */
708 @
709
710
711 1.5
712 log
713 @typo
714 @
715 text
716 @d3 1
717 a3 1
718 static char Id[] = "$Id: sendmail.c,v 1.4 1992/01/24 22:31:43 jromine Exp jromine $";
719 d141 1
720 a141 1
721     NULL, NULL
722 d143 4
723 @
724
725
726 1.4
727 log
728 @add id, use mktemp
729 @
730 text
731 @d3 1
732 a3 1
733 static char Id[] = "$Id$";
734 a556 2
735
736 static 
737 @
738
739
740 1.3
741 log
742 @Fixed one more lint boo-boo.
743 <erickson>
744 @
745 text
746 @d1 4
747 d7 2
748 d42 1
749 a42 1
750 char    msgfname[L_tmpnam];     /* name of message file */
751 d261 2
752 a262 1
753     if ( tmpnam(msgfname) == NULL )
754 d557 2
755 @
756
757
758 1.2
759 log
760 @Added lots of (void)'s to make lint happy.
761 <erickson>
762 @
763 text
764 @d542 2
765 @
766
767
768 1.1
769 log
770 @Initial revision
771 @
772 text
773 @d47 1
774 a47 1
775 long    clock = 0L;     /* the time we started (more or less) */
776 d155 1
777 a155 1
778     (void) time (&clock);
779 d176 1
780 a176 1
781                 syserr ("missing argument to %s", argp[-2]);
782 d179 1
783 a179 1
784                 syserr("More than one \"from\" person");
785 d228 1
786 a228 1
787                 syserr ("missing argument to %s", argp[-2]);
788 d239 1
789 a239 1
790                 syserr ("missing argument to %s", argp[-2]);
791 d242 1
792 a242 1
793                 syserr ("non-numeric argument to %s", argp[-2]);
794 d250 1
795 a250 1
796         syserr("mode not supported on header components");
797 d253 1
798 a253 1
799         syserr("usage: /usr/lib/sendmail [flags] addr...");
800 d256 1
801 a256 1
802         syserr ("%s: can't create msg file.",invo_name);
803 d259 1
804 a259 2
805         perror("msgfname");
806         syserr ("%s: exiting.",invo_name);
807 d347 1
808 a347 1
809                 fprintf (fp, "Date: %s\n", dtime (&clock));
810 d353 1
811 a353 1
812             fprintf (fp, "Sender: %s\n", from);
813 d431 1
814 a431 1
815                 fputs(bp,stdout);
816 d464 1
817 a464 1
818         fputs(buf,stdout);
819 d487 1
820 a487 1
821             syserr("Problem writing body");
822 d490 1
823 a490 1
824         syserr("Problem reading body");
825 d493 1
826 a493 1
827         syserr("problem ending submission");
828 d504 1
829 a504 1
830         syserr("cannot open smtp client process");
831 d510 1
832 a510 1
833             syserr("unable to fork smtp process");
834 d524 1
835 a524 1
836         kill(childid, SIGHUP);
837 d529 1
838 a529 9
839 /*VARARGS1*/
840 syserr(fmt, a, b)
841 char    *fmt, *a, *b;
842 {
843     (void) fprintf(stderr, fmt, a, b);
844     (void) fputc('\n', stderr);
845     exit(9);
846 }
847
848 d534 2
849 a535 2
850         fclose(fp);
851         unlink(msgfname);
852 @