arpa.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 663 行
C
663 行
# include <stdio.h># include <ctype.h># include <signal.h># include <sysexits.h># include <whoami.h># include "useful.h"static char SccsId[] = "@(#)arpa.c 4.1 7/25/83";char Version[] = "@(#)Arpa-mailer version 4.1 of 7/25/83";# define void int/*** ARPA MAILER -- Queue ARPANET mail for eventual delivery**** The standard input is stuck away in the outgoing arpanet** mail queue for delivery by the true arpanet mailer.**** CUSTOMIZED FOR THE C/70**** Usage:** /usr/lib/mailers/arpa from host user**** Positional Parameters:** from -- the person sending the mail.** host -- the host to send the mail to.** user -- the user to send the mail to.**** Flags:** -T -- debug flag.**** Files:** /usr/spool/netmail/* -- the queue file.**** Return Codes:** 0 -- all messages successfully mailed.** 2 -- user or host unknown.** 3 -- service unavailable, probably temporary** file system condition.** 4 -- syntax error in address.**** Compilation Flags:** SPOOLDIR -- the spool directory**** Compilation Instructions:** cc -n -O -s arpa-mailer.c -o arpa-mailer -lX** chmod 755 arpa-mailer** mv arpa-mailer /usr/lib/mailers/arpa**** Author:** Eric Allman, UCB/INGRES (eric@berkeley)*/# ifdef C70# define SPOOLDIR "/usr/netmail"# else# define SPOOLDIR "/usr/spool/netmail"# endifchar *From; /* person sending this mail */char *To; /* current "To:" person */int State; /* the current state (for exit codes) */# ifdef DEBUGbool Tflag; /* -T given */# endif DEBUGchar FromHost[200]; /* string to prepend to addresses *//*** MAIN -- Main program for arpa mailer**** Processes arguments, and calls sendmail successively on** the To: list.**** Algorithm:** Scan for debug flag.** Catch interrupt signals.** Collect input file name and from person.** If more than one person in the to list, and** if the input file is not a real file,** collect input into a temp file.** For each person in the to list** Send to that person.**** Parameters:** argc** argv -- as usual**** Returns:** via exit**** Side Effects:** Mail gets sent.**** Author:** Eric Allman UCB/INGRES.*/main(argc, argv) int argc; char **argv;{ register int i; register char *p; register int ifd; char buf[512]; extern int done(); extern char *locv(); register char *q; char *lastmark; State = 3; if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void) signal(SIGINT, done); /* process flags */ argv[argc] = 0;# ifdef DEBUG if (strcmp(argv[1], "-T") == 0) { Tflag++; argv++; argc--; printf("%s\n", Version); }# endif DEBUG if (argc != 4) { rexit(EX_SOFTWARE); } /* decode parameters */ From = argv[1]; lastmark = &FromHost[-1]; for (p = From, q = FromHost; (*q = *p) != '\0'; p++, q++) { if (*p == ':') *q = *p = '.'; if (*q == '.' || *q == '!' || *q == '@') lastmark = q; } lastmark[1] = '\0'; /* start sending mail */ State = sendmail(argv[2], argv[3]); /* all done, clean up */ done();}/*** DONE -- Finish up, remove temp files, etc.**** This does basic cleanup on interrupt, error, or** normal termination. It uses "State" to tell which** is happening.**** Parameters:** none**** Returns:** none**** Side Effects:** Exit(State).*/done(){ rexit(State);}/*** REXIT -- exit, reporting error code if -T given**** Parameters:** e -- error code to exit with; see sysexits.h**** Returns:** none**** Side Effects:** Exit(e).*/rexit(e){# ifdef DEBUG if (Tflag) fprintf(stderr, "arpa-mail: return code %d\n", e);# endif exit(e);}/*** SENDMAIL -- Queue up mail for the arpanet mailer.**** The mail is inserted with proper headers into the** arpanet queue directory.**** Algorithm:** decode "to" address** if error, exit.** create a spool file name.** output the header information to spool file,** separate names in To:, CC: fields with commas.** copy the mail to the spool file.**** Parameters:** host -- the host to send to.** user -- the user to send to.**** Returns:** none**** Side Effects:** the mail is copied into a file in the network** queue directory (/usr/spool/netmail).*/sendmail(host, user) char *host; char *user;{ char spoolfile[50]; /* gets the spool file name */ register int i; register char *p; static int callnum; /* for the final letter on spoolfile */ char buf[512]; register FILE *sfp; /* spool file */ register int c; extern char *matchhdr(); /* verify that the host exists */ (void) strcpy(buf, "/dev/net/"); (void) strcat(buf, host);# ifndef C70#ifdef DEBUG if (!Tflag)#endif DEBUG if (host[0] == '\0' || access(buf, 0) < 0) return (EX_NOHOST);# endif C70 /* ** Create spool file name. ** Format is "username000nnX", where username is ** padded on the right with zeros and nn (the process ** id) is padded on the left with zeros; X is a unique ** sequence character. */# ifdef DEBUG if (Tflag) (void) strcpy(spoolfile, "arpa.out"); else# endif DEBUG (void) sprintf(spoolfile, "%s/arpamail%05d%c", SPOOLDIR, getpid(), 'a' + callnum++); /* create spool file */ sfp = fopen(spoolfile, "w"); if (sfp == NULL) { spoolerr: return (EX_OSERR); }# ifdef DEBUG if (!Tflag)# endif DEBUG (void) chmod(spoolfile, 0400); /* ** Output mailer control lines. ** These lines are as follows: ** /dev/net/<hostname> {target host} ** user-name {at target host} ** /mnt/eric {pathname of sender; not used} ** eric {name of user who is sending} ** These are different (but close) on the C/70. */# ifdef C70 fputs(host, sfp); fputs(":", sfp); fputs(user, sfp); fputs(":", sfp); fputs(From, sfp); fputs(":\n", sfp);# else fputs(buf, sfp); fputs("\n", sfp); fputs(user, sfp); fputs("\n\n", sfp); fputs(From, sfp); fputs("\n", sfp);# endif /* ** Output the mail ** Check the first line for the date. If not found, ** assume the message is not in arpanet standard format ** and output a "Date:" and "From:" header. */ if (fgets(buf, sizeof buf, stdin) == NULL) { /* no message */ (void) unlink(spoolfile); return (EX_OK); } if (strncmp("From ", buf, 5) == 0) { /* strip Unix "From" line */ /* should save the date here */ (void) fgets(buf, sizeof buf, stdin); } while (matchhdr(buf, "mail-from") != NULL || matchhdr(buf, "sender-path") != NULL || matchhdr(buf, "received") != NULL || matchhdr(buf, "via") != NULL) { fputs(buf, sfp); (void) fgets(buf, sizeof buf, stdin); } if (matchhdr(buf, "date") == NULL) putdate(sfp); else { fputs(buf, sfp); (void) fgets(buf, sizeof buf, stdin); } if (matchhdr(buf, "from") == NULL) putfrom(sfp); else { /* hack to support sendmail -- for a while */ if (index(buf, '@') == NULL) putfrom(sfp); else fputs(buf, sfp); (void) fgets(buf, sizeof buf, stdin); } if (!ishdr(buf)) { if (buf[0] != '\n') putc('\n', sfp); goto hdrdone; } /* ** At this point, we have a message with REAL headers. ** We look at each head line and insert commas if it ** is a To: or Cc: field. */ do { if (!ishdr(buf)) break; if (!matchhdr(buf, "to") && !matchhdr(buf, "cc")) { fputs(buf, sfp); continue; } /* gotcha! */ fixaddr(buf, 1, sfp); while (isspace(c = peekc(stdin)) && c != '\n') { (void) fgets(buf, BUFSIZ, stdin); fixaddr(buf, 0, sfp); } } while (fgets(buf, BUFSIZ, stdin) != NULL);hdrdone: /* output the rest of the header & the body of the letter */ do { fputs(buf, sfp); if (ferror(sfp)) goto spoolerr; } while (fgets(buf, sizeof buf, stdin) != NULL); /* all done! */ (void) fclose(sfp); return (EX_OK);}/*** FIXADDR -- Output header line with needed commas.**** Parameters:** buf -- header line** first -- true if this is not a continuation**** Returns:** none**** Side effects:** The contents of buf is copied onto the spool file with** with the right commas interlaced**** Called by:** sendmail*/fixaddr(buf, first, spf) char buf[]; register FILE *spf;{ register char *cp; register int c; char word[BUFSIZ], word2[BUFSIZ]; char *gword(); static char wsep[] = ", "; cp = buf; if (first) { while (*cp != ':' && *cp) putc(*cp++, spf); if (*cp == ':') { fputs(": ", spf); cp++; } } else while (*cp && isspace(*cp)) putc(*cp++, spf); cp = gword(word, cp); if (strlen(word) == 0) { putc('\n', spf); goto test; } for (;;) { cp = gword(word2, cp); if (strlen(word2) == 0) { putaddr(word, spf); break; } if (strcmp(word2, "%") == 0) word2[0] = '@'; if (strcmp(word2, "@") && strcmp(word2, "at")) { putaddr(word, spf); fputs(wsep, spf); (void) strcpy(word, word2); continue; } fputs(word, spf); if (word2[0] == '@') putc('@', spf); else fputs(" at ", spf); cp = gword(word, cp); fputs(word, spf); cp = gword(word, cp); if (strlen(word)) fputs(wsep, spf); }test: c = peekc(stdin); if (isspace(c) && c != '\n') fputs(",\n", spf); else putc('\n', spf);}/*** PUTADDR -- output address onto file**** Putaddr prepends the network header onto the address** unless one already exists.**** Parameters:** name -- the name to output.** fp -- the file to put it on.**** Returns:** none.**** Side Effects:** name is put onto fp.*/putaddr(name, fp) char *name; FILE *fp;{ register char *p; if (strlen(name) == 0) return; for (p = name; *p != '\0' && *p != ':' && *p != '.' && *p != '@' && *p != '!' && *p != '^'; p++) continue; if (*p == ':') *p = '.'; else if (*p == '\0') fputs(FromHost, fp); fputs(name, fp); if (*p != '@') fputs("@Berkeley", fp);}/*** PEEKC -- peek at next character in input file**** Parameters:** fp -- stdio file buffer**** Returns:** the next character in the input or EOF**** Side effects:** None.*/peekc(fp) register FILE *fp;{ register int c; c = getc(fp); (void) ungetc(c, fp); return(c);}/*** GWORD -- get the next liberal word from a string**** Parameters:** buf -- place to put scanned word** p -- place to start looking for word**** Returns:** updated value of p or 0 if no more left after this**** Side effects:** buf gets the liberal word scanned.** buf will be length 0 if there is no more input,** or if p was passed as 0*/char *gword(buf, p) char buf[]; register char *p;{ register char *sp, *dp; int atfound = 0; /* weither or not a '@' found in the scan */ (void) strcpy(buf, ""); if (p == 0) return(0); sp = p; while (*sp && (isspace(*sp) || *sp == ',')) sp++; dp = buf; if (*sp != '%' && *sp != '@') { while (*sp && !isspace(*sp) && *sp != ',' ) { if ( *sp == '@' || *sp == '%' ) atfound++; *dp++ = *sp++; } if ( atfound ) { dp--; while ( *dp != '@' && *dp != '%' ) dp--,sp--; sp--; } } else *dp++ = *sp++; *dp = 0; if (*sp == 0) return(0); return(sp);}/*** ISHDR -- see if the passed line is a ARPA style header line**** Parameters:** buf -- header line**** Returns:** non-zero if the line is a header line, else zero**** Side effects:** none**** Called by:** sendmail*/ishdr(buf) char buf[];{ register char *p; p = buf; /* check for continuation lines */ if (isspace(*p)) return (1); else { while (*p != ':' && !isspace(*p)) p++; while (isspace(*p)) p++; if (*p != ':') p = 0; } return(p != 0);}/*** PUTDATE -- Put the date field into the message.**** Parameters:** fp -- file to put it onto.**** Returns:** none**** Side Effects:** output onto fp.*/putdate(fp) register FILE *fp;{ extern char *arpadate(); fputs("Date: ", fp); fputs(arpadate(NULL), fp); fputs("\n", fp);}/*** PUTFROM -- Put the from field into the message.**** Parameters:** fp -- file to put it onto.**** Returns:** none**** Side Effects:** output onto fp.*/putfrom(fp) register FILE *fp;{ fputs("From: ", fp); fputs(From, fp); fputs("@Berkeley\n", fp);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?