# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/aux/arpa.c

##### Functions

    done              X
    fixaddr           X
    gword             X
    ishdr             X
    main              X
    peekc             X
    putaddr           X
    putdate           X
    putfrom           X
    rexit             X
    sendmail          X

##### Variables

    From              X
    FromHost          X
    State             X
    To                X
    Version           X
    copyright         X

##### Macros

    SPOOLDIR          X
    void              X

       1: /*
       2: **  Sendmail
       3: **  Copyright (c) 1983  Eric P. Allman
       4: **  Berkeley, California
       5: **
       6: **  Copyright (c) 1983 Regents of the University of California.
       7: **  All rights reserved.  The Berkeley software License Agreement
       8: **  specifies the terms and conditions for redistribution.
       9: */
      10:
      11: #ifndef lint
      12: char copyright[] =
      13: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      14:  All rights reserved.\n";
      15: #endif not lint
      16:
      17: #ifndef lint
      18: static char SccsId[] = "@(#)arpa.c	5.1 (Berkeley) 6/7/85";
      19: #endif not lint
      20:
      21: # include   <stdio.h>
      22: # include   <ctype.h>
      23: # include   <signal.h>
      24: # include   <sysexits.h>
      25: # include   <whoami.h>
      26: # include   "useful.h"
      27:
      28: char Version[] = "@(#)Arpa-mailer version 5.1 of 6/7/85";
      29:
      30: # define void   int
      31:
      32: /*
      33: **  ARPA MAILER -- Queue ARPANET mail for eventual delivery
      34: **
      35: **	The standard input is stuck away in the outgoing arpanet
      36: **	mail queue for delivery by the true arpanet mailer.
      37: **
      38: **		CUSTOMIZED FOR THE C/70
      39: **
      40: **	Usage:
      41: **		/usr/lib/mailers/arpa from host user
      42: **
      43: **	Positional Parameters:
      44: **		from -- the person sending the mail.
      45: **		host -- the host to send the mail to.
      46: **		user -- the user to send the mail to.
      47: **
      48: **	Flags:
      49: **		-T -- debug flag.
      50: **
      51: **	Files:
      52: **		/usr/spool/netmail/* -- the queue file.
      53: **
      54: **	Return Codes:
      55: **		0 -- all messages successfully mailed.
      56: **		2 -- user or host unknown.
      57: **		3 -- service unavailable, probably temporary
      58: **			file system condition.
      59: **		4 -- syntax error in address.
      60: **
      61: **	Compilation Flags:
      62: **		SPOOLDIR -- the spool directory
      63: **
      64: **	Compilation Instructions:
      65: **		cc -n -O -s arpa-mailer.c -o arpa-mailer -lX
      66: **		chmod 755 arpa-mailer
      67: **		mv arpa-mailer /usr/lib/mailers/arpa
      68: **
      69: **	Author:
      70: **		Eric Allman, UCB/INGRES (eric@berkeley)
      71: */
      72:
      73: # ifdef C70
      74: # define SPOOLDIR   "/usr/netmail"
      75: # else
      76: # define SPOOLDIR   "/usr/spool/netmail"
      77: # endif
      78:
      79:
      80:
      81:
      82: char    *From;          /* person sending this mail */
      83: char    *To;            /* current "To:" person */
      84: int State;          /* the current state (for exit codes) */
      85: # ifdef DEBUG
      86: bool    Tflag;          /* -T given */
      87: # endif DEBUG
      88: char    FromHost[200];      /* string to prepend to addresses */
      89: /*
      90: **  MAIN -- Main program for arpa mailer
      91: **
      92: **	Processes arguments, and calls sendmail successively on
      93: **	the To: list.
      94: **
      95: **	Algorithm:
      96: **		Scan for debug flag.
      97: **		Catch interrupt signals.
      98: **		Collect input file name and from person.
      99: **		If more than one person in the to list, and
     100: **			if the input file is not a real file,
     101: **			collect input into a temp file.
     102: **		For each person in the to list
     103: **			Send to that person.
     104: **
     105: **	Parameters:
     106: **		argc
     107: **		argv -- as usual
     108: **
     109: **	Returns:
     110: **		via exit
     111: **
     112: **	Side Effects:
     113: **		Mail gets sent.
     114: **
     115: **	Author:
     116: **		Eric Allman UCB/INGRES.
     117: */
     118:
     119: main(argc, argv)
     120:     int argc;
     121:     char **argv;
     122: {
     123:     register int i;
     124:     register char *p;
     125:     register int ifd;
     126:     char buf[512];
     127:     extern int done();
     128:     extern char *locv();
     129:     register char *q;
     130:     char *lastmark;
     131:
     132:     State = 3;
     133:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
     134:         (void) signal(SIGINT, done);
     135:
     136:     /* process flags */
     137:     argv[argc] = 0;
     138: # ifdef DEBUG
     139:     if (strcmp(argv[1], "-T") == 0)
     140:     {
     141:         Tflag++;
     142:         argv++;
     143:         argc--;
     144:         printf("%s\n", Version);
     145:     }
     146: # endif DEBUG
     147:
     148:     if (argc != 4)
     149:     {
     150:         rexit(EX_SOFTWARE);
     151:     }
     152:
     153:     /* decode parameters */
     154:     From = argv[1];
     155:     lastmark = &FromHost[-1];
     156:     for (p = From, q = FromHost; (*q = *p) != '\0'; p++, q++)
     157:     {
     158:         if (*p == ':')
     159:             *q = *p = '.';
     160:         if (*q == '.' || *q == '!' || *q == '@')
     161:             lastmark = q;
     162:     }
     163:     lastmark[1] = '\0';
     164:
     165:     /* start sending mail */
     166:     State = sendmail(argv[2], argv[3]);
     167:
     168:     /* all done, clean up */
     169:     done();
     170: }
     171: /*
     172: **  DONE -- Finish up, remove temp files, etc.
     173: **
     174: **	This does basic cleanup on interrupt, error, or
     175: **	normal termination.  It uses "State" to tell which
     176: **	is happening.
     177: **
     178: **	Parameters:
     179: **		none
     180: **
     181: **	Returns:
     182: **		none
     183: **
     184: **	Side Effects:
     185: **		Exit(State).
     186: */
     187:
     188: done()
     189: {
     190:     rexit(State);
     191: }
     192:
     193: /*
     194: ** REXIT -- exit, reporting error code if -T given
     195: **
     196: **	Parameters:
     197: **		e -- error code to exit with; see sysexits.h
     198: **
     199: **	Returns:
     200: **		none
     201: **
     202: **	Side Effects:
     203: **		Exit(e).
     204: */
     205: rexit(e)
     206: {
     207:
     208: # ifdef DEBUG
     209:     if (Tflag)
     210:         fprintf(stderr, "arpa-mail: return code %d\n", e);
     211: # endif
     212:     exit(e);
     213: }
     214: /*
     215: **  SENDMAIL -- Queue up mail for the arpanet mailer.
     216: **
     217: **	The mail is inserted with proper headers into the
     218: **	arpanet queue directory.
     219: **
     220: **	Algorithm:
     221: **		decode "to" address
     222: **			if error, exit.
     223: **		create a spool file name.
     224: **		output the header information to spool file,
     225: **		  separate names in To:, CC: fields with commas.
     226: **		copy the mail to the spool file.
     227: **
     228: **	Parameters:
     229: **		host -- the host to send to.
     230: **		user -- the user to send to.
     231: **
     232: **	Returns:
     233: **		none
     234: **
     235: **	Side Effects:
     236: **		the mail is copied into a file in the network
     237: **			queue directory (/usr/spool/netmail).
     238: */
     239:
     240: sendmail(host, user)
     241:     char *host;
     242:     char *user;
     243: {
     244:     char spoolfile[50]; /* gets the spool file name */
     245:     register int i;
     246:     register char *p;
     247:     static int callnum; /* for the final letter on spoolfile */
     248:     char buf[512];
     249:     register FILE *sfp; /* spool file */
     250:     register int c;
     251:     extern char *matchhdr();
     252:
     253:     /* verify that the host exists */
     254:     (void) strcpy(buf, "/dev/net/");
     255:     (void) strcat(buf, host);
     256: # ifndef C70
     257: #ifdef DEBUG
     258:     if (!Tflag)
     259: #endif DEBUG
     260:     if (host[0] == '\0' || access(buf, 0) < 0)
     261:         return (EX_NOHOST);
     262: # endif C70
     263:
     264:     /*
     265: 	**  Create spool file name.
     266: 	**	Format is "username000nnX", where username is
     267: 	**	padded on the right with zeros and nn (the process
     268: 	**	id) is padded on the left with zeros; X is a unique
     269: 	**	sequence character.
     270: 	*/
     271:
     272: # ifdef DEBUG
     273:     if (Tflag)
     274:         (void) strcpy(spoolfile, "arpa.out");
     275:     else
     276: # endif DEBUG
     277:         (void) sprintf(spoolfile, "%s/arpamail%05d%c", SPOOLDIR, getpid(), 'a' + callnum++);
     278:
     279:     /* create spool file */
     280:     sfp = fopen(spoolfile, "w");
     281:     if (sfp == NULL)
     282:     {
     283:     spoolerr:
     284:         return (EX_OSERR);
     285:     }
     286: # ifdef DEBUG
     287:     if (!Tflag)
     288: # endif DEBUG
     289:         (void) chmod(spoolfile, 0400);
     290:
     291:     /*
     292: 	** Output mailer control lines.
     293: 	**	These lines are as follows:
     294: 	**		/dev/net/<hostname> {target host}
     295: 	**		user-name {at target host}
     296: 	**		/mnt/eric {pathname of sender; not used}
     297: 	**		eric {name of user who is sending}
     298: 	**	These are different (but close) on the C/70.
     299: 	*/
     300:
     301: # ifdef C70
     302:     fputs(host, sfp);
     303:     fputs(":", sfp);
     304:     fputs(user, sfp);
     305:     fputs(":", sfp);
     306:     fputs(From, sfp);
     307:     fputs(":\n", sfp);
     308: # else
     309:     fputs(buf, sfp);
     310:     fputs("\n", sfp);
     311:     fputs(user, sfp);
     312:     fputs("\n\n", sfp);
     313:     fputs(From, sfp);
     314:     fputs("\n", sfp);
     315: # endif
     316:
     317:     /*
     318: 	**  Output the mail
     319: 	**	Check the first line for the date.  If not found,
     320: 	**	assume the message is not in arpanet standard format
     321: 	**	and output a "Date:" and "From:" header.
     322: 	*/
     323:
     324:     if (fgets(buf, sizeof buf, stdin) == NULL)
     325:     {
     326:         /* no message */
     327:         (void) unlink(spoolfile);
     328:         return (EX_OK);
     329:     }
     330:     if (strncmp("From ", buf, 5) == 0)
     331:     {
     332:         /* strip Unix "From" line */
     333:         /* should save the date here */
     334:         (void) fgets(buf, sizeof buf, stdin);
     335:     }
     336:     while (matchhdr(buf, "mail-from") != NULL ||
     337:            matchhdr(buf, "sender-path") != NULL ||
     338:            matchhdr(buf, "received") != NULL ||
     339:            matchhdr(buf, "via") != NULL)
     340:     {
     341:         fputs(buf, sfp);
     342:         (void) fgets(buf, sizeof buf, stdin);
     343:     }
     344:     if (matchhdr(buf, "date") == NULL)
     345:         putdate(sfp);
     346:     else
     347:     {
     348:         fputs(buf, sfp);
     349:         (void) fgets(buf, sizeof buf, stdin);
     350:     }
     351:     if (matchhdr(buf, "from") == NULL)
     352:         putfrom(sfp);
     353:     else
     354:     {
     355:         /* hack to support sendmail -- for a while */
     356:         if (index(buf, '@') == NULL)
     357:             putfrom(sfp);
     358:         else
     359:             fputs(buf, sfp);
     360:         (void) fgets(buf, sizeof buf, stdin);
     361:     }
     362:     if (!ishdr(buf))
     363:     {
     364:         if (buf[0] != '\n')
     365:             putc('\n', sfp);
     366:         goto hdrdone;
     367:     }
     368:
     369:     /*
     370: 	** At this point, we have a message with REAL headers.
     371: 	** We look at each head line and insert commas if it
     372: 	** is a To: or Cc: field.
     373: 	*/
     374:
     375:     do
     376:     {
     377:         if (!ishdr(buf))
     378:             break;
     379:         if (!matchhdr(buf, "to") && !matchhdr(buf, "cc"))
     380:         {
     381:             fputs(buf, sfp);
     382:             continue;
     383:         }
     384:         /* gotcha! */
     385:         fixaddr(buf, 1, sfp);
     386:         while (isspace(c = peekc(stdin)) && c != '\n')
     387:         {
     388:             (void) fgets(buf, BUFSIZ, stdin);
     389:             fixaddr(buf, 0, sfp);
     390:         }
     391:     } while (fgets(buf, BUFSIZ, stdin) != NULL);
     392:
     393: hdrdone:
     394:     /* output the rest of the header & the body of the letter */
     395:     do
     396:     {
     397:         fputs(buf, sfp);
     398:         if (ferror(sfp))
     399:             goto spoolerr;
     400:     } while (fgets(buf, sizeof buf, stdin) != NULL);
     401:
     402:     /* all done! */
     403:     (void) fclose(sfp);
     404:     return (EX_OK);
     405: }
     406: /*
     407: **  FIXADDR -- Output header line with needed commas.
     408: **
     409: **	Parameters:
     410: **		buf -- header line
     411: **		first -- true if this is not a continuation
     412: **
     413: **	Returns:
     414: **		none
     415: **
     416: **	Side effects:
     417: **		The contents of buf is copied onto the spool file with
     418: **		with the right commas interlaced
     419: **
     420: **	Called by:
     421: **		sendmail
     422: */
     423:
     424: fixaddr(buf, first, spf)
     425:     char buf[];
     426:     register FILE *spf;
     427: {
     428:     register char *cp;
     429:     register int c;
     430:     char word[BUFSIZ], word2[BUFSIZ];
     431:     char *gword();
     432:     static char wsep[] = ", ";
     433:
     434:     cp = buf;
     435:     if (first)
     436:     {
     437:         while (*cp != ':' && *cp)
     438:             putc(*cp++, spf);
     439:         if (*cp == ':')
     440:         {
     441:             fputs(": ", spf);
     442:             cp++;
     443:         }
     444:     }
     445:     else
     446:         while (*cp && isspace(*cp))
     447:             putc(*cp++, spf);
     448:     cp = gword(word, cp);
     449:     if (strlen(word) == 0)
     450:     {
     451:         putc('\n', spf);
     452:         goto test;
     453:     }
     454:     for (;;)
     455:     {
     456:         cp = gword(word2, cp);
     457:         if (strlen(word2) == 0)
     458:         {
     459:             putaddr(word, spf);
     460:             break;
     461:         }
     462:         if (strcmp(word2, "%") == 0)
     463:             word2[0] = '@';
     464:         if (strcmp(word2, "@") && strcmp(word2, "at"))
     465:         {
     466:             putaddr(word, spf);
     467:             fputs(wsep, spf);
     468:             (void) strcpy(word, word2);
     469:             continue;
     470:         }
     471:         fputs(word, spf);
     472:         if (word2[0] == '@')
     473:             putc('@', spf);
     474:         else
     475:             fputs(" at ", spf);
     476:         cp = gword(word, cp);
     477:         fputs(word, spf);
     478:         cp = gword(word, cp);
     479:         if (strlen(word))
     480:             fputs(wsep, spf);
     481:     }
     482:
     483: test:
     484:     c = peekc(stdin);
     485:     if (isspace(c) && c != '\n')
     486:         fputs(",\n", spf);
     487:     else
     488:         putc('\n', spf);
     489: }
     490: /*
     491: **  PUTADDR -- output address onto file
     492: **
     493: **	Putaddr prepends the network header onto the address
     494: **	unless one already exists.
     495: **
     496: **	Parameters:
     497: **		name -- the name to output.
     498: **		fp -- the file to put it on.
     499: **
     500: **	Returns:
     501: **		none.
     502: **
     503: **	Side Effects:
     504: **		name is put onto fp.
     505: */
     506:
     507: putaddr(name, fp)
     508:     char *name;
     509:     FILE *fp;
     510: {
     511:     register char *p;
     512:
     513:     if (strlen(name) == 0)
     514:         return;
     515:     for (p = name; *p != '\0' && *p != ':' && *p != '.' && *p != '@' &&
     516:          *p != '!' && *p != '^'; p++)
     517:         continue;
     518:     if (*p == ':')
     519:         *p = '.';
     520:     else if (*p == '\0')
     521:         fputs(FromHost, fp);
     522:     fputs(name, fp);
     523:     if (*p != '@')
     524:         fputs("@Berkeley", fp);
     525: }
     526: /*
     527: **  PEEKC -- peek at next character in input file
     528: **
     529: **	Parameters:
     530: **		fp -- stdio file buffer
     531: **
     532: **	Returns:
     533: **		the next character in the input or EOF
     534: **
     535: **	Side effects:
     536: **		None.
     537: */
     538: peekc(fp)
     539:     register FILE *fp;
     540: {
     541:     register int c;
     542:
     543:     c = getc(fp);
     544:     (void) ungetc(c, fp);
     545:     return(c);
     546: }
     547:
     548: /*
     549: **  GWORD -- get the next liberal word from a string
     550: **
     551: **	Parameters:
     552: **		buf -- place to put scanned word
     553: **		p -- place to start looking for word
     554: **
     555: **	Returns:
     556: **		updated value of p or 0 if no more left after this
     557: **
     558: **	Side effects:
     559: **		buf gets the liberal word scanned.
     560: **		buf will be length 0 if there is no more input,
     561: **		or if p was passed as 0
     562: */
     563: char *
     564: gword(buf, p)
     565:     char buf[];
     566:     register char *p;
     567: {
     568:     register char *sp, *dp;
     569:     int atfound = 0;            /* weither or not a '@' found in the scan */
     570:
     571:     (void) strcpy(buf, "");
     572:     if (p == 0)
     573:         return(0);
     574:     sp = p;
     575:     while (*sp && (isspace(*sp) || *sp == ','))
     576:         sp++;
     577:     dp = buf;
     578:     if (*sp != '%' && *sp != '@')
     579:     {
     580:         while (*sp && !isspace(*sp) && *sp != ',' )
     581:         {
     582:             if ( *sp == '@' || *sp == '%' )
     583:                 atfound++;
     584:             *dp++ = *sp++;
     585:         }
     586:         if ( atfound )
     587:         {
     588:             dp--;
     589:             while ( *dp != '@' && *dp != '%' )
     590:                 dp--,sp--;
     591:             sp--;
     592:         }
     593:
     594:     }
     595:     else
     596:         *dp++ = *sp++;
     597:     *dp = 0;
     598:     if (*sp == 0)
     599:         return(0);
     600:     return(sp);
     601: }
     602: /*
     603: **  ISHDR -- see if the passed line is a ARPA style header line
     604: **
     605: **	Parameters:
     606: **		buf -- header line
     607: **
     608: **	Returns:
     609: **		non-zero if the line is a header line, else zero
     610: **
     611: **	Side effects:
     612: **		none
     613: **
     614: **	Called by:
     615: **		sendmail
     616: */
     617: ishdr(buf)
     618:     char buf[];
     619: {
     620:     register char *p;
     621:
     622:     p = buf;
     623:
     624:     /* check for continuation lines */
     625:     if (isspace(*p))
     626:         return (1);
     627:     else
     628:     {
     629:         while (*p != ':' && !isspace(*p))
     630:             p++;
     631:         while (isspace(*p))
     632:             p++;
     633:         if (*p != ':')
     634:             p = 0;
     635:     }
     636:     return(p != 0);
     637: }
     638: /*
     639: **  PUTDATE -- Put the date field into the message.
     640: **
     641: **	Parameters:
     642: **		fp -- file to put it onto.
     643: **
     644: **	Returns:
     645: **		none
     646: **
     647: **	Side Effects:
     648: **		output onto fp.
     649: */
     650:
     651: putdate(fp)
     652:     register FILE *fp;
     653: {
     654:     extern char *arpadate();
     655:
     656:     fputs("Date: ", fp);
     657:     fputs(arpadate(NULL), fp);
     658:     fputs("\n", fp);
     659: }
     660: /*
     661: **  PUTFROM -- Put the from field into the message.
     662: **
     663: **	Parameters:
     664: **		fp -- file to put it onto.
     665: **
     666: **	Returns:
     667: **		none
     668: **
     669: **	Side Effects:
     670: **		output onto fp.
     671: */
     672:
     673: putfrom(fp)
     674:     register FILE *fp;
     675: {
     676:
     677:     fputs("From: ", fp);
     678:     fputs(From, fp);
     679:     fputs("@Berkeley\n", fp);
     680: }

#### Defined functions

done defined in line 188; used 3 times

- in line 127, 134, 169

fixaddr defined in line 424; used 2 times

- in line 385-389(2)

gword defined in line 563; used 5 times

- in line 431, 448, 456, 476-478(2)

ishdr defined in line 617; used 2 times

- in line 362, 377

main defined in line 119; never used
peekc defined in line 538; used 2 times

- in line 386, 484

putaddr defined in line 507; used 2 times

- in line 459, 466

putdate defined in line 651; used 1 times

- in line 345

putfrom defined in line 673; used 2 times

- in line 352-357(2)

rexit defined in line 205; used 2 times

- in line 150, 190

sendmail defined in line 240; used 1 times

- in line 166

#### Defined variables

From defined in line 82; used 5 times

- in line 154-156(2), 306, 313, 678

FromHost defined in line 88; used 3 times

- in line 155-156(2), 521

SccsId defined in line 18; never used
State defined in line 84; used 3 times

- in line 132, 166, 190

To defined in line 83; never used
Version defined in line 28; used 1 times

- in line 144

copyright defined in line 12; never used

#### Defined macros

SPOOLDIR defined in line 76; used 1 times

- in line 277

void defined in line 30; never used

Last modified: 1987-02-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1363 |