/*--------------------------------------------------------------------*/ /* r m a i l . c */ /* */ /* Delivery agent for UUPC/extended */ /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/ /* Changes Copyright (c) 1989 by Andrew H. Derbyshire. */ /* */ /* Changes Copyright (c) 1990-1993 by Kendra Electronic */ /* Wonderworks. */ /* */ /* All rights reserved except those explicitly granted by the */ /* UUPC/extended license agreement. */ /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/ /* RCS Information */ /*--------------------------------------------------------------------*/ /* * $Id: RMAIL.C 1.8 1993/04/15 03:17:21 ahd Exp $ * * $Log: RMAIL.C $ * Revision 1.8 1993/04/15 03:17:21 ahd * Correct conditions under which name in userp structure used * * Revision 1.7 1993/04/13 02:26:30 ahd * Make return codes more unique * * Revision 1.6 1993/04/11 00:33:05 ahd * Global edits for year, TEXT, etc. * * Revision 1.5 1992/12/05 23:38:43 ahd * Let logger close the log, not rmail * * Revision 1.4 1992/12/04 01:00:27 ahd * Add copyright messages * */ /*--------------------------------------------------------------------*/ /* Function: Stand alone mail delivery module for */ /* UUPC/extended */ /* Language: Borland C++ 3.1 (ANSI C mode) or Microsoft C 6.0. */ /* Arguments: One or more addresses to deliver mail to */ /* or "-t" to direct rmail to read the addresses */ /* from the RFC-822 header. */ /* A third mode of operation is to specify '-w' and/ */ /* or '-s subject' followed by one or more addresses */ /* with optional carbon copy flags (-c or -b) before */ /* additional addresses. This causes rmail to */ /* function like a bare bones batch version of the */ /* MAIL program; a valid RFC-822 header is generated */ /* and the mail is delivered, aliases are not expanded */ /* and the mail is not locally logged. (The current */ /* user id as the from address is used unless the */ /* environment variable LOGNAME is set, in which case */ /* it is used.) */ /* Optional argument "-f" to denote file to read in */ /* place of stdin. */ /* Optional argument "-F" to denote file to read in */ /* place of stdin and DELETE after readering. */ /* Optional argument "-x" to for debug level */ /* Input: mail to be delivered, with RFC-822 header, on */ /* stdin. */ /* Output: 'From' and 'Received:' headers are added, */ /* 'Bcc:' headers are removed, and the mail is */ /* delivered to one or more local users and/or */ /* one or more remote users. */ /* Exit code: 0 Success */ /* 1 One or more letters not delivered */ /* 2 No mail delivered */ /* 3 Configuration file error */ /* 4 Invalid option/help specified */ /* 5 Input/output error */ /* 6 Input/output error */ /* 7 Input/output error */ /* */ /* Note: When parsing RFC-822 headers, this program */ /* expects them to be "well-behaved", that is in */ /* format generated by UUPC/extended. This implies: */ /* */ /* One address per line */ /* */ /* Resent- headers, if any, before the original */ /* headers. */ /* */ /* From: header must precede To: header. */ /* */ /* To: header must precede Cc: and Bcc: headers. */ /* */ /* Cc: and Bcc: headers must be together (one */ /* after the other) */ /* */ /* The MUA has prefixed any obsolete Resent- */ /* headers by X- */ /* */ /* Note: The "-t" flag is supported by BSD sendmail for the */ /* purpose listed above, but we also turn use it to */ /* control other special options, all of which */ /* basically cause the program to act more like a */ /* local mailer than a remote mailer; these options */ /* include: */ /* */ /* Stripping off blind carbon copies */ /* */ /* Generating the UUCP From line differently */ /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/ /* System include files */ /*--------------------------------------------------------------------*/ #include #include #include #include #include #include #include /*--------------------------------------------------------------------*/ /* Application include files */ /*--------------------------------------------------------------------*/ #include "lib.h" #include "address.h" #include "arpadate.h" #include "deliver.h" #include "getopt.h" #include "hlib.h" #include "hostable.h" #include "logger.h" #include "security.h" #include "usertabl.h" #include "timestmp.h" #include "catcher.h" /*--------------------------------------------------------------------*/ /* Local defines */ /*--------------------------------------------------------------------*/ #define MOPLEN 10 /* Length of formatted header lines */ #define UUCPFROM "From " /* Length of UUCP incoming mail */ /*--------------------------------------------------------------------*/ /* Prototypes for internal files */ /*--------------------------------------------------------------------*/ static boolean CopyTemp( void ); static void ParseFrom( void ); static char **Parse822( boolean *header, size_t *count); static void Terminate( const int rc); static void PutHead( const char *label, const char *operand, FILE *stream, const boolean resent); static boolean DaemonMail( const char *subject, char **address, int count ); static void usage( void ); /*--------------------------------------------------------------------*/ /* Global variables */ /*--------------------------------------------------------------------*/ currentfile(); /* Declare file name for checkref() */ char *tempname = NULL; /* Pointer to temporary input file */ char *namein = CONSOLE; FILE *datain = stdin; /* Handle for reading input mail */ FILE *dataout = NULL; /* Handle for the output of mail */ char fromuser[MAXADDR] = ""; /* User id of originator */ char fromnode[MAXADDR] = ""; /* Node id of originator */ char *now; /* Time stamp for Received: banner */ static char received[] = "Received:"; static char receivedlen = sizeof( received) - 1; /*--------------------------------------------------------------------*/ /* main program */ /*--------------------------------------------------------------------*/ void main(int argc, char **argv) { boolean ReadHeader = FALSE; /* TRUE = Parse RFC-822 headers */ int option; /* For parsing option list */ char **address; /* Pointer to list of target addresses */ char *token; size_t addressees; /* Number of targets in address */ size_t count; /* Loop variable for delivery */ size_t delivered = 0; /* Count of successfull deliveries */ boolean header = TRUE; boolean DeleteInput = FALSE; boolean daemon = FALSE; char *subject = NULL; /*--------------------------------------------------------------------*/ /* Make a copy of the Borland copyright for debugging purposes */ /*--------------------------------------------------------------------*/ #if defined(__CORE__) copywrong = strdup(copyright); checkref(copywrong); #endif banner( argv); now = arpadate(); /* Set the current date */ debuglevel = -1; /* Set default so we can detect it */ /*--------------------------------------------------------------------*/ /* Load the UUPC/extended configuration file, and exit if any errors */ /*--------------------------------------------------------------------*/ if (!configure(B_MTA)) Terminate(3); /*--------------------------------------------------------------------*/ /* Handle control-C interrupts */ /*--------------------------------------------------------------------*/ if( signal( SIGINT, ctrlchandler ) == SIG_ERR ) { printmsg( 0, "Couldn't set SIGINT\n" ); panic(); } /*--------------------------------------------------------------------*/ /* Begin logging messages */ /*--------------------------------------------------------------------*/ openlog( NULL ); /*--------------------------------------------------------------------*/ /* Parse our operand flags */ /*--------------------------------------------------------------------*/ while ((option = getopt(argc, argv, "ws:tF:f:x:")) != EOF) { switch (option) { case 'w': daemon = TRUE; break; case 's': subject = optarg; daemon = TRUE; break; case 't': ReadHeader = TRUE; break; case 'x': debuglevel = atoi(optarg); break; case 'F': DeleteInput = TRUE; case 'f': namein = optarg; datain = FOPEN(namein , "r",TEXT_MODE); break; case '?': usage(); Terminate(4); } /* switch */ } /* while */ if ( debuglevel > 1 ) { for ( count = 1; (int) count < argc; count ++) printmsg(4,"rmail argv[%d] = \"%s\"", count, argv[count] ); } /* if ( debuglevel > 4 ) */ if ((optind == argc) != ReadHeader) { puts("Missing/extra parameter(s) at end."); Terminate(4); } remoteMail = ! (ReadHeader || daemon); /* If not reading headers, must be in normal rmail mode ... */ /*--------------------------------------------------------------------*/ /* If in local mode and the user doesn't want output, suppress */ /* routine delivery messages */ /*--------------------------------------------------------------------*/ if ( debuglevel == -1 ) { if (remoteMail) debuglevel = 1; else debuglevel = (int) bflag[F_VERBOSE]; } /*--------------------------------------------------------------------*/ /* Verify we have input stream available */ /*--------------------------------------------------------------------*/ if (datain == NULL ) { printerr(namein); Terminate(6); } /* if */ /*--------------------------------------------------------------------*/ /* Open up the output data stream */ /*--------------------------------------------------------------------*/ tempname = mktempname( NULL , "TMP"); dataout = FOPEN(tempname, "w",TEXT_MODE); if (dataout == NULL) { printmsg(0,"Cannot open temporary file \"%s\" for output", tempname); Terminate(5); } /* if */ /*--------------------------------------------------------------------*/ /* If in local mail mode, make up a list of addresses to mail to */ /*--------------------------------------------------------------------*/ if ( daemon ) { addressees = argc - optind; address = &argv[optind]; DaemonMail( subject, address, addressees ); header = FALSE; } else if (ReadHeader) address = Parse822( &header, &addressees ); else { ParseFrom(); /* Copy remote header instead */ addressees = argc - optind; address = &argv[optind]; } /* if */ if ( addressees == 0 ) /* Can we deliver mail? */ { printmsg(0, "No addressees to deliver to!"); Terminate( 2 ); /* No --> Execute punt formation */ } /*--------------------------------------------------------------------*/ /* Copy the rest of the input file into our holding tank */ /*--------------------------------------------------------------------*/ header = CopyTemp( ) && header ; if (header) /* Was the header ever terminated? */ { printmsg(0,"rmail: Improper header, adding trailing newline"); fputc('\n', dataout); /* If not, it is now ... */ } fclose(datain); fclose(dataout); if (DeleteInput) /* Make room for more data on disk */ remove(namein); /*--------------------------------------------------------------------*/ /* Determine requestor node and user id for remote mail */ /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/ /* Perform delivery of the mail */ /*--------------------------------------------------------------------*/ while ((token = strpbrk(tempname ,"/")) != NULL) *token = '\\'; for ( count = 0; count < addressees; count++) if ( *address[count] == '-') delivered ++; /* Ignore option flags on delivery */ else delivered += Deliver(tempname, address[count], FALSE, TRUE); /*--------------------------------------------------------------------*/ /* Terminate the program */ /*--------------------------------------------------------------------*/ printmsg(8,"rmail: %d addressees, delivered to %d mailboxes", addressees, delivered); if ( delivered >= addressees ) Terminate( 0 ); /* All mail delivered */ else if ( delivered == 0 ) Terminate( 2 ); /* No mail delivered */ else Terminate (1 ); /* Some mail delivered */ } /* main */ /*--------------------------------------------------------------------*/ /* T e r m i n a t e */ /* */ /* Cleanup open files and return to operating system */ /*--------------------------------------------------------------------*/ static void Terminate( const int rc) { if (tempname != NULL) /* Did temporary file get named? */ { if (datain != stdin) /* Non-standard input? */ fclose(stdin); /* Yes --> Close it */ remove(tempname); /* Purge temporary file, if exists */ } /* if */ exit( rc ); /* Return to operating systems */ } /* Terminate */ /*--------------------------------------------------------------------*/ /* P a r s e F r o m */ /* */ /* Read the from address of incoming data from UUCP */ /*--------------------------------------------------------------------*/ static void ParseFrom() { static char from[] = "From "; static char remote[] = "remote from "; static int remotelen = sizeof remote - 1; static int fromlen = sizeof from - 1; char *token; char buf[BUFSIZ]; boolean hit; /*--------------------------------------------------------------------*/ /* Use UUXQT Information, if available */ /*--------------------------------------------------------------------*/ token = getenv( UU_MACHINE ); if ( token == NULL ) *fromnode = '\0'; else { strncpy( fromnode, token , sizeof fromnode ); fromnode[ sizeof fromnode - 1 ] = '\0'; } fgets(buf, BUFSIZ , datain); hit = equaln(buf, from, fromlen ); if (hit) { int nodelen = strlen( fromnode ) + 1; /* Plus ! */ char *s; token = strtok( &buf[ fromlen ], " "); s = strtok( NULL, "\n"); if (strlen( token ) + nodelen >= MAXADDR) { char *next; token = strtok( token, "!" ); while ((next = strtok( NULL , "!")) != NULL ) { token = next; if (strlen( next ) + nodelen < MAXADDR) break; } /* while */ } /* if */ strncpy(fromuser, token , sizeof fromuser ); fromuser[ sizeof fromuser - nodelen ] = '\0'; if ( *fromnode == '\0') { while ( *s != '\0') { if equaln(s, remote, remotelen) break; else s++; } /* while */ strncpy( fromnode , (*s == '\0') ? E_nodename : s + remotelen , sizeof fromnode ); fromnode[ sizeof fromnode -1 ] = '\0'; } /* if ( *fromnode != '\0') */ } /* if */ else { if ( *fromnode == '\0') strcpy(fromnode, E_nodename ); strcpy(fromuser, "/dev/null"); } /* else */ /*--------------------------------------------------------------------*/ /* Generate required "From " and "Received" header lines */ /*--------------------------------------------------------------------*/ fprintf(dataout,"%-10s from %s by %s (%s %s) with UUCP;\n%-10s %s\n", "Received:", fromnode, E_domain, compilep, compilev, " ", now); /*--------------------------------------------------------------------*/ /* If what we read wasn't a From line, write into the new file */ /*--------------------------------------------------------------------*/ if (!hit) { fputs(buf, dataout); if (ferror(dataout)) { printerr(tempname); Terminate(6); } /* if */ } /* if */ /*--------------------------------------------------------------------*/ /* Determine the requestor user id and node */ /*--------------------------------------------------------------------*/ token = getenv( UU_USER ); /* Get exactly what remote told us */ if ( token != NULL ) { /* Use exactly what remote told us */ ruser = strtok( token , WHITESPACE ); rnode = strtok( NULL , WHITESPACE ); } /* else */ if ((rnode == NULL) || (strchr(rnode,'.') == NULL )) /* Did it tell us the domain? */ { /* No --> Use from information */ char node[MAXADDR]; char user[MAXADDR]; sprintf(buf ,"%s!%s", fromnode, fromuser); user_at_node(buf , buf, node, user); ruser = newstr( user ); rnode = newstr( node ); } uuser = "uucp"; /* Effective id is always our daemon */ } /* ParseFrom */ /*--------------------------------------------------------------------*/ /* P a r s e 8 2 2 */ /* */ /* Parse an RFC-822 header generated by that esteemed mail user */ /* agent, UUPC/extended's MAIL. */ /* */ /* Note that we parse the header in the format we KNOW that UUPC */ /* generated it in: "To:", "Cc:", "Bcc:", optionally prefixed */ /* by "Resent-". We also know that mail comes in one address */ /* per line, and that the Resent- headers, if any, precede the */ /* original headers. */ /*--------------------------------------------------------------------*/ static char **Parse822( boolean *header, size_t *count) { /*--------------------------------------------------------------------*/ /* Define the headers we will be examining and variables for their */ /* lengths */ /*--------------------------------------------------------------------*/ static char *to = "Resent-To:"; static char *cc = "Resent-Cc:"; static char *bcc = "Resent-Bcc:"; static char *resent = "Resent-"; static char *from = "Resent-From:"; size_t tolen; size_t cclen; size_t bcclen; size_t resentlen = strlen(resent); size_t offset = resentlen; /* Subscript for examining headers, which allows us to ignore Resent- */ size_t fromlen = strlen( &from[offset] ); size_t allocated = 5; /* Reasonable first size for address */ /* Note: MUST BE AT LEAST 2 because we add 50% below! */ boolean blind = FALSE; char **addrlist = calloc( sizeof *addrlist , allocated); char buf[BUFSIZ]; /* Input buffer for reading header */ char address[MAXADDR]; /* Buffer for parsed address */ char path[MAXADDR]; char *token; /* For parsing line in buf */ struct HostTable *hostp; /*--------------------------------------------------------------------*/ /* Begin processing */ /*--------------------------------------------------------------------*/ *count = 0; /* No addresses discovered yet */ checkref(addrlist); /* Verify we had room for the list */ fprintf(dataout,"%-10s by %s (%s %s);\n%-10s %s\n", "Received:",E_domain,compilep, compilev, " ", now ); /*--------------------------------------------------------------------*/ /* Find the From: line */ /*--------------------------------------------------------------------*/ do { if (fgets( buf, BUFSIZ, datain) == NULL) /* End of file? */ return NULL; /* Yes --> Very bad, report error */ fputs(buf, dataout ); if (*buf == '\n') /* End of the header? */ return NULL; /* Yes --> Very bad, report error */ else if (equalni(resent, buf, resentlen)) { offset = 0; fromlen = strlen(&from[offset]); } /* if */ else if (equalni(received, buf, receivedlen)) hops++; } while (!equalni(&from[offset], buf, fromlen)); strtok( buf , WHITESPACE); /* Drop the leading token */ token = strtok( NULL, "\n"); /* Get the token with From: addr */ ExtractAddress( address, token, FALSE ); /* Get the From: address itself */ user_at_node(address, path, fromnode, fromuser); /* Separate portions of the address */ /*--------------------------------------------------------------------*/ /* Generate a Sender: line if we need it */ /*--------------------------------------------------------------------*/ if (equal(fromnode,HostAlias(E_fdomain))) /* Same as hidden site? */ strcpy(fromnode, E_nodename);/* Yes --> Declare as local system */ hostp = checkname( fromnode ); /* Look up real system name */ if (!equal(fromuser,E_mailbox) || (hostp == BADHOST) || (hostp->hstatus != localhost)) { sprintf(buf, "%s <%s@%s>", E_name, E_mailbox, E_fdomain ); PutHead("Sender:", buf, dataout , offset == 0 ); } /* if */ /*--------------------------------------------------------------------*/ /* Set UUCP requestor name while we've got the information */ /*--------------------------------------------------------------------*/ if ((hostp != BADHOST) && (hostp->hstatus == localhost)) rnode = bflag[F_BANG] ? E_nodename : E_fdomain; /* Use full domain address, if possible */ else rnode = fromnode; uuser = ruser = fromuser; /* User and requestor always the same for locally generated mail */ /*--------------------------------------------------------------------*/ /* Generate a message-id */ /*--------------------------------------------------------------------*/ sprintf(buf, "<%lx.%s@%s>", time( NULL ) , E_nodename, E_domain); PutHead("Message-ID:", buf, dataout , offset == 0 ); PutHead(NULL, NULL, dataout , FALSE ); /*--------------------------------------------------------------------*/ /* Locate the To: or Resent-To: line */ /*--------------------------------------------------------------------*/ tolen = strlen( &to[offset] ); do { if (fgets( buf, BUFSIZ, datain ) == NULL) /* End of file? */ return NULL; /* Yes --> Very bad, report error */ fputs(buf, dataout ); if (*buf == '\n') /* End of the header? */ return NULL; /* Yes --> Very bad, report error */ else if (equalni(received, buf, receivedlen)) hops++; } while ( !equalni(&to[offset] , buf , tolen )); token = strpbrk( buf ," \t"); /*--------------------------------------------------------------------*/ /* Proccess the rest of the addressees */ /*--------------------------------------------------------------------*/ cclen = strlen( &cc[offset] ); bcclen = strlen( &bcc[offset] ); do { if (allocated == (*count+1)) /* Do we have room for addr? */ { allocated += allocated / 2; /* Choose larger array size */ addrlist = realloc( addrlist , allocated * sizeof( *addrlist )); checkref(addrlist); /* Verify the allocation worked */ } /* if */ ExtractAddress( address, token, FALSE ); /* Get address itself*/ if (!strlen(address)) { printmsg(0,"Could not locate expected address in header"); *count = 0; return NULL; } /* if */ else { addrlist[*count] = newstr( address ); /* Save permanent copy of address */ checkref( addrlist[*count] ); /* Verify strdup worked */ printmsg(4,"address[%d]= \"%s\"",*count, address); *count += 1; /* Flag we got the address */ } /* else */ if (fgets( buf, BUFSIZ, datain ) == NULL) /* End of file? */ token = NULL; /* Yes --> Odd, but no major problem */ else if (*buf == '\n') /* End of the header? */ { token = NULL; /* Yes --> Exit loop */ *header = FALSE; /* Report to caller the header is done */ blind = FALSE; /* Denote not a blind header */ } else if (isspace(*buf)) /* Another address? */ token = buf; /* Yes --> Write it out */ else { /* No --> Determine what next header is*/ blind = FALSE; /* Assume not a blind header */ if (equalni(&cc[offset], buf, cclen)) /* Cc: header? */ token = strpbrk(buf," \t"); else if (equalni(&bcc[offset], buf, bcclen)) /* Bcc: header?*/ { token = strpbrk(buf ," \t"); blind = TRUE; } /* if */ else /* Unsupported header, exit loop */ token = NULL; } /* else */ if ( ! blind ) fputs(buf, dataout ); } while (token != NULL ); /*--------------------------------------------------------------------*/ /* Return address list to caller */ /*--------------------------------------------------------------------*/ return addrlist; } /* Parse822 */ /*--------------------------------------------------------------------*/ /* C o p y T e m p */ /* */ /* Copy the un-parsed parts of a message into the holding file */ /*--------------------------------------------------------------------*/ static boolean CopyTemp( void ) { boolean header = TRUE; char buf[BUFSIZ]; boolean newline = TRUE; while (fgets(buf, BUFSIZ, datain) != NULL) { if (header) { if (*buf == '\n') header = FALSE; else if (equalni(received, buf, receivedlen)) hops++; } newline = buf[ strlen( buf ) - 1 ] == '\n'; if (fputs(buf, dataout) == EOF) /* I/O error? */ { printerr(tempname); printmsg(0,"I/O error on \"%s\"", tempname); fclose(dataout); return FALSE; } /* if */ } /* while */ if (ferror(datain)) /* Clean end of file on input? */ { printerr(namein); Terminate(7); } if ( !newline ) /* Is the file terminated properly? */ { printmsg(0, "rmail: Improperly formed message, adding final newline!"); fputc( '\n', dataout ); } return header; } /* CopyTemp */ /*--------------------------------------------------------------------*/ /* D a e m o n M a i l */ /* */ /* Send text in a mailbag file to address(es) specified by address */ /*--------------------------------------------------------------------*/ static boolean DaemonMail( const char *subject, char **address, int count ) { char buf[BUFSIZ]; char *logname; char *token; char *moi = NULL; struct UserTable *userp; char *header = "To:"; char *cc = "Cc:"; boolean print = TRUE; /*--------------------------------------------------------------------*/ /* Validate the input */ /*--------------------------------------------------------------------*/ if ( count == 0 ) { printmsg(0,"rmail: No addresseses to deliver to!"); return FALSE; } /*--------------------------------------------------------------------*/ /* Determine our user id */ /*--------------------------------------------------------------------*/ logname = getenv( LOGNAME ); if ( logname == NULL ) logname = E_mailbox; /*--------------------------------------------------------------------*/ /* Get the name of the user, or make one up */ /*--------------------------------------------------------------------*/ userp = checkuser(logname); /* Locate user id in host table */ if ( (userp != BADUSER) && (userp->realname != NULL) && !equal(userp->realname, EMPTY_GCOS )) moi = userp->realname; else if ( equali(logname, E_postmaster) || equali(logname, POSTMASTER)) moi = "Postmaster"; else if ( equali( logname, "uucp" )) moi = "Unix to Unix Copy"; else moi = logname; /* Dummy to ease formatting From: line */ /*--------------------------------------------------------------------*/ /* Add the boilerplate the front: */ /* */ /* Date, From, Organization, and Reply-To */ /*--------------------------------------------------------------------*/ fprintf(dataout,"%-10s by %s (%s %s);\n%-10s %s\n", "Received:",E_domain,compilep, compilev, " ", now ); /*--------------------------------------------------------------------*/ /* Generate a message-id */ /*--------------------------------------------------------------------*/ sprintf(buf, "<%lx.%s@%s>", time( NULL ) , E_nodename, E_domain); PutHead("Message-ID:", buf, dataout , FALSE ); PutHead(NULL, NULL, dataout , FALSE ); PutHead("Date:", arpadate() , dataout, FALSE); if (bflag[F_BANG]) sprintf(buf, "(%s) %s!%s", moi, E_nodename, logname ); else { checkname( E_nodename ); /* Force loading of the E_fdomain name */ sprintf(buf, "\"%s\" <%s@%s>", moi, logname , E_fdomain ); } PutHead("From:", buf, dataout, FALSE ); if (E_organization != NULL ) PutHead("Organization:", E_organization, dataout, FALSE); /*--------------------------------------------------------------------*/ /* Write the address out */ /*--------------------------------------------------------------------*/ while( (count-- > 0) && print ) { token = *address++; if ( *token == '-') /* Option flag? */ { if (token[1] == 'c') { header = cc; cc = ""; } else if (token[1] == 'b') print = FALSE; else printmsg(0,"rmail: Invalid flag \"%s\" ignored!", token); } /* if ( token == '-') */ else if ( print ) { if (strpbrk(token,"!@") == nil(char)) { if (bflag[F_BANG]) sprintf(buf, "%s!%s", E_nodename, token ); else sprintf(buf, "%s@%s", token , E_fdomain ); token = buf; } PutHead(header , token, dataout, FALSE); header = ""; /* Continue same field by default */ } } /* while( (count-- > 0) && print ) */ /*--------------------------------------------------------------------*/ /* Handle the subject, if any */ /*--------------------------------------------------------------------*/ if (subject != NULL) PutHead("Subject:", subject, dataout, FALSE); PutHead(NULL, "", dataout, FALSE); /* Terminate the header line */ PutHead(NULL, "", dataout, FALSE); /* Terminate the header file */ /*--------------------------------------------------------------------*/ /* Return to caller */ /*--------------------------------------------------------------------*/ uuser = ruser = strncpy(fromuser, logname, sizeof fromuser); /* Define user for UUCP From line */ fromuser[ sizeof fromuser - 1 ] = '\0'; rnode = bflag[F_BANG] ? E_nodename : E_fdomain; /* Use full domain address, if possible */ strcpy(fromnode, E_nodename);/* Declare as local system */ return TRUE; } /*DaemonMail*/ /*--------------------------------------------------------------------*/ /* P u t H e a d */ /* */ /* Write one line of an RFC-822 header */ /*--------------------------------------------------------------------*/ static void PutHead( const char *label, const char *operand, FILE *stream, const boolean resent) { static boolean terminate = TRUE; if (label == NULL ) /* Terminate call? */ { /* Yes --> Reset Flag and return */ fputc('\n', stream); /* Terminate the current line */ terminate = TRUE; return; } /* if */ if (strlen(label)) /* First line of a header? */ { if (!terminate) /* Terminate previous line? */ fputc('\n', stream); if (resent) fprintf(stream,"Resent-%s %s",label, operand); else fprintf(stream,"%-10s %s",label, operand); terminate = FALSE; /* Flag that we did not end file */ } /* if */ else /* Continuing line */ fprintf(stream,",\n%-10s %s",label, operand); } /* PutHead */ /*--------------------------------------------------------------------*/ /* u s a g e */ /* */ /* Report how the program works */ /*--------------------------------------------------------------------*/ static void usage( void ) { static char syntax[] = "Usage:\tRMAIL\t-t [-x debug] [-f | -F file]\n" "\t\t-w [-x debug] [-f | -F file] [-s subject] addr1 [-c] addr2 [-b] addr3 ...\n" "\t\t[-x debug] [-f | -F file] addr1 addr2 addr3 ...\n"; puts( syntax ); exit(3); }