19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 359b50d902SRodney W. Grimes static char sccsid[] = "@(#)send.c 8.1 (Berkeley) 6/6/93"; 369b50d902SRodney W. Grimes #endif /* not lint */ 379b50d902SRodney W. Grimes 389b50d902SRodney W. Grimes #include "rcv.h" 399b50d902SRodney W. Grimes #include "extern.h" 409b50d902SRodney W. Grimes 419b50d902SRodney W. Grimes /* 429b50d902SRodney W. Grimes * Mail -- a mail program 439b50d902SRodney W. Grimes * 449b50d902SRodney W. Grimes * Mail to others. 459b50d902SRodney W. Grimes */ 469b50d902SRodney W. Grimes 479b50d902SRodney W. Grimes /* 489b50d902SRodney W. Grimes * Send message described by the passed pointer to the 499b50d902SRodney W. Grimes * passed output buffer. Return -1 on error. 509b50d902SRodney W. Grimes * Adjust the status: field if need be. 519b50d902SRodney W. Grimes * If doign is given, suppress ignored header fields. 529b50d902SRodney W. Grimes * prefix is a string to prepend to each output line. 539b50d902SRodney W. Grimes */ 549b50d902SRodney W. Grimes int 559b50d902SRodney W. Grimes send(mp, obuf, doign, prefix) 569b50d902SRodney W. Grimes register struct message *mp; 579b50d902SRodney W. Grimes FILE *obuf; 589b50d902SRodney W. Grimes struct ignoretab *doign; 599b50d902SRodney W. Grimes char *prefix; 609b50d902SRodney W. Grimes { 619b50d902SRodney W. Grimes long count; 629b50d902SRodney W. Grimes register FILE *ibuf; 639b50d902SRodney W. Grimes char line[LINESIZE]; 649b50d902SRodney W. Grimes int ishead, infld, ignoring, dostat, firstline; 659b50d902SRodney W. Grimes register char *cp, *cp2; 669b50d902SRodney W. Grimes register int c; 679b50d902SRodney W. Grimes int length; 689b50d902SRodney W. Grimes int prefixlen; 699b50d902SRodney W. Grimes 709b50d902SRodney W. Grimes /* 719b50d902SRodney W. Grimes * Compute the prefix string, without trailing whitespace 729b50d902SRodney W. Grimes */ 739b50d902SRodney W. Grimes if (prefix != NOSTR) { 749b50d902SRodney W. Grimes cp2 = 0; 759b50d902SRodney W. Grimes for (cp = prefix; *cp; cp++) 769b50d902SRodney W. Grimes if (*cp != ' ' && *cp != '\t') 779b50d902SRodney W. Grimes cp2 = cp; 789b50d902SRodney W. Grimes prefixlen = cp2 == 0 ? 0 : cp2 - prefix + 1; 799b50d902SRodney W. Grimes } 809b50d902SRodney W. Grimes ibuf = setinput(mp); 819b50d902SRodney W. Grimes count = mp->m_size; 829b50d902SRodney W. Grimes ishead = 1; 839b50d902SRodney W. Grimes dostat = doign == 0 || !isign("status", doign); 849b50d902SRodney W. Grimes infld = 0; 859b50d902SRodney W. Grimes firstline = 1; 869b50d902SRodney W. Grimes /* 879b50d902SRodney W. Grimes * Process headers first 889b50d902SRodney W. Grimes */ 899b50d902SRodney W. Grimes while (count > 0 && ishead) { 909b50d902SRodney W. Grimes if (fgets(line, LINESIZE, ibuf) == NULL) 919b50d902SRodney W. Grimes break; 929b50d902SRodney W. Grimes count -= length = strlen(line); 939b50d902SRodney W. Grimes if (firstline) { 949b50d902SRodney W. Grimes /* 959b50d902SRodney W. Grimes * First line is the From line, so no headers 969b50d902SRodney W. Grimes * there to worry about 979b50d902SRodney W. Grimes */ 989b50d902SRodney W. Grimes firstline = 0; 999b50d902SRodney W. Grimes ignoring = doign == ignoreall; 1009b50d902SRodney W. Grimes } else if (line[0] == '\n') { 1019b50d902SRodney W. Grimes /* 1029b50d902SRodney W. Grimes * If line is blank, we've reached end of 1039b50d902SRodney W. Grimes * headers, so force out status: field 1049b50d902SRodney W. Grimes * and note that we are no longer in header 1059b50d902SRodney W. Grimes * fields 1069b50d902SRodney W. Grimes */ 1079b50d902SRodney W. Grimes if (dostat) { 1089b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1099b50d902SRodney W. Grimes dostat = 0; 1109b50d902SRodney W. Grimes } 1119b50d902SRodney W. Grimes ishead = 0; 1129b50d902SRodney W. Grimes ignoring = doign == ignoreall; 1139b50d902SRodney W. Grimes } else if (infld && (line[0] == ' ' || line[0] == '\t')) { 1149b50d902SRodney W. Grimes /* 1159b50d902SRodney W. Grimes * If this line is a continuation (via space or tab) 1169b50d902SRodney W. Grimes * of a previous header field, just echo it 1179b50d902SRodney W. Grimes * (unless the field should be ignored). 1189b50d902SRodney W. Grimes * In other words, nothing to do. 1199b50d902SRodney W. Grimes */ 1209b50d902SRodney W. Grimes } else { 1219b50d902SRodney W. Grimes /* 1229b50d902SRodney W. Grimes * Pick up the header field if we have one. 1239b50d902SRodney W. Grimes */ 1249b50d902SRodney W. Grimes for (cp = line; (c = *cp++) && c != ':' && !isspace(c);) 1259b50d902SRodney W. Grimes ; 1269b50d902SRodney W. Grimes cp2 = --cp; 1279b50d902SRodney W. Grimes while (isspace(*cp++)) 1289b50d902SRodney W. Grimes ; 1299b50d902SRodney W. Grimes if (cp[-1] != ':') { 1309b50d902SRodney W. Grimes /* 1319b50d902SRodney W. Grimes * Not a header line, force out status: 1329b50d902SRodney W. Grimes * This happens in uucp style mail where 1339b50d902SRodney W. Grimes * there are no headers at all. 1349b50d902SRodney W. Grimes */ 1359b50d902SRodney W. Grimes if (dostat) { 1369b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1379b50d902SRodney W. Grimes dostat = 0; 1389b50d902SRodney W. Grimes } 1399b50d902SRodney W. Grimes if (doign != ignoreall) 1409b50d902SRodney W. Grimes /* add blank line */ 1419b50d902SRodney W. Grimes (void) putc('\n', obuf); 1429b50d902SRodney W. Grimes ishead = 0; 1439b50d902SRodney W. Grimes ignoring = 0; 1449b50d902SRodney W. Grimes } else { 1459b50d902SRodney W. Grimes /* 1469b50d902SRodney W. Grimes * If it is an ignored field and 1479b50d902SRodney W. Grimes * we care about such things, skip it. 1489b50d902SRodney W. Grimes */ 1499b50d902SRodney W. Grimes *cp2 = 0; /* temporarily null terminate */ 1509b50d902SRodney W. Grimes if (doign && isign(line, doign)) 1519b50d902SRodney W. Grimes ignoring = 1; 1529b50d902SRodney W. Grimes else if ((line[0] == 's' || line[0] == 'S') && 1539b50d902SRodney W. Grimes strcasecmp(line, "status") == 0) { 1549b50d902SRodney W. Grimes /* 1559b50d902SRodney W. Grimes * If the field is "status," go compute 1569b50d902SRodney W. Grimes * and print the real Status: field 1579b50d902SRodney W. Grimes */ 1589b50d902SRodney W. Grimes if (dostat) { 1599b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1609b50d902SRodney W. Grimes dostat = 0; 1619b50d902SRodney W. Grimes } 1629b50d902SRodney W. Grimes ignoring = 1; 1639b50d902SRodney W. Grimes } else { 1649b50d902SRodney W. Grimes ignoring = 0; 1659b50d902SRodney W. Grimes *cp2 = c; /* restore */ 1669b50d902SRodney W. Grimes } 1679b50d902SRodney W. Grimes infld = 1; 1689b50d902SRodney W. Grimes } 1699b50d902SRodney W. Grimes } 1709b50d902SRodney W. Grimes if (!ignoring) { 1719b50d902SRodney W. Grimes /* 1729b50d902SRodney W. Grimes * Strip trailing whitespace from prefix 1739b50d902SRodney W. Grimes * if line is blank. 1749b50d902SRodney W. Grimes */ 1759b50d902SRodney W. Grimes if (prefix != NOSTR) 1769b50d902SRodney W. Grimes if (length > 1) 1779b50d902SRodney W. Grimes fputs(prefix, obuf); 1789b50d902SRodney W. Grimes else 1799b50d902SRodney W. Grimes (void) fwrite(prefix, sizeof *prefix, 1809b50d902SRodney W. Grimes prefixlen, obuf); 1819b50d902SRodney W. Grimes (void) fwrite(line, sizeof *line, length, obuf); 1829b50d902SRodney W. Grimes if (ferror(obuf)) 1839b50d902SRodney W. Grimes return -1; 1849b50d902SRodney W. Grimes } 1859b50d902SRodney W. Grimes } 1869b50d902SRodney W. Grimes /* 1879b50d902SRodney W. Grimes * Copy out message body 1889b50d902SRodney W. Grimes */ 1899b50d902SRodney W. Grimes if (doign == ignoreall) 1909b50d902SRodney W. Grimes count--; /* skip final blank line */ 1919b50d902SRodney W. Grimes if (prefix != NOSTR) 1929b50d902SRodney W. Grimes while (count > 0) { 1939b50d902SRodney W. Grimes if (fgets(line, LINESIZE, ibuf) == NULL) { 1949b50d902SRodney W. Grimes c = 0; 1959b50d902SRodney W. Grimes break; 1969b50d902SRodney W. Grimes } 1979b50d902SRodney W. Grimes count -= c = strlen(line); 1989b50d902SRodney W. Grimes /* 1999b50d902SRodney W. Grimes * Strip trailing whitespace from prefix 2009b50d902SRodney W. Grimes * if line is blank. 2019b50d902SRodney W. Grimes */ 2029b50d902SRodney W. Grimes if (c > 1) 2039b50d902SRodney W. Grimes fputs(prefix, obuf); 2049b50d902SRodney W. Grimes else 2059b50d902SRodney W. Grimes (void) fwrite(prefix, sizeof *prefix, 2069b50d902SRodney W. Grimes prefixlen, obuf); 2079b50d902SRodney W. Grimes (void) fwrite(line, sizeof *line, c, obuf); 2089b50d902SRodney W. Grimes if (ferror(obuf)) 2099b50d902SRodney W. Grimes return -1; 2109b50d902SRodney W. Grimes } 2119b50d902SRodney W. Grimes else 2129b50d902SRodney W. Grimes while (count > 0) { 2139b50d902SRodney W. Grimes c = count < LINESIZE ? count : LINESIZE; 2149b50d902SRodney W. Grimes if ((c = fread(line, sizeof *line, c, ibuf)) <= 0) 2159b50d902SRodney W. Grimes break; 2169b50d902SRodney W. Grimes count -= c; 2179b50d902SRodney W. Grimes if (fwrite(line, sizeof *line, c, obuf) != c) 2189b50d902SRodney W. Grimes return -1; 2199b50d902SRodney W. Grimes } 2209b50d902SRodney W. Grimes if (doign == ignoreall && c > 0 && line[c - 1] != '\n') 2219b50d902SRodney W. Grimes /* no final blank line */ 2229b50d902SRodney W. Grimes if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF) 2239b50d902SRodney W. Grimes return -1; 2249b50d902SRodney W. Grimes return 0; 2259b50d902SRodney W. Grimes } 2269b50d902SRodney W. Grimes 2279b50d902SRodney W. Grimes /* 2289b50d902SRodney W. Grimes * Output a reasonable looking status field. 2299b50d902SRodney W. Grimes */ 2309b50d902SRodney W. Grimes void 2319b50d902SRodney W. Grimes statusput(mp, obuf, prefix) 2329b50d902SRodney W. Grimes register struct message *mp; 2339b50d902SRodney W. Grimes FILE *obuf; 2349b50d902SRodney W. Grimes char *prefix; 2359b50d902SRodney W. Grimes { 2369b50d902SRodney W. Grimes char statout[3]; 2379b50d902SRodney W. Grimes register char *cp = statout; 2389b50d902SRodney W. Grimes 2399b50d902SRodney W. Grimes if (mp->m_flag & MREAD) 2409b50d902SRodney W. Grimes *cp++ = 'R'; 2419b50d902SRodney W. Grimes if ((mp->m_flag & MNEW) == 0) 2429b50d902SRodney W. Grimes *cp++ = 'O'; 2439b50d902SRodney W. Grimes *cp = 0; 2449b50d902SRodney W. Grimes if (statout[0]) 2459b50d902SRodney W. Grimes fprintf(obuf, "%sStatus: %s\n", 2469b50d902SRodney W. Grimes prefix == NOSTR ? "" : prefix, statout); 2479b50d902SRodney W. Grimes } 2489b50d902SRodney W. Grimes 2499b50d902SRodney W. Grimes /* 2509b50d902SRodney W. Grimes * Interface between the argument list and the mail1 routine 2519b50d902SRodney W. Grimes * which does all the dirty work. 2529b50d902SRodney W. Grimes */ 2539b50d902SRodney W. Grimes int 25499bd6601SJoerg Wunsch mail(to, cc, bcc, smopts, subject, replyto) 2559b50d902SRodney W. Grimes struct name *to, *cc, *bcc, *smopts; 25699bd6601SJoerg Wunsch char *subject, *replyto; 2579b50d902SRodney W. Grimes { 2589b50d902SRodney W. Grimes struct header head; 2599b50d902SRodney W. Grimes 2609b50d902SRodney W. Grimes head.h_to = to; 2619b50d902SRodney W. Grimes head.h_subject = subject; 2629b50d902SRodney W. Grimes head.h_cc = cc; 2639b50d902SRodney W. Grimes head.h_bcc = bcc; 2649b50d902SRodney W. Grimes head.h_smopts = smopts; 26599bd6601SJoerg Wunsch head.h_replyto = replyto; 26699bd6601SJoerg Wunsch head.h_inreplyto = NOSTR; 2679b50d902SRodney W. Grimes mail1(&head, 0); 2689b50d902SRodney W. Grimes return(0); 2699b50d902SRodney W. Grimes } 2709b50d902SRodney W. Grimes 2719b50d902SRodney W. Grimes 2729b50d902SRodney W. Grimes /* 2739b50d902SRodney W. Grimes * Send mail to a bunch of user names. The interface is through 2749b50d902SRodney W. Grimes * the mail routine below. 2759b50d902SRodney W. Grimes */ 2769b50d902SRodney W. Grimes int 2779b50d902SRodney W. Grimes sendmail(str) 2789b50d902SRodney W. Grimes char *str; 2799b50d902SRodney W. Grimes { 2809b50d902SRodney W. Grimes struct header head; 2819b50d902SRodney W. Grimes 2829b50d902SRodney W. Grimes head.h_to = extract(str, GTO); 2839b50d902SRodney W. Grimes head.h_subject = NOSTR; 2849b50d902SRodney W. Grimes head.h_cc = NIL; 2859b50d902SRodney W. Grimes head.h_bcc = NIL; 2869b50d902SRodney W. Grimes head.h_smopts = NIL; 28799bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 28899bd6601SJoerg Wunsch head.h_replyto = NOSTR; 28999bd6601SJoerg Wunsch head.h_inreplyto = NOSTR; 2909b50d902SRodney W. Grimes mail1(&head, 0); 2919b50d902SRodney W. Grimes return(0); 2929b50d902SRodney W. Grimes } 2939b50d902SRodney W. Grimes 2949b50d902SRodney W. Grimes /* 2959b50d902SRodney W. Grimes * Mail a message on standard input to the people indicated 2969b50d902SRodney W. Grimes * in the passed header. (Internal interface). 2979b50d902SRodney W. Grimes */ 2989b50d902SRodney W. Grimes void 2999b50d902SRodney W. Grimes mail1(hp, printheaders) 3009b50d902SRodney W. Grimes struct header *hp; 3019b50d902SRodney W. Grimes int printheaders; 3029b50d902SRodney W. Grimes { 3039b50d902SRodney W. Grimes char *cp; 3049b50d902SRodney W. Grimes int pid; 3059b50d902SRodney W. Grimes char **namelist; 3069b50d902SRodney W. Grimes struct name *to; 3079b50d902SRodney W. Grimes FILE *mtf; 3089b50d902SRodney W. Grimes 3099b50d902SRodney W. Grimes /* 3109b50d902SRodney W. Grimes * Collect user's mail from standard input. 3119b50d902SRodney W. Grimes * Get the result as mtf. 3129b50d902SRodney W. Grimes */ 3139b50d902SRodney W. Grimes if ((mtf = collect(hp, printheaders)) == NULL) 3149b50d902SRodney W. Grimes return; 3159b50d902SRodney W. Grimes if (value("interactive") != NOSTR) 3169b50d902SRodney W. Grimes if (value("askcc") != NOSTR) 3179b50d902SRodney W. Grimes grabh(hp, GCC); 3189b50d902SRodney W. Grimes else { 3199b50d902SRodney W. Grimes printf("EOT\n"); 3209b50d902SRodney W. Grimes (void) fflush(stdout); 3219b50d902SRodney W. Grimes } 3229b50d902SRodney W. Grimes if (fsize(mtf) == 0) 3239b50d902SRodney W. Grimes if (hp->h_subject == NOSTR) 3249b50d902SRodney W. Grimes printf("No message, no subject; hope that's ok\n"); 3259b50d902SRodney W. Grimes else 3269b50d902SRodney W. Grimes printf("Null message body; hope that's ok\n"); 3279b50d902SRodney W. Grimes /* 3289b50d902SRodney W. Grimes * Now, take the user names from the combined 3299b50d902SRodney W. Grimes * to and cc lists and do all the alias 3309b50d902SRodney W. Grimes * processing. 3319b50d902SRodney W. Grimes */ 3329b50d902SRodney W. Grimes senderr = 0; 3339b50d902SRodney W. Grimes to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc))); 3349b50d902SRodney W. Grimes if (to == NIL) { 3359b50d902SRodney W. Grimes printf("No recipients specified\n"); 3369b50d902SRodney W. Grimes senderr++; 3379b50d902SRodney W. Grimes } 3389b50d902SRodney W. Grimes /* 3399b50d902SRodney W. Grimes * Look through the recipient list for names with /'s 3409b50d902SRodney W. Grimes * in them which we write to as files directly. 3419b50d902SRodney W. Grimes */ 3429b50d902SRodney W. Grimes to = outof(to, mtf, hp); 3439b50d902SRodney W. Grimes if (senderr) 3449b50d902SRodney W. Grimes savedeadletter(mtf); 3459b50d902SRodney W. Grimes to = elide(to); 3469b50d902SRodney W. Grimes if (count(to) == 0) 3479b50d902SRodney W. Grimes goto out; 3489b50d902SRodney W. Grimes fixhead(hp, to); 3499b50d902SRodney W. Grimes if ((mtf = infix(hp, mtf)) == NULL) { 3509b50d902SRodney W. Grimes fprintf(stderr, ". . . message lost, sorry.\n"); 3519b50d902SRodney W. Grimes return; 3529b50d902SRodney W. Grimes } 3539b50d902SRodney W. Grimes namelist = unpack(cat(hp->h_smopts, to)); 3549b50d902SRodney W. Grimes if (debug) { 3559b50d902SRodney W. Grimes char **t; 3569b50d902SRodney W. Grimes 3579b50d902SRodney W. Grimes printf("Sendmail arguments:"); 3589b50d902SRodney W. Grimes for (t = namelist; *t != NOSTR; t++) 3599b50d902SRodney W. Grimes printf(" \"%s\"", *t); 3609b50d902SRodney W. Grimes printf("\n"); 3619b50d902SRodney W. Grimes goto out; 3629b50d902SRodney W. Grimes } 3639b50d902SRodney W. Grimes if ((cp = value("record")) != NOSTR) 3649b50d902SRodney W. Grimes (void) savemail(expand(cp), mtf); 3659b50d902SRodney W. Grimes /* 3669b50d902SRodney W. Grimes * Fork, set up the temporary mail file as standard 3679b50d902SRodney W. Grimes * input for "mail", and exec with the user list we generated 3689b50d902SRodney W. Grimes * far above. 3699b50d902SRodney W. Grimes */ 3709b50d902SRodney W. Grimes pid = fork(); 3719b50d902SRodney W. Grimes if (pid == -1) { 3729b50d902SRodney W. Grimes perror("fork"); 3739b50d902SRodney W. Grimes savedeadletter(mtf); 3749b50d902SRodney W. Grimes goto out; 3759b50d902SRodney W. Grimes } 3769b50d902SRodney W. Grimes if (pid == 0) { 3779b50d902SRodney W. Grimes prepare_child(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT)| 3789b50d902SRodney W. Grimes sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU), 3799b50d902SRodney W. Grimes fileno(mtf), -1); 3809b50d902SRodney W. Grimes if ((cp = value("sendmail")) != NOSTR) 3819b50d902SRodney W. Grimes cp = expand(cp); 3829b50d902SRodney W. Grimes else 3839b50d902SRodney W. Grimes cp = _PATH_SENDMAIL; 3849b50d902SRodney W. Grimes execv(cp, namelist); 3859b50d902SRodney W. Grimes perror(cp); 3869b50d902SRodney W. Grimes _exit(1); 3879b50d902SRodney W. Grimes } 3889b50d902SRodney W. Grimes if (value("verbose") != NOSTR) 3899b50d902SRodney W. Grimes (void) wait_child(pid); 3909b50d902SRodney W. Grimes else 3919b50d902SRodney W. Grimes free_child(pid); 3929b50d902SRodney W. Grimes out: 3939b50d902SRodney W. Grimes (void) Fclose(mtf); 3949b50d902SRodney W. Grimes } 3959b50d902SRodney W. Grimes 3969b50d902SRodney W. Grimes /* 3979b50d902SRodney W. Grimes * Fix the header by glopping all of the expanded names from 3989b50d902SRodney W. Grimes * the distribution list into the appropriate fields. 3999b50d902SRodney W. Grimes */ 4009b50d902SRodney W. Grimes void 4019b50d902SRodney W. Grimes fixhead(hp, tolist) 4029b50d902SRodney W. Grimes struct header *hp; 4039b50d902SRodney W. Grimes struct name *tolist; 4049b50d902SRodney W. Grimes { 4059b50d902SRodney W. Grimes register struct name *np; 4069b50d902SRodney W. Grimes 4079b50d902SRodney W. Grimes hp->h_to = NIL; 4089b50d902SRodney W. Grimes hp->h_cc = NIL; 4099b50d902SRodney W. Grimes hp->h_bcc = NIL; 4109b50d902SRodney W. Grimes for (np = tolist; np != NIL; np = np->n_flink) 4119b50d902SRodney W. Grimes if ((np->n_type & GMASK) == GTO) 4129b50d902SRodney W. Grimes hp->h_to = 4139b50d902SRodney W. Grimes cat(hp->h_to, nalloc(np->n_name, np->n_type)); 4149b50d902SRodney W. Grimes else if ((np->n_type & GMASK) == GCC) 4159b50d902SRodney W. Grimes hp->h_cc = 4169b50d902SRodney W. Grimes cat(hp->h_cc, nalloc(np->n_name, np->n_type)); 4179b50d902SRodney W. Grimes else if ((np->n_type & GMASK) == GBCC) 4189b50d902SRodney W. Grimes hp->h_bcc = 4199b50d902SRodney W. Grimes cat(hp->h_bcc, nalloc(np->n_name, np->n_type)); 4209b50d902SRodney W. Grimes } 4219b50d902SRodney W. Grimes 4229b50d902SRodney W. Grimes /* 4239b50d902SRodney W. Grimes * Prepend a header in front of the collected stuff 4249b50d902SRodney W. Grimes * and return the new file. 4259b50d902SRodney W. Grimes */ 4269b50d902SRodney W. Grimes FILE * 4279b50d902SRodney W. Grimes infix(hp, fi) 4289b50d902SRodney W. Grimes struct header *hp; 4299b50d902SRodney W. Grimes FILE *fi; 4309b50d902SRodney W. Grimes { 4319b50d902SRodney W. Grimes extern char tempMail[]; 4329b50d902SRodney W. Grimes register FILE *nfo, *nfi; 4339b50d902SRodney W. Grimes register int c; 4349b50d902SRodney W. Grimes 4359b50d902SRodney W. Grimes if ((nfo = Fopen(tempMail, "w")) == NULL) { 4369b50d902SRodney W. Grimes perror(tempMail); 4379b50d902SRodney W. Grimes return(fi); 4389b50d902SRodney W. Grimes } 4399b50d902SRodney W. Grimes if ((nfi = Fopen(tempMail, "r")) == NULL) { 4409b50d902SRodney W. Grimes perror(tempMail); 4419b50d902SRodney W. Grimes (void) Fclose(nfo); 4429b50d902SRodney W. Grimes return(fi); 4439b50d902SRodney W. Grimes } 4449b50d902SRodney W. Grimes (void) rm(tempMail); 44599bd6601SJoerg Wunsch (void) puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO|GNL|GCOMMA); 4469b50d902SRodney W. Grimes c = getc(fi); 4479b50d902SRodney W. Grimes while (c != EOF) { 4489b50d902SRodney W. Grimes (void) putc(c, nfo); 4499b50d902SRodney W. Grimes c = getc(fi); 4509b50d902SRodney W. Grimes } 4519b50d902SRodney W. Grimes if (ferror(fi)) { 4529b50d902SRodney W. Grimes perror("read"); 4539b50d902SRodney W. Grimes rewind(fi); 4549b50d902SRodney W. Grimes return(fi); 4559b50d902SRodney W. Grimes } 4569b50d902SRodney W. Grimes (void) fflush(nfo); 4579b50d902SRodney W. Grimes if (ferror(nfo)) { 4589b50d902SRodney W. Grimes perror(tempMail); 4599b50d902SRodney W. Grimes (void) Fclose(nfo); 4609b50d902SRodney W. Grimes (void) Fclose(nfi); 4619b50d902SRodney W. Grimes rewind(fi); 4629b50d902SRodney W. Grimes return(fi); 4639b50d902SRodney W. Grimes } 4649b50d902SRodney W. Grimes (void) Fclose(nfo); 4659b50d902SRodney W. Grimes (void) Fclose(fi); 4669b50d902SRodney W. Grimes rewind(nfi); 4679b50d902SRodney W. Grimes return(nfi); 4689b50d902SRodney W. Grimes } 4699b50d902SRodney W. Grimes 4709b50d902SRodney W. Grimes /* 4719b50d902SRodney W. Grimes * Dump the to, subject, cc header on the 4729b50d902SRodney W. Grimes * passed file buffer. 4739b50d902SRodney W. Grimes */ 4749b50d902SRodney W. Grimes int 4759b50d902SRodney W. Grimes puthead(hp, fo, w) 4769b50d902SRodney W. Grimes struct header *hp; 4779b50d902SRodney W. Grimes FILE *fo; 4789b50d902SRodney W. Grimes int w; 4799b50d902SRodney W. Grimes { 4809b50d902SRodney W. Grimes register int gotcha; 4819b50d902SRodney W. Grimes 4829b50d902SRodney W. Grimes gotcha = 0; 4839b50d902SRodney W. Grimes if (hp->h_to != NIL && w & GTO) 4849b50d902SRodney W. Grimes fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++; 4859b50d902SRodney W. Grimes if (hp->h_subject != NOSTR && w & GSUBJECT) 4869b50d902SRodney W. Grimes fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 4879b50d902SRodney W. Grimes if (hp->h_cc != NIL && w & GCC) 4889b50d902SRodney W. Grimes fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++; 4899b50d902SRodney W. Grimes if (hp->h_bcc != NIL && w & GBCC) 4909b50d902SRodney W. Grimes fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++; 49199bd6601SJoerg Wunsch if (hp->h_replyto != NOSTR && w && GREPLYTO) 49299bd6601SJoerg Wunsch fprintf(fo, "Reply-To: %s\n", hp->h_replyto), gotcha++; 49399bd6601SJoerg Wunsch if (hp->h_inreplyto != NOSTR && w && GINREPLYTO) 49499bd6601SJoerg Wunsch fprintf(fo, "In-Reply-To: <%s>\n", hp->h_inreplyto), gotcha++; 4959b50d902SRodney W. Grimes if (gotcha && w & GNL) 4969b50d902SRodney W. Grimes (void) putc('\n', fo); 4979b50d902SRodney W. Grimes return(0); 4989b50d902SRodney W. Grimes } 4999b50d902SRodney W. Grimes 5009b50d902SRodney W. Grimes /* 5019b50d902SRodney W. Grimes * Format the given header line to not exceed 72 characters. 5029b50d902SRodney W. Grimes */ 5039b50d902SRodney W. Grimes void 5049b50d902SRodney W. Grimes fmt(str, np, fo, comma) 5059b50d902SRodney W. Grimes char *str; 5069b50d902SRodney W. Grimes register struct name *np; 5079b50d902SRodney W. Grimes FILE *fo; 5089b50d902SRodney W. Grimes int comma; 5099b50d902SRodney W. Grimes { 5109b50d902SRodney W. Grimes register col, len; 5119b50d902SRodney W. Grimes 5129b50d902SRodney W. Grimes comma = comma ? 1 : 0; 5139b50d902SRodney W. Grimes col = strlen(str); 5149b50d902SRodney W. Grimes if (col) 5159b50d902SRodney W. Grimes fputs(str, fo); 5169b50d902SRodney W. Grimes for (; np != NIL; np = np->n_flink) { 5179b50d902SRodney W. Grimes if (np->n_flink == NIL) 5189b50d902SRodney W. Grimes comma = 0; 5199b50d902SRodney W. Grimes len = strlen(np->n_name); 5209b50d902SRodney W. Grimes col++; /* for the space */ 5219b50d902SRodney W. Grimes if (col + len + comma > 72 && col > 4) { 5229b50d902SRodney W. Grimes fputs("\n ", fo); 5239b50d902SRodney W. Grimes col = 4; 5249b50d902SRodney W. Grimes } else 5259b50d902SRodney W. Grimes putc(' ', fo); 5269b50d902SRodney W. Grimes fputs(np->n_name, fo); 5279b50d902SRodney W. Grimes if (comma) 5289b50d902SRodney W. Grimes putc(',', fo); 5299b50d902SRodney W. Grimes col += len + comma; 5309b50d902SRodney W. Grimes } 5319b50d902SRodney W. Grimes putc('\n', fo); 5329b50d902SRodney W. Grimes } 5339b50d902SRodney W. Grimes 5349b50d902SRodney W. Grimes /* 5359b50d902SRodney W. Grimes * Save the outgoing mail on the passed file. 5369b50d902SRodney W. Grimes */ 5379b50d902SRodney W. Grimes 5389b50d902SRodney W. Grimes /*ARGSUSED*/ 5399b50d902SRodney W. Grimes int 5409b50d902SRodney W. Grimes savemail(name, fi) 5419b50d902SRodney W. Grimes char name[]; 5429b50d902SRodney W. Grimes register FILE *fi; 5439b50d902SRodney W. Grimes { 5449b50d902SRodney W. Grimes register FILE *fo; 5459b50d902SRodney W. Grimes char buf[BUFSIZ]; 5469b50d902SRodney W. Grimes register i; 5479b50d902SRodney W. Grimes time_t now, time(); 5489b50d902SRodney W. Grimes char *ctime(); 5499b50d902SRodney W. Grimes 5509b50d902SRodney W. Grimes if ((fo = Fopen(name, "a")) == NULL) { 5519b50d902SRodney W. Grimes perror(name); 5529b50d902SRodney W. Grimes return (-1); 5539b50d902SRodney W. Grimes } 5549b50d902SRodney W. Grimes (void) time(&now); 5559b50d902SRodney W. Grimes fprintf(fo, "From %s %s", myname, ctime(&now)); 5569b50d902SRodney W. Grimes while ((i = fread(buf, 1, sizeof buf, fi)) > 0) 5579b50d902SRodney W. Grimes (void) fwrite(buf, 1, i, fo); 5589b50d902SRodney W. Grimes (void) putc('\n', fo); 5599b50d902SRodney W. Grimes (void) fflush(fo); 5609b50d902SRodney W. Grimes if (ferror(fo)) 5619b50d902SRodney W. Grimes perror(name); 5629b50d902SRodney W. Grimes (void) Fclose(fo); 5639b50d902SRodney W. Grimes rewind(fi); 5649b50d902SRodney W. Grimes return (0); 5659b50d902SRodney W. Grimes } 566