|
|
1.1 root 1: From ulysses!andys Wed Dec 12 17:06:59 EST 1990
2: Received: from localhost [127.0.0.1] by odius; Wed Dec 12 17:07:01 EST 1990
3: To: ches
4: Subject: here it is
5: Date: Wed, 12 Dec 90 17:06:59 EST
6:
7: Here is the stuff to get peernames in DEBUG alerts and Received lines.
8:
9: smtp/smtpd.sh is a shell wrapper to spawn smtpd from inetd.
10: It will call getpeer to set the magic option. Remember to
11: do similar magic in your dksrvtab (or whatever it is on the mips)
12:
13: smtp/*.c are the changes to add the magic option and use it
14: in Received lines, DEBUG alerts, and the LOG_INFO which has the
15: transaction summary.
16:
17: smtp/makefile has been fixed to do a chgrp when installing
18: smtpqer. Since it is setgid, we'd not like that to be random.
19: It's also necessary so that smtpqer can write in a directory
20: that was created by a program running as root. The makefile
21: also install smtpd.sh
22:
23: misc/getpeer.c is a program that gets the peername if stdin
24: is a socket
25:
26: misc/maphost.c does a maphost on its argument.
27:
28: misc/makefile will make and install those things if asked
29: by make maphost getpeer or make install.maphost install.getpeer.
30:
31: ----------------------cut me here-------------------------
32: # This is a shell archive. Remove anything before this line,
33: # then unpack it by saving it in a file and typing "sh file".
34: #
35: # Wrapped by andys on Wed Dec 12 17:03:07 EST 1990
36: # Contents: smtp/smtpd.sh smtp/smtpd.c smtp/conversed.c smtp/from822.c
37: # smtp/makefile misc/getpeer.c misc/maphost.c misc/makefile
38:
39: echo x - smtp/smtpd.sh
40: sed 's/^@//' > "smtp/smtpd.sh" <<'@//E*O*F smtp/smtpd.sh//'
41: #!/bin/sh
42: #
43: # spawn smtpd with peer identification a -c option
44: exec LIBDIR/smtpd -c "`LIBDIR/getpeer`" $*
45: @//E*O*F smtp/smtpd.sh//
46: chmod u=rw,g=r,o=r smtp/smtpd.sh
47:
48: echo x - smtp/smtpd.c
49: sed 's/^@//' > "smtp/smtpd.c" <<'@//E*O*F smtp/smtpd.c//'
50: #include <stdio.h>
51: #include <netdb.h>
52: #include <sys/types.h>
53: #include <netinet/in.h>
54: #include <sys/socket.h>
55: #include "smtp.h"
56: #include "sys.h"
57:
58: int norun;
59: int log;
60: int debug = 0;
61:
62: char *progname, *helohost, *thishost;
63: extern char *sysname_read();
64:
65: char *mypeer;
66:
67: main(argc, argv)
68: char *argv[];
69: {
70: int c;
71: extern int optind;
72: extern char *optarg;
73: char *malloc();
74:
75: progname = argv[0];
76: Openlog("smtpd", LOG_PID, LOG_SMTPD);
77: setlogmask(LOG_UPTO(LOG_INFO));
78:
79: umask(2);
80:
81: while((c = getopt(argc, argv, "H:h:DnL:c:")) != EOF) {
82: switch(c) {
83:
84: case 'H': helohost = optarg; break;
85: case 'h': thishost = optarg; break;
86: case 'L': setloglevel(optarg); break;
87: case 'n': norun++;
88: case 'D': debug++; break;
89: case 'c': mypeer = malloc(256);
90: if ( mypeer != (char *) NULL )
91: strncpy(mypeer, optarg, 256);
92: break;
93: case '?':
94: default:
95: Syslog(LOG_CRIT, "%s: usage\n", progname);
96: exit(2);
97: }
98: }
99: if(helohost == NULL)
100: helohost=sysname_read();
101:
102: converse(stdin, stdout);
103: /* NOTREACHED */
104: return 0;
105: }
106: @//E*O*F smtp/smtpd.c//
107: chmod u=rw,g=r,o=r smtp/smtpd.c
108:
109: echo x - smtp/conversed.c
110: sed 's/^@//' > "smtp/conversed.c" <<'@//E*O*F smtp/conversed.c//'
111: #ifndef lint
112: static char *sccsid = "@(#)converse.c 1.9 87/07/31";
113: #endif lint
114: /* Copyright 1984 Massachusetts Institute of Technology
115:
116: Permission to use, copy, modify, and distribute this program
117: for any purpose and without fee is hereby granted, provided
118: that this copyright and permission notice appear on all copies
119: and supporting documentation, the name of M.I.T. not be used
120: in advertising or publicity pertaining to distribution of the
121: program without specific prior permission, and notice be given
122: in supporting documentation that copying and distribution is
123: by permission of M.I.T. M.I.T. makes no representations about
124: the suitability of this software for any purpose. It is pro-
125: vided "as is" without express or implied warranty. */
126:
127: /*
128: * I've raped this code severely. Bugs could be
129: * MIT's or mine. -- presotto
130: *
131: * Me too. -- ches
132: */
133:
134: /*
135: * smtpd - World's most trivial SMTP server. Only accepts the MAIL, FROM,
136: * RCPT, and DATA commands. Generates a data file for the mail
137: * daemon and kicks the mail daemon off.
138: */
139:
140: #include <stdio.h>
141: #include <signal.h>
142: #include <ctype.h>
143:
144: #include <fcntl.h>
145: #include <string.h>
146: #include <sysexits.h>
147:
148: #include "mail.h"
149: #include "smtp.h"
150: #include "cmds.h"
151: #include "string.h"
152:
153: /* fundamental constants */
154: #define TRUE 1
155: #define FALSE 0
156: #define SECONDS 1
157: #define MINUTES 60
158: #define HOURS (60 * MINUTES)
159:
160: /* tunable constants */
161: #define SHORTTIME (5 * MINUTES) /* enough time for easy stuff */
162: #define LONGTIME (2 * HOURS) /* max time, DATA to `.' */
163:
164:
165: static string *rcvrs;
166:
167: FILE *datafd; /* data file descriptor */
168: FILE *fi; /* fd from remote host */
169: FILE *fo; /* fd to remote host */
170:
171: char dataname[NAMSIZ], rcptto[BUFSIZ]; /* data file name */
172:
173: typedef int event;
174:
175: static void terminate();
176:
177: extern char *convertaddr();
178: extern char *UPASROOT;
179: extern int death();
180: extern int alarmsend();
181: extern char *helohost;
182: extern char *thishost;
183: extern int queuing;
184: extern int norun;
185: extern char *spoolsubdir[];
186: extern char *mypeer;
187:
188: int n_rcpt = 0;
189: long nbytes = 0;
190: int virus = 0;;
191:
192: static char mailfrom[BUFSIZ];
193: static char *fromaddr;
194:
195:
196: #ifndef NOFILE
197: #define NOFILE 32
198: #endif /*NOFILE*/
199:
200: SIGRETURN
201: alarmtr(s)
202: int s;
203: {
204: Syslog(LOG_INFO, "timed out");
205: death(EX_TEMPFAIL);
206: }
207:
208: /*
209: * This is the routine which processes incoming smtp commands from the
210: * user. It goes to sleep awaiting network input. When a complete
211: * command is received, the tcp receiver task awakens us to process it.
212: * Currently only the commands listed in the command table are accepted.
213: * This routine never returns.
214: */
215: converse(rfi, rfo)
216: FILE *rfi, *rfo;
217: {
218: char greeting[MAXSTR];
219:
220: fo = rfo;
221: fi = rfi;
222:
223: (void) signal(SIGALRM, alarmtr);
224: (void) alarm(SHORTTIME); /* make sure we eventually go away */
225: (void) sprintf(greeting, "220 %s SMTP\n", helohost);
226: csend(LOG_DEBUG, greeting);
227:
228: do_helo(fi, fo); /* wait for the hello */
229:
230: /*
231: * avoid annoying interuptions
232: */
233: signal(SIGHUP, SIG_IGN);
234: signal(SIGPIPE, SIG_IGN);
235:
236: for (;;) { /* until QUIT */
237: n_rcpt = 0;
238: rcvrs = s_reset(rcvrs);
239: *dataname = *rcptto = 0;
240: fromaddr = 0;
241: if (!do_mail(fi, fo))
242: continue; /* wait for the mail command */
243: while (do_rcpt(fi, fo)) /* do all the recipients */
244: n_rcpt++;
245: (void) alarm(LONGTIME);
246: do_data(fi, fo); /* do the data */
247: }
248: }
249:
250: /*
251: * Wait for the user to send the HELO command. Punt out if he sends
252: * QUIT or RSET.
253: *
254: * The spooling directory depends on the calling host. The host name
255: * is used to connect to the appropriate spool directory.
256: */
257: do_helo(fi, fo)
258: FILE *fi, *fo;
259: {
260: char cmdbuf[MAXSTR];
261: char greeting[MAXSTR], *nlptr;
262: int buflen;
263: char *hp;
264: char *parse_hello();
265:
266: for (;;) { /* until HELO, or QUIT */
267: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */
268: switch (cmdparse(cmdbuf, buflen)) {
269: case QUIT:
270: quit(fi, fo);
271: case RSET:
272: case NOOP:
273: csend(LOG_DEBUG, "250 OK\n");
274: continue;
275: case HELO:
276: hp = parse_hello(cmdbuf, sizeof(cmdbuf));
277: Syslog(LOG_DEBUG, "HELO from %s", hp);
278: if(gotodir(hp)<0){
279: csend(LOG_ALERT, "451 Transaction failed -- Could not access spool directory.\n");
280: death(EX_OSERR);
281: }
282: (void) sprintf(greeting, "250 %s\n", helohost);
283: csend(LOG_DEBUG, greeting);
284: return;
285: case DEBG:
286: if ((char *)0 != mypeer ) {
287: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer);
288: }
289: else
290: Syslog(LOG_ALERT, "DEBUG attempt");
291: csend(LOG_DEBUG, "200 OK\n");
292: virus = 1;
293: continue;
294: case NONE:
295: bitch(cmdbuf, fo);
296: continue;
297: default:
298: csend(LOG_DEBUG, "503 Expecting HELO\n");
299: continue;
300: }
301: }
302: }
303:
304: /*
305: * Wait for the user to send the MAIL command. Punt out if he sends
306: * QUIT. Return false if he said RSET, so we can start over.
307: */
308: do_mail(fi, fo)
309: FILE *fi, *fo;
310: {
311: char cmdbuf[MAXSTR];
312: char gripe[MAXSTR], *nlptr;
313: int buflen;
314:
315: for (;;) { /* until MAIL, QUIT, or RSET */
316: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */
317: switch (cmdparse(cmdbuf, buflen)) {
318: case QUIT:
319: quit(fi, fo);
320: case NOOP:
321: csend(LOG_DEBUG, "250 OK\n");
322: continue;
323: case MAIL:
324: strcpy(mailfrom, cmdbuf);
325: csend(LOG_DEBUG, "250 OK\n");
326: return(TRUE);
327: case DEBG:
328: if ((char *)0 != mypeer) {
329: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer);
330: }
331: else
332: Syslog(LOG_ALERT, "DEBUG attempt");
333: csend(LOG_WARNING, "200 OK\n");
334: virus = 1;
335: continue;
336: case VRFY:
337: csend(LOG_INFO, "252 Cannot VRFY user\n");
338: continue;
339: case NONE:
340: bitch(cmdbuf, fo);
341: continue;
342: case RSET:
343: csend(LOG_DEBUG, "250 OK\n");
344: return(FALSE);
345: default:
346: csend(LOG_DEBUG, "503 Expecting MAIL\n");
347: continue;
348: }
349: }
350: }
351:
352: /*
353: * Wait for the user to send the RCPT command. Punt out if he sends
354: * QUIT or RSET. Returns TRUE if a RCPT command was received, FALSE
355: * if a DATA command was received.
356: */
357: do_rcpt(fi, fo)
358: FILE *fi, *fo;
359: {
360: char cmdbuf[MAXSTR];
361: char gripe[MAXSTR], *nlptr;
362: int buflen;
363:
364: for (;;) { /* until RCPT, DATA, QUIT, or RSET */
365: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */
366: switch (cmdparse(cmdbuf, buflen)) {
367: case QUIT:
368: quit(fi, fo);
369: case NOOP:
370: csend(LOG_DEBUG, "250 OK\n");
371: continue;
372: case RCPT:
373: if (!parse_rcpt(cmdbuf, buflen)) {
374: csend(LOG_DEBUG, "501 Syntax error in recipient name\n");
375: continue;
376: }
377: csend(LOG_DEBUG, "250 OK\n");
378: return(TRUE);
379: case DATA:
380: if (*s_to_c(rcvrs) == 0) {
381: csend(LOG_DEBUG, "503 Expecting RCPT\n");
382: continue;
383: }
384: if (!init_xfr()) { /* set up data file */
385: csend(LOG_ALERT, "451 Can't initialize files in spool directory\n");
386: death(EX_CANTCREAT);
387: }
388: csend(LOG_DEBUG, "354 Start mail input; end with <CRLF>.<CRLF>\n");
389: return(FALSE);
390: case VRFY:
391: csend(LOG_INFO, "252 Cannot VRFY user\n");
392: continue;
393: case DEBG:
394: if ((char *)0 != mypeer) {
395: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer);
396: }
397: else
398: Syslog(LOG_ALERT, "DEBUG attempt");
399: csend(LOG_WARNING, "200 OK\n");
400: virus = 1;
401: continue;
402: case RSET: /* this code doesn't handle this here. Feign ignorance. */
403: case NONE:
404: bitch(cmdbuf, fo);
405: continue;
406: default:
407: csend(LOG_DEBUG, "503 Expecting RCPT or DATA\n");
408: continue;
409: }
410: }
411: }
412:
413: /*
414: * input a line at a time till a <cr>.<cr>. return the count of the characters
415: * input. if EOF is reached, return -1. if <cr>.<cr> is reached, return 0.
416: */
417: static int atend; /* true when <cr>.<cr> is reached */
418:
419: char *
420: smfgets(buf, len, fi)
421: char *buf;
422: int len;
423: FILE *fi;
424: {
425: int n;
426: int i;
427:
428: if(atend)
429: return NULL;
430: n = tgets(buf, len, fi);
431: if (n < 0)
432: return NULL;
433: if (buf[0] == '.') {
434: if(buf[1] == '\n'){
435: atend = 1;
436: return NULL;
437: } else if(buf[1] == '.'){
438: for(i=1; i<=n; i++)
439: buf[i-1] = buf[i];
440: }
441: }
442: nbytes += n;
443: return buf;
444: }
445:
446: do_data(fi, fo)
447: FILE *fi, *fo;
448: {
449: string *cc;
450: int pid, wpid;
451: char gripe[MAXSTR];
452: char cmd[MAXSTR];
453: char ctlfile[MAXSTR];
454: int ac, i;
455: char *cp;
456:
457: clearerr(fi);
458: clearerr(datafd);
459:
460: /*
461: * read data message
462: */
463: atend = nbytes = 0;
464: from822(thishost, smfgets, fi, datafd, fromaddr, helohost);
465: fflush(datafd);
466: if(ferror(datafd) || ferror(fi)){
467: fclose(datafd);
468: unlink(dataname);
469: csend(LOG_ALERT, "451 Transaction failed -- error writing data file\n");
470: death(EX_IOERR);
471: }
472: fclose(datafd);
473:
474: /*
475: * create a control file. the two lines are
476: * <reply-address> <recipients>
477: * <recipients>
478: */
479: cc = s_new();
480: s_append(cc, fromaddr ? fromaddr : "postmaster");
481: s_append(cc, " ");
482: s_append(cc, s_to_c(rcvrs));
483: s_append(cc, "\n");
484: s_append(cc, s_to_c(rcvrs));
485: s_append(cc, "\n");
486: if(mkctlfile('X', dataname, s_to_c(cc))<0){
487: unlink(dataname);
488: csend(LOG_ALERT, "451 Transaction failed -- can't make control file\n");
489: death(EX_CANTCREAT);
490: }
491: s_free(cc);
492: csend(LOG_DEBUG, "250 OK\n");
493: if ((char *)0 != mypeer)
494: Syslog(LOG_INFO, "%s(%s) sent %d bytes to %s\n",
495: fromaddr ? fromaddr : "postmaster", mypeer, nbytes,
496: s_to_c(rcvrs));
497: else
498: Syslog(LOG_INFO, "%s sent %d bytes to %s\n",
499: fromaddr ? fromaddr : "postmaster", nbytes,
500: s_to_c(rcvrs));
501:
502:
503: /*
504: * reinitialize all the data pointers
505: */
506: rcvrs = s_reset(rcvrs);
507: nbytes = 0;
508: *dataname = *rcptto = 0;
509: fromaddr = 0;
510:
511: }
512:
513: /*
514: * Create the data file for the transfer. Get unique
515: * names and create the files.
516: */
517: init_xfr()
518: {
519: int dfd; /* file desc. for data file */
520: char *cp;
521:
522: strcpy(dataname, "D.xxxxxxxxxxxx");
523: if((dfd = mkdatafile(dataname)) < 0)
524: return FALSE;
525: datafd = fdopen(dfd, "w"); /* make stdio descriptor */
526: if (datafd == NULL)
527: return FALSE;
528:
529: /*
530: * find the sender name if any
531: */
532: if(*mailfrom){
533:
534: /* skip noise */
535: for(cp=mailfrom+sizeof("MAIL FROM:")-1; *cp; cp++)
536: if(strchr(";<>{}()\n| \t", *cp)==NULL)
537: break;
538: fromaddr = cp;
539:
540: /* find address */
541: for(; *cp; cp++)
542: if(strchr(";<>{}()\n| \t", *cp)!=NULL){
543: *cp = '\0';
544: break;
545: }
546: }
547: if(fromaddr)
548: fromaddr = convertaddr(fromaddr);
549:
550: return TRUE;
551: }
552:
553: /*
554: * Give up on the transfer. Unlink the data file (if any),
555: * close the tcp connection, and exit.
556: */
557: quit(fi, fo)
558: FILE *fi, *fo;
559: {
560: int i;
561: char greeting[MAXSTR];
562:
563: (void) sprintf(greeting, "221 %s Terminating\n", helohost);
564: csend(LOG_DEBUG, greeting);
565: (void) fclose(fi);
566: (void) fclose(fo);
567: Syslog(LOG_DEBUG, "finished.\n");
568:
569: /*
570: * run the queue from this caller
571: */
572: for(i=0; i<NOFILE; i++)
573: close(i);
574: open("/dev/null", 0);
575: open("/dev/null", 1);
576: open("/dev/null", 1);
577: if(!norun)
578: smtpsched("Dsmtpsched", spoolsubdir);
579:
580: exit(0);
581: }
582:
583: /*
584: * Parse the command part off the specified buffer. Return the strchr
585: * of the command in the command table(or 0 if the command is not
586: * recognized).
587: * The commands and indices accepted are listed in the include file
588: * "cmds.h".
589: * If the len parameter is -1 (as returned by tgets), issue the QUIT command.
590: * This non-protocol extension was added to cool the jets of sail.stanford.edu.
591: */
592: cmdparse(buf, len)
593: char *buf;
594: int len;
595: {
596: register char *cmdp, *bufp; /* command, buffer ptrs. */
597: register struct cmdtab *ct; /* cmd table ptr */
598: register int i; /* strchr in cmd table */
599: int clen; /* length of this command */
600:
601: if (len == -1) { /* EOF */
602: buf = "QUIT";
603: len = strlen(buf);
604: }
605: for (ct = &cmdtab[1], i = 1; ct->c_name != NULL; ct++, i++) {
606: clen = ct->c_len;
607: if (len < clen) /* buffer shorter than command? */
608: continue;
609: /* case-insensitive matching of command names */
610: for (cmdp = ct->c_name, bufp = buf;
611: clen > 0 && *cmdp == (ISLOWER(*bufp) ? TOUPPER(*bufp) : *bufp);
612: cmdp++, bufp++, clen--)
613: ;
614: if (clen == 0) { /* success */
615: /* sendmail compatibility */
616: if (i == ONEX || i == VERB)
617: i = NOOP;
618: return i;
619: }
620: }
621: return 0;
622: }
623:
624: /*
625: * Parse a hello and return a pointer to name of the last two elements
626: * of the calling machine's domain name (or last 14 chars).
627: */
628: char *
629: parse_hello(buf, len)
630: char *buf;
631: int len;
632: {
633: char *bp = buf;
634: char *lp;
635: int dots;
636:
637: /* skip command */
638: bp[len-1] = 0;
639: for(; *bp && !isspace(*bp); bp++)
640: ;
641: /* skip white */
642: for(; isspace(*bp); bp++)
643: ;
644: /* skip arg */
645: lp = bp;
646: for(; *bp && !isspace(*bp); bp++)
647: ;
648: /* null terminate */
649: *bp = 0;
650:
651: return lp;
652: }
653:
654: static char *to; /* ptr. into request buffer */
655:
656: /*
657: * Parse the recipient spec in the buffer. Start by stripping the
658: * command off the front of the buffer. Then call canon() to convert
659: * the recpient name into a format acceptable to the mailer daemon
660: * (ie. !-format).
661: * Returns TRUE if parsed successfully, FALSE otherwise.
662: */
663: /* ARGSUSED len */
664: parse_rcpt(buf, len)
665: char *buf; /* command buffer */
666: int len; /* size of buffer string */
667: {
668: register char *from; /* ptr to recipient name */
669: char *end;
670: char *rv;
671: char *sysname_read();
672: char *thissys;
673:
674: from = &buf[cmdtab[RCPT].c_len];
675: while (*from == ' ' || *from == '\t')
676: from++;
677: if (*from == '<') {
678: end = strchr(from++, '>');
679: if (end == 0) {
680: return FALSE;
681: }
682: *end = 0;
683: }
684:
685: /*
686: * convert to lower case (this is wrong but rfc822 is case
687: * insensitive)
688: */
689: for(rv = from; *rv; rv++)
690: if(isupper(*rv))
691: *rv = tolower(*rv);
692:
693: /*
694: * convert address to bang format. Assume the first site
695: * in the list is us and take it out.
696: */
697: rv=convertaddr(from);
698: if(end=strchr(rv, '!')){
699: thissys = sysname_read();
700: *end = '\0';
701: if(strcmp(rv, thissys)==0)
702: rv = end+1;
703: else
704: *end = '!';
705: }
706:
707: /*
708: * check for address syntax
709: */
710: if(shellchars(rv)){
711: if ( (char *) NULL != mypeer )
712: Syslog(LOG_ALERT, "shell characters in address: %s from %s",
713: mypeer, rv);
714: else
715: Syslog(LOG_ALERT, "shell characters in address: %s", rv);
716: if(virus)
717: rv = "upas.security";
718: else
719: return FALSE;
720: }
721:
722: /*
723: * add to list of recipients
724: */
725: if(*s_to_c(rcvrs))
726: s_append(rcvrs, " ");
727: s_append(rcvrs, rv);
728: return TRUE;
729: }
730:
731:
732: /* Time to live elapsed or io error. */
733: death(weapon)
734: {
735: (void) unlink(dataname);
736: exit(1);
737: }
738:
739: alarmsend()
740: {
741: csend(LOG_WARNING, "451 Our mailer appears to be hung.\n");
742: death(EX_TEMPFAIL);
743: }
744:
745: funnychars(str)
746: register char *str;
747: {
748: for (;;)
749: switch(*str++) {
750: case '^':
751: case '&':
752: case '>':
753: case '<':
754: case '`':
755: case '|':
756: case ';':
757: case '\'':
758: return TRUE;
759:
760: case 0:
761: return FALSE;
762: }
763: }
764:
765: bitch(buf, fo)
766: char *buf;
767: FILE *fo;
768: {
769: char gripe[BUFSIZ], *nlptr;
770:
771: if ((nlptr = strchr(buf, '\n')) != 0)
772: *nlptr = 0;
773: (void) sprintf(gripe, "502 %s ... Not recognized\n", buf);
774: csend(LOG_DEBUG, gripe);
775: }
776:
777: bomb(err)
778: int err;
779: {
780: death(err);
781: }
782:
783: csend(loglevel, message)
784: int loglevel;
785: char *message;
786: {
787: Syslog(loglevel, "<--- %s", message);
788: (void) tputs(message, fo);
789: }
790:
791: int
792: crecv(buf, len, fd)
793: char *buf;
794: int len, fd;
795: {
796: int n = tgets(buf, len, fi);
797: Syslog(LOG_DEBUG, "-------> %s", buf);
798: return n;
799: }
800: @//E*O*F smtp/conversed.c//
801: chmod u=rw,g=r,o=r smtp/conversed.c
802:
803: echo x - smtp/from822.c
804: sed 's/^@//' > "smtp/from822.c" <<'@//E*O*F smtp/from822.c//'
805: #include <stdio.h>
806: #include <ctype.h>
807: #include "mail.h"
808: #include "string.h"
809: #include "header.h"
810: #include "aux.h"
811:
812: /*
813: * Convert the rfc822 message on standard input into `UNIX' format
814: * and write it onto the passed FILE.
815: */
816:
817: /* header tags */
818: header hdrs[] = {
819: HEADER("Date:"),
820: HEADER("From:"),
821: HEADER("Sender:"),
822: HEADER("UnixFrom:"),
823: HEADER("UnixDate:"),
824: HEADER("Reply-To:"),
825: HEADER("")
826: };
827: #define datehdr hdrs[0]
828: #define fromhdr hdrs[1]
829: #define senderhdr hdrs[2]
830: #define unixfromhdr hdrs[3]
831: #define unixdatehdr hdrs[4]
832: #define replyhdr hdrs[5]
833:
834: /* imported */
835: extern int getheader();
836: extern string *getaddr();
837: extern int printheaders();
838: extern void printbodies();
839: extern char *lowercase();
840: extern char *convertaddr();
841: extern char *mypeer;
842:
843:
844: /* predeclared */
845: static char *getfrom();
846: static char *getdate();
847:
848: /* exported */
849: int extrafrom = 0;
850:
851: /*
852: * network name gets tacked onto the return addresses if addnet is set or if
853: * rfc822 routing is specified.
854: */
855: from822(net, fgetsp, fi, fo, defsender, helohost)
856: char *net;
857: char *(*fgetsp)();
858: FILE *fi; /* input file */
859: FILE *fo; /* output file */
860: char *defsender;
861: char *helohost;
862: {
863: char *from=NULL;
864: char *date;
865: char *basic;
866: char buf[4096];
867: int n;
868: extern int fputs();
869:
870: getheader(fgetsp, fi);
871:
872: /* Get sender's address.
873: */
874: if (unixfromhdr.line != NULL) {
875: from = basic = s_to_c(unixfromhdr.line);
876: } else if (senderhdr.line != NULL) {
877: from = getfrom(basic=HCONTENT(senderhdr), net);
878: } else if (fromhdr.line != NULL) {
879: from = getfrom(basic=HCONTENT(fromhdr), net);
880: } else if (defsender != NULL) {
881: from = getfrom(basic=defsender, net);
882: } else if (replyhdr.line != NULL) {
883: from = getfrom(basic=HCONTENT(replyhdr), net);
884: } else {
885: from = basic = "unknown";
886: }
887:
888: /* Get date line, or make one up */
889: if(datehdr.line != NULL)
890: date = getdate(HCONTENT(datehdr));
891: else if(unixdatehdr.line != NULL)
892: date = s_to_c(unixdatehdr.line);
893: else
894: date = getdate((char *)0);
895:
896: /* output UNIX header */
897: if (from != NULL && from != '\0' && date != '\0')
898: print_remote_header(fo, from, date, "");
899:
900: /* throw in a received line */
901: if(unixfromhdr.line == NULL)
902: printrcved(fo, helohost);
903:
904: /* output the rest */
905: if(printheaders(fputs, fo, 0))
906: fputs("\n", fo);
907: printbodies(fputs, fo);
908: while ((*fgetsp)(buf, sizeof(buf), fi)!=NULL)
909: fputs(buf, fo);
910: }
911:
912: /*
913: * Print out a received line
914: */
915: printrcved(fo, by)
916: FILE *fo;
917: char *by;
918: {
919: if ( (char *)0 == mypeer )
920: fprintf(fo, "Received: by %s; %s\n", by, getdate((char *)0));
921: else
922: fprintf(fo, "Received: from %s by %s; %s\n", mypeer, by,
923: getdate((char *)0));
924: }
925:
926: /*
927: * Return true if the two lines are the same modulo <>, whitespace,
928: * and newline.
929: */
930: sameaddr(line, addr)
931: char *line;
932: char *addr;
933: {
934: if (line==NULL)
935: return(1);
936: while (*line==' ' || *line=='\t' || *line=='<')
937: line++;
938: while (*addr==' ' || *addr=='\t' || *addr=='<')
939: addr++;
940: while(*addr && *addr!='>' && *addr!=' ' && *addr!='\t'){
941: if(*addr != *line)
942: break;
943: addr++;
944: line++;
945: }
946: while (*line=='>' || *line==' ' || *line=='\t')
947: line++;
948: while (*addr=='>' || *addr==' ' || *addr=='\t')
949: addr++;
950: while(*line)
951: if(*addr++ != *line++)
952: return(0);
953: return(1);
954: }
955:
956: /*
957: * The sender is either the next first whitespace delimited token or
958: * the first thing enclosed in "<" ">".
959: * Sets extrafrom > 0 if a from line with other cruft in it.
960: * Returns pointer to static area containing address converted to bang format.
961: */
962: static char *
963: getfrom(line, net)
964: char *line;
965: char *net;
966: {
967: register char *lp;
968: string *sender;
969:
970: sender = getaddr(line);
971: lp = convertaddr(s_to_c(sender));
972: if(net!=NULL){
973: s_reset(sender);
974: s_append(sender, net);
975: s_append(sender, "!");
976: s_append(sender, lp);
977: lp = s_to_c(sender);
978: }
979: return lp;
980: }
981:
982: /*
983: * Get a date line. Convert to `UNIX' format.
984: * use the current time instead if misparse, or if day omitted
985: * 822 standard: [Mon, ] 19 Oct 87 19:47:25 EDT
986: * (sometimes the , is omitted; sometimes (Mon) at end)
987: * Unix: Mon Oct 19 19:47:25 EDT 1987
988: *
989: */
990: static char *
991: getdate(line)
992: char *line;
993: {
994: register char *sp;
995: int i;
996: long t, time();
997: char *p, *nl, *ctime();
998: char *field[6];
999: static string *date=0;
1000: static string *olddate=0;
1001:
1002: date = s_reset(date);
1003: olddate = s_reset(olddate);
1004: if (line) {
1005: s_append(olddate, line);
1006: sp = s_to_c(olddate);
1007: for (i = 0; *sp && i < 6; i++) {
1008: while (isspace(*sp) || *sp == ',' || *sp == '-')
1009: *sp++ = '\0';
1010: field[i] = sp;
1011: while (!isspace(*sp) && *sp != ',' && *sp != '-'
1012: && *sp != '\0')
1013: sp++;
1014: }
1015: *sp = '\0';
1016: if (i==6 && isalpha(*field[0])) {
1017: s_append(date, field[0]);
1018: s_putc(date, ' ');
1019: s_append(date, field[2]);
1020: s_putc(date, ' ');
1021: if(strlen(field[1])==1)
1022: s_putc(date, ' ');
1023: s_append(date, field[1]);
1024: s_putc(date, ' ');
1025: s_append(date, field[4]);
1026: s_putc(date, ' ');
1027: for (p = field[5]; *p; p++)
1028: if(islower(*p))
1029: *p = toupper(*p);
1030: s_append(date, field[5]);
1031: s_putc(date, ' ');
1032: if (field[3][2]=='\0')
1033: s_append(date, "19");
1034: s_append(date, field[3]);
1035: }
1036: }
1037: s_terminate(date);
1038: if (*s_to_c(date) == '\0') {
1039: s_append(date, thedate());
1040: }
1041: return s_to_c(date);
1042: }
1043:
1044: /* Return 1 if addr has only one bang in it */
1045: int
1046: onehop(addr)
1047: char *addr;
1048: {
1049: register char *p;
1050: register int cnt=0;
1051:
1052: for (p=addr; *p; )
1053: if (*p++ == '!')
1054: if (cnt++>0)
1055: return 0;
1056: return 1;
1057: }
1058: @//E*O*F smtp/from822.c//
1059: chmod u=rw,g=r,o=r smtp/from822.c
1060:
1061: echo x - smtp/makefile
1062: sed 's/^@//' > "smtp/makefile" <<'@//E*O*F smtp/makefile//'
1063: # COBJ is for sysname_read()
1064: COBJ=log.o ../common/common.a ../libc/libc.a ../config/config.o
1065:
1066: QEROBJ=smtpqer.o to822addr.o qlib.o $(COBJ)
1067: SMTPOBJ=smtp.o converse.o netio.o to822addr.o to822.o header.o $(COBJ)
1068: SMTPDOBJ=smtpd.o conversed.o netio.o qlib.o from822addr.o from822.o header.o $(COBJ)
1069:
1070: CFLAGS=${UNIX} -g -I. -I../libc -I../common ${SCFLAGS}
1071: LIB=/usr/lib/upas
1072:
1073:
1074: all: smtp smtpd smtpqer smtpsched
1075:
1076:
1077: smtp: ../ipc/libipc.a $(SMTPOBJ)
1078: $(CC) $(SMTPOBJ) ../ipc/libipc.a -o smtp $(SLFLAGS)
1079:
1080: smtpd: $(SMTPDOBJ)
1081: $(CC) $(SMTPDOBJ) -o smtpd $(SLFLAGS)
1082:
1083: smtpqer: $(QEROBJ)
1084: $(CC) $(QEROBJ) -o smtpqer $(SLFLAGS)
1085:
1086: smtpsched: smtpsched.o qlib.o
1087: $(CC) smtpsched.o qlib.o $(COBJ) -o smtpsched $(SLFLAGS)
1088:
1089:
1090: from822.o: header.h ../common/mail.h ../common/string.h ../common/aux.h
1091: from822addr.o: ../common/string.h
1092: header.o: header.h ../common/mail.h ../common/string.h ../common/aux.h
1093: converse.o: smtp.h ../common/mail.h ../common/string.h
1094: conversed.o: smtp.h cmds.h ../common/mail.h ../common/string.h
1095: smtp.o: smtp.h ../common/string.h ../common/aux.h
1096: netio.o: smtp.h
1097: qlib.o: smtp.h ../common/string.h
1098: smtpqer.o: ../common/string.h ../common/mail.h
1099: smtpsched.o: smtp.h ../common/string.h
1100: to822.o: header.h addrformat.h ../common/mail.h ../common/string.h \
1101: ../common/aux.h
1102: to822addr.o: addrformat.h ../common/string.h
1103:
1104: sedfile:
1105: echo 's+LIBDIR+$(LIB)+g' >sed.file
1106:
1107: install: dirs sedfile $(LIB)/smtp $(LIB)/smtpd $(LIB)/smtpqer $(LIB)/smtpsched install.smtpd.sh
1108:
1109: dirs:
1110: -mkdir /usr/spool/smtpq
1111: -chown uucp /usr/spool/smtpq
1112: -chmod 775 /usr/spool/smtpq
1113:
1114: install.smtpd.sh:
1115: sed -f sed.file smtpd.sh >$(LIB)/smtpd.sh
1116: -chmod 775 $(LIB)/smtpd.sh
1117:
1118: $(LIB)/smtp: smtp
1119: chmod 755 smtp
1120: cp smtp $(LIB)/smtp
1121: strip $(LIB)/smtp
1122:
1123: $(LIB)/smtpd: smtpd
1124: chmod 755 smtpd
1125: cp smtpd $(LIB)/smtpd
1126: strip $(LIB)/smtpd
1127:
1128: $(LIB)/smtpqer: smtpqer
1129: cp smtpqer $(LIB)/smtpqer
1130: strip $(LIB)/smtpqer
1131: chown uucp $(LIB)/smtpqer
1132: chgrp uucp $(LIB)/smtpqer
1133: chmod 6775 $(LIB)/smtpqer
1134:
1135: $(LIB)/smtpsched: smtpsched
1136: chmod 755 smtpsched
1137: cp smtpsched $(LIB)/smtpsched
1138: strip $(LIB)/smtpsched
1139:
1140:
1141: clean:
1142: rm -f smtp smtpd smtpqer smtpsched *.o sed.file
1143: @//E*O*F smtp/makefile//
1144: chmod u=rw,g=r,o=r smtp/makefile
1145:
1146: echo x - misc/getpeer.c
1147: sed 's/^@//' > "misc/getpeer.c" <<'@//E*O*F misc/getpeer.c//'
1148: #include <stdio.h>
1149: #include <sys/types.h>
1150: #include <sys/socket.h>
1151: #include <netdb.h>
1152: #include <netinet/in.h>
1153:
1154: main(argc, argv)
1155: int argc;
1156: char *argv[];
1157: {
1158: int iplen;
1159: char *adc, *inet_ntoa();
1160: struct sockaddr_in ip;
1161: struct hostent *hp, *gethostbyaddr();
1162:
1163: iplen = sizeof(ip);
1164: if ( -1 == getpeername(0, &ip, &iplen) ) {
1165: perror("getpeername");
1166: exit(1);
1167: }
1168: adc = inet_ntoa(ip.sin_addr);
1169: if ( NULL == (hp = gethostbyaddr(&ip.sin_addr, sizeof(ip.sin_addr),
1170: AF_INET) ) )
1171: printf("[%s]\n", adc);
1172: else
1173: printf("%s [%s]\n", hp->h_name, adc);
1174: }
1175: @//E*O*F misc/getpeer.c//
1176: chmod u=rw,g=r,o=r misc/getpeer.c
1177:
1178: echo x - misc/maphost.c
1179: sed 's/^@//' > "misc/maphost.c" <<'@//E*O*F misc/maphost.c//'
1180: #include <stdio.h>
1181: #include <dk.h>
1182:
1183: main(argc, argv)
1184: int argc;
1185: char *argv[];
1186: {
1187: if ( argc != 2 ) {
1188: fprintf(stderr, "Usage maphost host\n");
1189: exit(1);
1190: }
1191: printf("%s\n", maphost(argv[1], 's', "", "", ""));
1192: exit(0);
1193: }
1194: @//E*O*F misc/maphost.c//
1195: chmod u=rw,g=r,o=r misc/maphost.c
1196:
1197: echo x - misc/makefile
1198: sed 's/^@//' > "misc/makefile" <<'@//E*O*F misc/makefile//'
1199: LIB=/usr/lib/upas
1200: CFLAGS=${UNIX} -g -I. -I../libc -I../common -I/usr/include -I/usr/include/sys
1201: LFLAGS=-g
1202: HOSTNAME=cat /etc/whoami
1203:
1204: #DKINCLUDE=-I/usr/include/dkit
1205:
1206: @.c.o: ; $(CC) -c $(CFLAGS) $(DKINCLUDE) $*.c
1207: all: mail
1208:
1209: maphost: maphost.o
1210: cc maphost.o -L/usr/dk/lib -ldk -o maphost
1211:
1212: getpeer: getpeer.o
1213: cc getpeer.o -o getpeer
1214:
1215: sedfile:
1216: echo 's+LIBDIR+$(LIB)+g' >sed.file
1217: echo 's+HOSTNAME+$(HOSTNAME)+g' >>sed.file
1218:
1219: install: sedfile install.fish install.mail.sh
1220:
1221: install.getpeer: getpeer sedfile
1222: cp getpeer $(LIB)
1223: -chmod 775 $(LIB)/getpeer
1224: strip $(LIB)/getpeer
1225:
1226: install.maphost: maphost sedfile
1227: cp maphost $(LIB)
1228: -chmod 775 $(LIB)/maphost
1229: strip $(LIB)/maphost
1230:
1231: install.fish:
1232: cp gone.msg $(LIB)
1233: sed -f sed.file gone.fishing >$(LIB)/gone.fishing
1234: -chmod 775 $(LIB)/gone.fishing
1235: -chown bin $(LIB)/gone.fishing $(LIB)/gone.msg
1236:
1237: install.mail.sh:
1238: sed -f sed.file mail.sh >/bin/mail
1239: -chown bin /bin/mail
1240: -chmod 775 /bin/mail
1241:
1242: install.notify: notify
1243: cp notify $(LIB)/notify
1244: -chmod 775 $(LIB)/notify
1245: -chown bin $(LIB)/notify
1246:
1247: install.mail: mail
1248: cp mail /bin
1249: strip /bin/mail
1250:
1251: notify: notify.o
1252: cc $(LFLAGS) notify.o -o notify
1253:
1254: mail: mail.o ../config/config.o
1255: cc $(LFLAGS) mail.o ../config/config.o -o mail
1256:
1257: clean:
1258: -rm -f *.[oOa] core a.out *.sL notify
1259: -rm -f sed.file mail getpeer maphost
1260:
1261: @//E*O*F misc/makefile//
1262: chmod u=rw,g=r,o=r misc/makefile
1263:
1264: exit 0
1265:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.