]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/RCS/sendmail.c,v
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / 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 @