9 date 92.11.24.18.37.01; author jromine; state Exp;
14 date 92.11.04.01.02.39; author jromine; state Exp;
19 date 92.10.20.17.27.08; author jromine; state Exp;
24 date 92.05.19.21.07.35; author jromine; state Exp;
29 date 92.01.24.22.36.27; author jromine; state Exp;
34 date 92.01.24.22.31.43; author jromine; state Exp;
39 date 91.05.22.17.59.50; author erickson; state Exp;
44 date 91.05.20.17.31.04; author erickson; state Exp;
49 date 91.05.17.15.31.52; author jromine; state Exp;
65 static char Id[] = "$Id: sendmail.c,v 1.8 1992/11/04 01:02:39 jromine Exp jromine $";
70 * Contributed by Scott Erickson <erickson@@ics.uci.edu>
72 /* Include files glommed from post.c */
75 #include "../h/addrsbr.h"
76 #include "../h/aliasbr.h"
77 #include "../h/dropsbr.h"
78 #include "../zotnet/tws.h"
84 #include <sys/types.h>
86 #include "../mts/mmdf/util.h"
87 #include "../mts/mmdf/mmdf.h"
89 #include "../zotnet/mts.h"
92 #include <sys/ioctl.h>
97 #include "../mts/sendmail/smail.h"
105 char *SMTPSRVR = "smtpsrvr";
107 char msgfname[50]; /* name of message file */
108 char *FullName; /* sender's full name */
109 char *from; /* sender's mail address */
115 int status; /* return value from procedures */
116 static int childid; /* id from smtp child process */
118 long lclock = 0L; /* the time we started (more or less) */
121 FILE *fp; /* file pointer for message file */
122 extern FILE *tmpfile();
124 static struct swit switches[] = {
209 #if !defined(POSIX) && !defined(_POSIX_SOURCE)
210 extern char *mktemp();
213 static void removemsg();
214 static int isheader(), sendfile();
222 char **argp = argv + 1;
225 setlocale(LC_ALL, "");
227 invo_name = r1bindex (argv[0], '/');
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);
237 FullName = getfullname();
238 from = adrsprintf(NULLCP,NULLCP);
239 (void) time (&lclock);
241 while ( (cp = *argp) && *cp == '-' ) {
243 switch (smatch ( ++cp, switches )) {
244 case ARPASW: /* smtp on stdin */
245 case SMTPSW: /* smtp on stdin */
247 exit(98); /* should never happen */
249 case DELIVSW: /* just send mail */
252 case ADRVRFSW: /* verify mode */
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 */
263 adios (NULLCP, "More than one \"from\" person");
270 case EXTHDRSW: /* read recipients from message */
274 case VERBSW: /* give blow-by-blow description */
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 */
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 */
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 */
326 adios (NULLCP, "non-numeric argument to %s", argp[-2]);
327 continue; /* Ignore */
331 (void) setuid(getuid());
333 if (verify && extract)
334 adios (NULLCP, "mode not supported on header components");
336 if (*argp == NULL && !extract)
337 adios (NULLCP, "usage: /usr/lib/sendmail [flags] addr...");
339 strcpy (msgfname, "/tmp/sendmhXXXXXX");
340 if ( mktemp(msgfname) == NULL )
341 adios (msgfname, "can't create msg file ");
343 if ( (fp = fopen(msgfname,"w") ) == NULL ) {
344 adios (msgfname, "error opening ");
360 static void removemsg()
362 if ( unlink(msgfname) != 0 )
370 int gotdate, gotfrom, gotsender, gotto;
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".
377 /* If we're doing a verify, just create a "To:" header. */
379 gotdate = gotfrom = gotto = gotsender = dodist = 0;
380 while (fgets (line, BUFSIZ, stdin) != NULL) {
381 if (line[0] == '\n') /* end of header */
383 if ( !isheader(line) )
386 /* if any of the following headers are present, then we
389 if ( !gotdate && uprf(line, "date") )
390 gotdate = dodist = 1;
392 else if ( !gotto && (uprf(line, "to") || uprf(line, "cc")) )
395 else if ( uprf(line, "message-id") )
398 else if ( !gotsender && uprf(line, "sender") )
399 gotsender = dodist = 1;
401 else if ( uprf ( line, "resent-" ) ) {
403 (void) fputs("Prev-", fp);
406 /* See if we are re-writing the from line */
407 if ( uprf(line, "from") ) {
412 (void) fputs(line,fp);
415 (void) fputs(line,fp);
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
423 (void) fprintf (fp, "%sTo: %s", (dodist ? "Resent-" : "" ), *argp++);
425 (void) fprintf ( fp, ",\n\t%s", *argp++ );
426 (void) fputs("\n",fp);
428 /* If we're doing a dist, we must have a "Date:" and "From:" field.
432 (void) fprintf (fp, "Date: %s\n", dtime (&lclock));
436 #ifdef MMDFI /* sigh */
438 (void) fprintf (fp, "Sender: %s\n", from);
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 */
445 if ( rewritefrom && uprf(line, "from"))
448 (void) fputs(line,fp);
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
457 if ( line[0] != '\n' ) /* i.e. a "body" line */
458 (void) fputc('\n', fp);
459 (void) fputs(line, fp);
462 static int isheader(s)
467 /* If the first character is a space, assume a continuation of a header */
471 /* If there's no ':', it's not a header */
472 if ( (cp = index(s,':')) == NULL )
475 /* If there's a space between BOL and ':', it's not a header */
484 /* This procedure does the verify and returns the status */
486 char *command, buf[BUFSIZ], *bp;
487 FILE *verfp, *popen();
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)))
498 (void) strcpy(command,postproc);
499 (void) strcat(command," -whom -check ");
501 (void) strcat(command, "-verbose " );
502 (void) strcat(command, msgfname);
504 /* open up the pipe */
505 if ( (verfp = popen(command,"r")) == NULL )
508 while ( fgets(buf, BUFSIZ, verfp) != NULL )
511 * so we need to strip the extra post headers.
518 (void) fputs(bp,stdout);
521 /* return the error status of post */
522 return( pclose(verfp) >> 8 );
525 static int sendfile()
527 char *command, buf[BUFSIZ];
528 FILE *verfp, *popen();
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)))
539 (void) strcpy(command,postproc);
540 (void) strcat(command," ");
542 (void) strcat(command, "-verbose " );
544 (void) strcat(command, "-dist " );
545 (void) strcat(command, msgfname);
547 /* open up the pipe */
548 if ( (verfp = popen(command,"r")) == NULL )
551 while ( fgets(buf, BUFSIZ, verfp) != NULL )
552 (void) fputs(buf,stdout);
554 /* return the error status of post */
555 return( pclose(verfp) >> 8 );
562 (void) sprintf(line, "From: %s <%s>\n", FullName, from);
564 (void) sprintf(line, "From: %s\n", from);
565 (void) fputs(line, fp);
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");
578 adios (NULLCP, "Problem reading body");
580 if ( fclose(fp) != 0 )
581 adios (NULLCP, "problem ending submission");
589 char buf[BUFSIZ], response[BUFSIZ];
591 if ((sd = client(NULLCP, "tcp", "smtp", 0, response)) == NOTOK)
592 adios (NULLCP, "cannot open smtp client process");
594 (void) signal(SIGCHLD, silentdie);
596 switch ((childid = fork())) {
598 adios (NULLCP, "unable to fork smtp process");
600 case OK: /* i.e. child */
604 default: /* i.e. parent */
608 while ( (len = read(0, buf, BUFSIZ)) > 0)
609 (void) write (1, buf, len);
612 (void) kill(childid, SIGHUP);
623 (void) unlink(msgfname);
626 (void) fprintf(stderr, "sendmail: dying from signal %d\n", sig);
632 TYPESIG silentdie(sig)
635 pidwait (childid, OK);
649 static char Id[] = "$Id: sendmail.c,v 1.7 1992/10/20 17:27:08 jromine Exp jromine $";
653 main(argc, argv) int argc; char **argv; {
659 doheader(argp) char **argp; {
662 static isheader(s) char *s; {
671 @remove debugging print
676 static char Id[] = "$Id: sendmail.c,v 1.6 1992/05/19 21:07:35 jromine Exp jromine $";
702 static char Id[] = "$Id: sendmail.c,v 1.5 1992/01/24 22:36:27 jromine Exp jromine $";
718 static char Id[] = "$Id: sendmail.c,v 1.4 1992/01/24 22:31:43 jromine Exp jromine $";
733 static char Id[] = "$Id$";
742 @Fixed one more lint boo-boo.
750 char msgfname[L_tmpnam]; /* name of message file */
753 if ( tmpnam(msgfname) == NULL )
760 @Added lots of (void)'s to make lint happy.
775 long clock = 0L; /* the time we started (more or less) */
778 (void) time (&clock);
781 syserr ("missing argument to %s", argp[-2]);
784 syserr("More than one \"from\" person");
787 syserr ("missing argument to %s", argp[-2]);
790 syserr ("missing argument to %s", argp[-2]);
793 syserr ("non-numeric argument to %s", argp[-2]);
796 syserr("mode not supported on header components");
799 syserr("usage: /usr/lib/sendmail [flags] addr...");
802 syserr ("%s: can't create msg file.",invo_name);
806 syserr ("%s: exiting.",invo_name);
809 fprintf (fp, "Date: %s\n", dtime (&clock));
812 fprintf (fp, "Sender: %s\n", from);
821 syserr("Problem writing body");
824 syserr("Problem reading body");
827 syserr("problem ending submission");
830 syserr("cannot open smtp client process");
833 syserr("unable to fork smtp process");
836 kill(childid, SIGHUP);
843 (void) fprintf(stderr, fmt, a, b);
844 (void) fputc('\n', stderr);