ast@cs.vu.nl (Andy Tanenbaum) (10/23/89)
: This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'umheader.c' sed 's/^X//' > 'umheader.c' << '+ END-OF-FILE ''umheader.c' X/* X * UMAIL - MINIX Remote Domain-adressing Mail Router X * X * This version of RMAIL handles message-headers in a much X * more "standard" way. It can handle bang-adresses, plus X * the new-style Internet adressing (user@host.domain). X * It is called by programs as "Mail" and "Uuxqt". X * X * M A I L H E A D E R C O N V E R S I O N M O D U L E X * X * Headers: This module reads the header part of a message into X * memory, and then rearranges it into RFC-822 order. X * The preferred order of fields is: X * X * 1. From (old-style V6/V7) X * 2. From: X * 3. Received: (top to bottom) X * 4. Sender: X * X * 5. Unknown fields (user-defined) X * X * 6. To: X * 7. Cc: X * 8. Bcc: X * 9. Subject: X * 10. Message-ID: X * 11. Date: X * X * This order may be changed and/or expanded in the future, X * especially the "Resent-" fields should be added. X * X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl) X */ X#include <stdio.h> X#include <alloc.h> X#include <string.h> X#include <time.h> X#include "umail.h" X X Xtypedef struct __hdr { X struct __hdr *next; X int done; /* 1==READ, 0==UNREAD */ X int count; /* 1==FIRST, 2.. == NEXT PART */ X int std; /* 1==RFC, 0==USER_DEFINED */ X char *name; /* field name */ X char *value; /* field value */ X} HEADER; X#define NILHEAD ((HEADER *)NULL) X X Xstatic HEADER *hlist = NILHEAD; /* old message header */ Xstatic char *rfcfields[] = { /* list of RFC-822 fields */ X "FROM ", "FROM", "RECEIVED", "SENDER", X "TO", "CC", "BCC", "SUBJECT", X "MESSAGE-ID", "DATE", NULL X}; Xstatic char olduser[1024]; /* old user */ Xstatic char olddate[48]; /* old date */ Xstatic char oldhost[48]; /* old host machine */ X X X/* X * Look for a field in the header table in memory. X * If found, return its value, otherwise return NULL. X */ Xstatic char *hfind(name) Xchar *name; X{ X register HEADER *hp; X char tmp[48]; X X hp = hlist; X while (hp != NILHEAD) { X strcpy(tmp, hp->name); X strupr(tmp); X if (!strcmp(tmp, name)) return(hp->value); X hp = hp->next; X } X return(NULL); X} X X X/* X * Look for a field in the header table in memory. X * If found, mark the field as READ, and return its adress. X * Otherwise, return NILHEAD. X */ Xstatic HEADER *hsearch(name) Xchar *name; X{ X register HEADER *hp; X char tmp[48]; X X hp = hlist; X while (hp != NILHEAD) { X strcpy(tmp, hp->name); X strupr(tmp); X if (!strcmp(tmp, name)) { X if (hp->done == 0) { X hp->done = 1; X return(hp); X } X } X hp = hp->next; X } X return(NILHEAD); X} X X X/* X * Decode an old-style (V6/V7) mail header. X * This has a syntax like: X * X * From <user> <date> [remote from <host>] X * To: <user> X * Subject: <text> X * X * We want to find out the <user>, <date> and possible <date> fields. X * Return TRUE for OK, or FALSE if error. X */ Xstatic int get_oldhdr(rmt) Xint *rmt; /* REMOTE or LOCAL mail? */ X{ X register char *bp, *sp, *cp; X X sp = hfind("FROM "); X if (sp == NULL) { /* No From-line??? */ X sprintf(errmsg, "%s: no From line", dfile); X return(FALSE); X } X X strcpy(olduser, sp); /* stuff field into 'user' */ X sp = olduser; /* skip until <date> field */ X while (*sp && *sp!=' ' && *sp!='\t') sp++; X *sp++ = '\0'; /* mark 'end-of-user' */ X X /* X * SP now contains <date> and (possible) <remote> fields. X * Parse line to seek out "remote from". X */ X cp = sp; /* save the Date-pointer */ X while (TRUE) { X bp = strchr(sp++, 'r'); X if (bp != NULL) { /* we found an 'r' */ X if (!strncmp(bp, "remote from ", 12)) break; X } else break; X } X X if (bp != NULL) { /* remote host found --> remote mail */ X sp = strrchr(bp, ' '); /* seek to start of "remote from" text */ X *(bp - 1) = '\0'; /* mark end-of-date */ X strcpy(olddate, cp); /* set old date */ X strcpy(oldhost, ++sp); /* set host name */ X sprintf(mailsender, "%s!%s", oldhost, olduser); X *rmt = TRUE; X } else { X strcpy(olddate, cp); /* set old date */ X strcpy(oldhost, ""); /* no remote host */ X strcpy(mailsender, olduser); X *rmt = FALSE; X } X return(TRUE); X} X X X/* X * Analyze the current header. X * X * See if this mail was generated locally or came from somewhere else. X * Note, that old-style mailers use "postmarks" (i.e. header lines X * looking like "From <user> <date>" with a possible suffix of X * "remote from <host>". New-style mailers (should) only use the X * "From: <path>" and "Date: <date>" lines in their headers. X * UMAIL knows both types. By default it uses new-style headers, X * but it can use (and generate) old headers by defining OLDMAILER. X * X * Return TRUE if we think this mail has been generated remotely, X * or FALSE if this message was generated by local mail. X */ Xstatic int chk_hdr(void) X{ X int remmail; /* remote mail? */ X long now; X register char *sp, *bp; /* fast scanning pointers */ X X bp = hfind("FROM"); /* get RFC-From: field */ X sp = hfind("DATE"); /* get RFC-Date: field */ X X if (sp==NULL || bp==NULL) { /* should have both or none! */ X if (oldmailer == TRUE) { /* try old-style header */ X if (get_oldhdr(&remmail) == FALSE) { X strcat(errmsg, "\n\nBad adress or header!\n"); X return(FALSE); X } X } X } else { /* only use new-style From:=lines */ X strcpy(olddate, sp); /* Save the DATE field */ X strcpy(oldhost, bp); X sp = oldhost; /* skip comments */ X while (*sp && *sp!=' ' && *sp!='\t') sp++; X *sp = '\0'; X strcpy(mailsender, oldhost); X X sp = strchr(oldhost, '!'); /* check for pathname! */ X if (sp != NULL) { /* found one; this was remote! */ X remmail = TRUE; X *sp++ = '\0'; X strcpy(olduser, sp); X } else { X remmail = FALSE; X strcpy(olduser, bp); X strcpy(oldhost, ""); X } X } X return(remmail); X} X X X/* X * Create a new RFC-822 message header. X * This is necessary because we are processing X * a locally-generated message. X * The header should become: X * X * From <host!user> <date> remote from <here> X * From: <host>!<user> X * Received: by <here> with <proto>; X * <receive-date> X * Sender: <user>@<host>.<domain> (Real Name) X * To: <user> X * Subject: <text> X */ Xstatic void new_hdr(outfp) XFILE *outfp; X{ X long rcvtm; /* current time */ X char *date; /* current date in MET */ X char *fmt1 = "%s:%s\n"; X char *fmt2 = "%s\n"; X register char *sp; X X /* get the current date and time */ X time(&rcvtm); date = maketime(&rcvtm); X X if (oldmailer == TRUE) { X fprintf(outfp, "From %s %s remote from %s\n", X olduser, xtime(&rcvtm), myname); X } X fprintf(outfp, "From: %s!%s (%s)\n", myname, olduser, realname(olduser)); X fprintf(outfp, "Received: by %s.%s (UMAIL %s) with UUCP;\n %s\n", X myname, mydomain, Version, date); X fprintf(outfp, "Sender: %s (%s)\n", full_id(olduser), realname(olduser)); X if (myorg != NULL) fprintf(outfp, "Organization: %s\n", myorg); X if ((sp = hfind("TO")) != NULL) fprintf(outfp, "To: %s\n", sp); X if ((sp = hfind("SUBJECT")) != NULL) fprintf(outfp, "Subject: %s\n", sp); X fprintf(outfp, "Date: %s\n", olddate); X fprintf(outfp, "\n"); X} X X X/* X * Update the current header. X * This is necessary because the message comes from X * a remote system without RFC-conforming mailer... X * We should include ALL RFC-822 fields in this routine! X */ Xstatic void upd_hdr(outfp) XFILE *outfp; X{ X long rcvtm; /* current time */ X char *date; /* current date in MET */ X char *fmt1 = "%s: %s\n"; X char *fmt2 = "%s\n"; X register char *sp; X register HEADER *hp; X X /* get the current date and time */ X time(&rcvtm); date = maketime(&rcvtm); X X /* First of all, get the Old V6/V7 From-line */ X if (oldmailer == TRUE) { X hp = hsearch("FROM "); /* to make it DONE */ X if (oldhost[0] == '\0') X fprintf(outfp, "From %s %s remote from %s\n", X olduser, xtime(&rcvtm), myname); X else fprintf(outfp, "From %s!%s %s remote from %s\n", X oldhost, olduser, xtime(&rcvtm), myname); X } X X /* X * Write the modified From:-line X * Note, that we must only add our name if the mail is to be forwarded X * to another system. If it will be delivered locally, leave it. X */ X hp = hsearch("FROM"); X if (hp != NILHEAD) { X if (aremote == TRUE) { /* adressee is REMOTE. add our name! */ X fprintf(outfp, "%s: %s!%s\n", hp->name, myname, hp->value); X } else { /* adressee is LOCAL */ X fprintf(outfp, "%s: %s\n", hp->name, hp->value); X } X } X X /* Our own Receive:-line */ X fprintf(outfp, "Received: by %s.%s (UMAIL %s) with UUCP;\n %s\n", X myname, mydomain, Version, date); X X /* Next, all other Received:-lines */ X while ((hp = hsearch("RECEIVED")) != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* The old Sender:-line */ X hp = hsearch("SENDER"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* insert all unknown fields here */ X hp = hlist; X while (hp != NILHEAD) { X if (hp->std == 0) { X hp->done = 1; X fprintf(outfp, fmt1, hp->name, hp->value); X } X hp = hp->next; X } X X /* Write the To:-line too */ X hp = hsearch("TO"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* The CarbonCopy Cc:-line */ X hp = hsearch("CC"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* And the BlindCarbonCopy as well */ X hp = hsearch("BCC"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* Finally, the old Subject:-line */ X hp = hsearch("SUBJECT"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* A message ID */ X hp = hsearch("MESSAGE-ID"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } X X /* And the old date of sending */ X hp = hsearch("DATE"); X if (hp != NILHEAD) { X if (hp->count > 1) fprintf(outfp, fmt2, hp->value); X else fprintf(outfp, fmt1, hp->name, hp->value); X } else fprintf(outfp, fmt1, "Date: ", date); X X /* an empty line marks the end of the header! */ X fprintf(outfp, "\n"); X} X X X/* X * Read the message-header into memory. X */ Xstatic int read_hdr(infp) Xregister FILE *infp; X{ X char hdrbuf[1024]; X char lastf[128]; X int i, numfields = 0; X int lastc = 1; X register HEADER *hp, *xp; X register char *bp, *sp; X X while (TRUE) { X if (mfgets(hdrbuf, 1024, infp) == NULL) break; /* end of file */ X if (hdrbuf[0] == '\0') break; /* end of header */ X X numfields++; X bp = hdrbuf; X X /* first check if this is the V6/V7 From-line */ X if (strncmp(hdrbuf, "From ", 5)) { X /* No From-line. */ X if (*bp==' ' || *bp=='\t') { X lastc++; /* next part of previous field */ X bp = lastf; /* previous field */ X sp = hdrbuf; /* value */ X } else { X sp = strchr(bp, ':'); /* plain field, get sepa */ X if (sp != NULL) { /* do we have one? */ X *sp++ = '\0'; /* end it */ X while (*sp && (*sp==' ' || *sp=='\t')) sp++; X strcpy(lastf, bp); /* set as prev field */ X lastc = 1; X } else sp = bp; /* no sepa, use entire field */ X } X } else { X bp = "From "; X sp = &hdrbuf[5]; X } X X /* Add a new header field to the message header in memory */ X hp = (HEADER *) malloc(sizeof(HEADER)); /* allocate new variable */ X if (hlist == NILHEAD) { /* first variable */ X hlist = hp; X } else { X xp = hlist; X while (xp->next != NILHEAD) xp = xp->next; X xp->next = hp; X } X X hp->next = NILHEAD; X hp->name = (char *) malloc(strlen(bp) + 2); X hp->value = (char *) malloc(strlen(sp) + 2); X X strcpy(hp->name, bp); X strcpy(hp->value, sp); X hp->done = 0; /* not yet read */ X hp->count = lastc; /* folding level */ X hp->std = 0; /* standard field? */ X X /* now see if this field is an RFC-822 field */ X i = 0; X sp = rfcfields[i]; X strcpy(hdrbuf, hp->name); /* convert field name to uppercase */ X strupr(hdrbuf); X while (sp != NULL) { X if (!strcmp(sp, hdrbuf)) break; X sp = rfcfields[++i]; X } X if (sp != NULL) hp->std = 1; X } X} X X X/* X * Read the header from the input file 'infd', and adapt some X * fields to the new values. X * Then, sort the entries and generate a new header. X * Put that new header into file 'outfp'. X * Return TRUE if REMOTE, FALSE if LOCAL mail. X */ Xint header(infp, outfp) Xregister FILE *infp; Xregister FILE *outfp; X{ X int remote; X char *sp; X X (void) read_hdr(infp); /* read in the current header */ X X remote = chk_hdr(outfp); /* analyze old header */ X X if (remote == FALSE) new_hdr(outfp); /* locally-generated mail */ X else upd_hdr(outfp); X X return(remote); X} + END-OF-FILE umheader.c chmod 'u=rw,g=r,o=r' 'umheader.c' set `wc -c 'umheader.c'` count=$1 case $count in 12680) :;; *) echo 'Bad character count in ''umheader.c' >&2 echo 'Count should be 12680' >&2 esac echo Extracting 'ummain.c' sed 's/^X//' > 'ummain.c' << '+ END-OF-FILE ''ummain.c' X/* X * UMAIL - MINIX Remote Domain-adressing Mail Router X * X * This version of RMAIL handles message-headers in a much X * more "standard" way. It can handle bang-adresses, plus X * the new-style Internet adressing (user@host.domain). X * It is called by programs as "Mail" and "Uuxqt". X * X * Usage: umail [-c <config>] [-d] [-i <infile>] [-n] <user> ... X * X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl) X */ X#include <stdio.h> X#include <string.h> X#include <alloc.h> X#include <ctype.h> X#include <time.h> X#include <pwd.h> X#include "umail.h" X X Xchar *Version = VERSION; /* UMAIL version ID */ Xint immediate, debug = FALSE; /* commandline option flags */ Xint restrict = FALSE; /* restricted (UUCP) use only */ Xint aremote; /* is the adressee REMOTE or LOCAL ? */ Xchar dfile[128], infile[128]; /* names of message temp-files */ Xchar errmsg[512]; /* global error message */ Xchar mailsender[1024]; /* who sent the message? */ Xchar mailaddr[1024]; /* final routed adress to use. */ Xchar mailhost[64]; /* which host to send to */ Xchar mailcmd[512]; /* command to use to send the mail */ Xchar mailopts[64]; /* which options the mailer uses */ XNAME *namelist = NILNAME; /* list of my network names */ XVAR *varlist = NILVAR; /* list of configuration variables */ XHOST *hostlist = NILHOST; /* list of reacheable host names */ XROUTE *routemap = NILROUTE; /* list of domain routes */ X X/* configuration settings */ Xchar *myname = NULL; /* my UUCP site name */ Xchar *mydomain = NULL; /* my UUCP domain name */ Xchar *myorg = NULL; /* Name of my organization */ Xint oldmailer = FALSE; /* does our mailer use old From-lines? */ Xint escape = FALSE; /* can we offer a routing-escape? */ X X Xextern int getopt(), optind; /* from standard library */ Xextern char *optarg, *fgets(); Xextern long ftell(); X X X/* X * Convert strings S to upper case. X */ Xchar *strupr(s) Xchar *s; X{ X register char *sp; X X sp = s; X while (*sp) { X if (*sp>='a' && *sp<='z') *sp = _toupper(*sp); X sp++; X } X return(s); X} X X X/* X * Convert strings S to lower case. X */ Xchar *strlwr(s) Xchar *s; X{ X register char *sp; X X sp = s; X while (*sp) { X if (*sp>='A' && *sp<='Z') *sp = _tolower(*sp); X sp++; X } X return(s); X} X X X/* X * Add 'NAME' to the list of our names. X */ Xvoid add_name(name) Xchar *name; X{ X register NAME *np, *xp; X X np = (NAME *) malloc(sizeof(NAME)); /* allocate new variable */ X if (namelist == NILNAME) { /* first variable */ X namelist = np; X } else { X xp = namelist; X while (xp->next != NILNAME) xp = xp->next; X xp->next = np; X } X X np->next = NILNAME; X np->name = (char *) malloc(strlen(name) + 2); X X strcpy(np->name, name); X} X X X/* X * Add host 'NAME' to the list of hosts. X */ Xvoid add_host(name, smart, cmd, opts) Xchar *name; Xint smart; Xchar *cmd; Xchar *opts; X{ X register HOST *hp, *xp; X X hp = (HOST *) malloc(sizeof(HOST)); /* allocate new variable */ X if (hostlist == NILHOST) { /* first variable */ X hostlist = hp; X } else { X xp = hostlist; X while (xp->next != NILHOST) xp = xp->next; X xp->next = hp; X } X X hp->next = NILHOST; X hp->name = (char *) malloc(strlen(name) + 2); X hp->command = (char *) malloc(strlen(cmd) + 2); X hp->opts = (char *) malloc(strlen(opts) + 2); X X strcpy(hp->name, name); X strcpy(hp->command, cmd); X strcpy(hp->opts, opts); X hp->smart = smart; X} X X X/* X * Add route 'DOMAIN' to the routing table. X */ Xvoid add_route(domain, host, route) Xchar *domain; Xchar *host; Xchar *route; X{ X register ROUTE *rp, *xp; X X rp = (ROUTE *) malloc(sizeof(ROUTE)); /* allocate new route */ X if (routemap == NILROUTE) { /* first route */ X routemap = rp; X } else { X xp = routemap; X while (xp->next != NILROUTE) xp = xp->next; X xp->next = rp; X } X X rp->next = NILROUTE; X rp->domain = (char *) malloc(strlen(domain) + 2); X rp->host = (char *) malloc(strlen(host) + 2); X rp->route = (char *) malloc(strlen(route) + 2); X X strcpy(rp->domain, domain); X strcpy(rp->host, host); X strcpy(rp->route, route); X} X X X/* X * Add variable 'NAME' to the variable list. X */ Xvoid add_var(name, val) Xchar *name; Xchar *val; X{ X register VAR *vp, *xp; X X strupr(name); X X vp = (VAR *) malloc(sizeof(VAR)); /* allocate new variable */ X if (varlist == NILVAR) { /* first variable */ X varlist = vp; X } else { X xp = varlist; X while (xp->next != NILVAR) xp = xp->next; X xp->next = vp; X } X X vp->next = NILVAR; X vp->name = (char *) malloc(strlen(name) + 2); X vp->value = (char *) malloc(strlen(val) + 2); X X strcpy(vp->name, name); X strcpy(vp->value, val); X} X X X/* X * Get a variable from the variable list. X * Return NULL if not defined. X */ Xchar *lookup(what) Xchar *what; X{ X register VAR *vp; X X vp = varlist; X while (vp != NILVAR) { X if (!strcmp(vp->name, what)) return(vp->value); X vp = vp->next; X } X return(NULL); X} X X X/* X * Return TRUE or FALSE value, depending on X * the value of the given variable. X */ Xint boolean(ascii) Xchar *ascii; X{ X strupr(ascii); X if (ascii==NULL || !strcmp(ascii, "FALSE")) return(FALSE); X else if (!strcmp(ascii, "TRUE")) return(TRUE); X else fprintf(stderr, "Bad value of boolean: \"%s\"\n", ascii); X return(FALSE); X} X X X/* X * Lookup a host in our hosts-table. X */ XHOST *gethost(host) Xchar *host; X{ X register HOST *hp; X X hp = hostlist; X while (hp != NILHOST) { X if (!strcmp(hp->name, host)) return(hp); X hp = hp->next; X } X return(NILHOST); X} X X X/* X * Lookup a domain in our domain-table. X */ XROUTE *getdomain(domain) Xchar *domain; X{ X register ROUTE *rp; X X rp = routemap; X while (rp != NILROUTE) { X if (!strcmp(rp->domain, domain)) return(rp); X rp = rp->next; X } X return(NILROUTE); X} X X X/* X * mfgets (modified fgets) X * Same as fgets() only this version deletes '\n' X */ Xchar *mfgets(s, n, iop) Xchar *s; Xregister int n; Xregister FILE *iop; X{ X register int c; X register char *cs; X X cs = s; X while (--n > 0 && (c = getc(iop)) != EOF) { X if (c == '\n') { X *cs = '\0'; X break; X } else *cs++ = c; X } X return((c == EOF && cs == s) ? (char *)NULL : s); X} X X X/* X * Return the full UUCP ID of the calling user X */ Xchar *full_id(user) Xchar *user; X{ X static char fullbuf[48]; X X sprintf(fullbuf, "%s@%s.%s", user, myname, mydomain); X return(fullbuf); X} X X X/* X * Return the Real Name of the calling user X */ Xchar *realname(who) Xchar *who; X{ X struct passwd *pw; X X if ((pw = getpwnam(who)) != NULL) return(pw->pw_gecos); X else return("unknown flag"); X} X X X/* X * Make a decent DATE/TIME string. X * Note, that there are TWO possible date formats: X * X * Sat, 12 Oct 89 20:29:00\0 X * and X * Sat 12 Oct 20:29:00 1989\0 X * X * Most Internet mailers use this first form, so we try X * to this also. We use the function xtime() for the work... X */ Xchar *maketime(salt) Xlong *salt; X{ X static char datetime[48]; /* date and time in MET format */ X char *sp; X X sp = lookup("TIMEZONE"); /* get Time Zone from config file */ X if (sp == NULL) sp = ""; /* must have SOME pointer! */ X X sprintf(datetime, "%s %s", xtime(salt), sp); X X return(datetime); X} X X X/* X * Copy a file from 'inf' to 'outf'. X */ Xvoid fcopy(inf, outf) Xregister FILE *inf, *outf; X{ X char cpbuff[1024]; X X while (TRUE) { X if (fgets(cpbuff, sizeof(cpbuff), inf) == (char *)NULL) break; X fwrite(cpbuff, sizeof(char), strlen(cpbuff), outf); X } X} X X X/* X * Load the configuration parameters into their variables. X */ Xstatic void setup(cfg) Xchar *cfg; X{ X if (scanner(cfg) != 0) { /* read the configuration file */ X perror(cfg); X exit(1); X } X X myname = lookup("SYSTEM"); X if (myname == NULL) { X fprintf(stderr, "Missing SYSTEM definition\n"); X exit(-1); X } X mydomain = lookup("DOMAIN"); X if (mydomain == NULL) { X fprintf(stderr, "Missing DOMAIN definition\n"); X exit(-1); X } X myorg = lookup("ORGANIZATION"); X oldmailer = boolean(lookup("OLDMAILER")); X escape = boolean(lookup("ESCAPE")); X} X X X/* X * Something went wrong. X * Tell the caller how we should be called! X */ Xstatic void usage() X{ X fprintf(stderr, X "Usage: umail [-c <config>] [-d] [-i <infile>] [-n] <users>\n"); X} X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *fdfile, *infp; /* message file pointers */ X BOX *box; /* conversion/routing adresses */ X char *cfgfile = CONFIG; /* config file; to save space */ X register int st; /* error status, to exit() */ X X if (argv[0][0] == 'r') { /* 'rmail' link? */ X restrict = TRUE; /* yes, restrict usage */ X } X X while ((st = getopt(argc, argv, "c:di:n")) != EOF) switch(st) { X case 'c': /* use non-standard CONFIGH file */ X cfgfile = optarg; X break; X X case 'd': /* turn on DEBUG mode */ X debug = TRUE; X break; X case 'i': /* use non-stdin input file */ X strncpy(infile, optarg, 128 - 1); X break; X case 'n': /* call UUCICO after processing */ X immediate = TRUE; X break; X default: X usage(); X exit(1); X } X X if (optind >= argc) { /* we need another parameter! */ X usage(); /* (the adressee ) */ X exit(-1); X } X X umask(0117); /* change umask to -rw-rw---- */ X X setup(cfgfile); /* read CONFIG and setup */ X X strcpy(dfile, "/tmp/umXXXXXX"); /* create temp. message file */ X mktemp(dfile); X if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL) { X perror("rmail 1"); X exit(1); X } X X box = convert(argv[optind]); /* convert Internet adress to UUCP */ X if (box == NILBOX) st = FALSE; X else st = route(box); /* run it through routing tables */ X X if (infile[0] != '\0') { /* open input file if -i option */ X infp = fopen(infile, "r"); X if (infp == (FILE *)NULL) { X perror(infile); X exit(1); X } X } else infp = stdin; /* otherwise use stdin! */ X X header(infp, fdfile); /* analyze message header */ X X fcopy(infp, fdfile); /* copy message to the temp. file */ X X fclose(fdfile); X if (infp != stdin) fclose(infp); X X if (st == FALSE) { /* conversion/routing went wrong? */ X errmail(errmsg, FALSE); /* yes; return the message! */ X st = -1; X } else st = sendit(mailaddr, mailhost, mailcmd, mailopts, dfile); X X unlink(dfile); /* remote data file */ X exit(st); /* and exit! */ X} + END-OF-FILE ummain.c chmod 'u=rw,g=r,o=r' 'ummain.c' set `wc -c 'ummain.c'` count=$1 case $count in 10125) :;; *) echo 'Bad character count in ''ummain.c' >&2 echo 'Count should be 10125' >&2 esac exit 0