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 350c3a8314SMike Heffner #if 0 369b50d902SRodney W. Grimes static char sccsid[] = "@(#)send.c 8.1 (Berkeley) 6/6/93"; 370c3a8314SMike Heffner #endif 380c3a8314SMike Heffner static const char rcsid[] = 390c3a8314SMike Heffner "$FreeBSD$"; 409b50d902SRodney W. Grimes #endif /* not lint */ 419b50d902SRodney W. Grimes 429b50d902SRodney W. Grimes #include "rcv.h" 439b50d902SRodney W. Grimes #include "extern.h" 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes /* 469b50d902SRodney W. Grimes * Mail -- a mail program 479b50d902SRodney W. Grimes * 489b50d902SRodney W. Grimes * Mail to others. 499b50d902SRodney W. Grimes */ 509b50d902SRodney W. Grimes 519b50d902SRodney W. Grimes /* 529b50d902SRodney W. Grimes * Send message described by the passed pointer to the 539b50d902SRodney W. Grimes * passed output buffer. Return -1 on error. 549b50d902SRodney W. Grimes * Adjust the status: field if need be. 559b50d902SRodney W. Grimes * If doign is given, suppress ignored header fields. 569b50d902SRodney W. Grimes * prefix is a string to prepend to each output line. 579b50d902SRodney W. Grimes */ 589b50d902SRodney W. Grimes int 590c3a8314SMike Heffner sendmessage(mp, obuf, doign, prefix) 609b50d902SRodney W. Grimes register struct message *mp; 619b50d902SRodney W. Grimes FILE *obuf; 629b50d902SRodney W. Grimes struct ignoretab *doign; 639b50d902SRodney W. Grimes char *prefix; 649b50d902SRodney W. Grimes { 659b50d902SRodney W. Grimes long count; 669b50d902SRodney W. Grimes register FILE *ibuf; 679b50d902SRodney W. Grimes char line[LINESIZE]; 689b50d902SRodney W. Grimes int ishead, infld, ignoring, dostat, firstline; 699b50d902SRodney W. Grimes register char *cp, *cp2; 709b50d902SRodney W. Grimes register int c; 719b50d902SRodney W. Grimes int length; 729b50d902SRodney W. Grimes int prefixlen; 739b50d902SRodney W. Grimes 749b50d902SRodney W. Grimes /* 759b50d902SRodney W. Grimes * Compute the prefix string, without trailing whitespace 769b50d902SRodney W. Grimes */ 779b50d902SRodney W. Grimes if (prefix != NOSTR) { 789b50d902SRodney W. Grimes cp2 = 0; 799b50d902SRodney W. Grimes for (cp = prefix; *cp; cp++) 809b50d902SRodney W. Grimes if (*cp != ' ' && *cp != '\t') 819b50d902SRodney W. Grimes cp2 = cp; 829b50d902SRodney W. Grimes prefixlen = cp2 == 0 ? 0 : cp2 - prefix + 1; 839b50d902SRodney W. Grimes } 849b50d902SRodney W. Grimes ibuf = setinput(mp); 859b50d902SRodney W. Grimes count = mp->m_size; 869b50d902SRodney W. Grimes ishead = 1; 879b50d902SRodney W. Grimes dostat = doign == 0 || !isign("status", doign); 889b50d902SRodney W. Grimes infld = 0; 899b50d902SRodney W. Grimes firstline = 1; 909b50d902SRodney W. Grimes /* 919b50d902SRodney W. Grimes * Process headers first 929b50d902SRodney W. Grimes */ 939b50d902SRodney W. Grimes while (count > 0 && ishead) { 940c3a8314SMike Heffner if (fgets(line, sizeof(line), ibuf) == NULL) 959b50d902SRodney W. Grimes break; 969b50d902SRodney W. Grimes count -= length = strlen(line); 979b50d902SRodney W. Grimes if (firstline) { 989b50d902SRodney W. Grimes /* 999b50d902SRodney W. Grimes * First line is the From line, so no headers 1009b50d902SRodney W. Grimes * there to worry about 1019b50d902SRodney W. Grimes */ 1029b50d902SRodney W. Grimes firstline = 0; 1039b50d902SRodney W. Grimes ignoring = doign == ignoreall; 1049b50d902SRodney W. Grimes } else if (line[0] == '\n') { 1059b50d902SRodney W. Grimes /* 1069b50d902SRodney W. Grimes * If line is blank, we've reached end of 1079b50d902SRodney W. Grimes * headers, so force out status: field 1089b50d902SRodney W. Grimes * and note that we are no longer in header 1099b50d902SRodney W. Grimes * fields 1109b50d902SRodney W. Grimes */ 1119b50d902SRodney W. Grimes if (dostat) { 1129b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1139b50d902SRodney W. Grimes dostat = 0; 1149b50d902SRodney W. Grimes } 1159b50d902SRodney W. Grimes ishead = 0; 1169b50d902SRodney W. Grimes ignoring = doign == ignoreall; 1179b50d902SRodney W. Grimes } else if (infld && (line[0] == ' ' || line[0] == '\t')) { 1189b50d902SRodney W. Grimes /* 1199b50d902SRodney W. Grimes * If this line is a continuation (via space or tab) 1209b50d902SRodney W. Grimes * of a previous header field, just echo it 1219b50d902SRodney W. Grimes * (unless the field should be ignored). 1229b50d902SRodney W. Grimes * In other words, nothing to do. 1239b50d902SRodney W. Grimes */ 1249b50d902SRodney W. Grimes } else { 1259b50d902SRodney W. Grimes /* 1269b50d902SRodney W. Grimes * Pick up the header field if we have one. 1279b50d902SRodney W. Grimes */ 1289b50d902SRodney W. Grimes for (cp = line; (c = *cp++) && c != ':' && !isspace(c);) 1299b50d902SRodney W. Grimes ; 1309b50d902SRodney W. Grimes cp2 = --cp; 1319b50d902SRodney W. Grimes while (isspace(*cp++)) 1329b50d902SRodney W. Grimes ; 1339b50d902SRodney W. Grimes if (cp[-1] != ':') { 1349b50d902SRodney W. Grimes /* 1359b50d902SRodney W. Grimes * Not a header line, force out status: 1369b50d902SRodney W. Grimes * This happens in uucp style mail where 1379b50d902SRodney W. Grimes * there are no headers at all. 1389b50d902SRodney W. Grimes */ 1399b50d902SRodney W. Grimes if (dostat) { 1409b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1419b50d902SRodney W. Grimes dostat = 0; 1429b50d902SRodney W. Grimes } 1439b50d902SRodney W. Grimes if (doign != ignoreall) 1449b50d902SRodney W. Grimes /* add blank line */ 1459b50d902SRodney W. Grimes (void) putc('\n', obuf); 1469b50d902SRodney W. Grimes ishead = 0; 1479b50d902SRodney W. Grimes ignoring = 0; 1489b50d902SRodney W. Grimes } else { 1499b50d902SRodney W. Grimes /* 1509b50d902SRodney W. Grimes * If it is an ignored field and 1519b50d902SRodney W. Grimes * we care about such things, skip it. 1529b50d902SRodney W. Grimes */ 1539b50d902SRodney W. Grimes *cp2 = 0; /* temporarily null terminate */ 1549b50d902SRodney W. Grimes if (doign && isign(line, doign)) 1559b50d902SRodney W. Grimes ignoring = 1; 1569b50d902SRodney W. Grimes else if ((line[0] == 's' || line[0] == 'S') && 1579b50d902SRodney W. Grimes strcasecmp(line, "status") == 0) { 1589b50d902SRodney W. Grimes /* 1599b50d902SRodney W. Grimes * If the field is "status," go compute 1609b50d902SRodney W. Grimes * and print the real Status: field 1619b50d902SRodney W. Grimes */ 1629b50d902SRodney W. Grimes if (dostat) { 1639b50d902SRodney W. Grimes statusput(mp, obuf, prefix); 1649b50d902SRodney W. Grimes dostat = 0; 1659b50d902SRodney W. Grimes } 1669b50d902SRodney W. Grimes ignoring = 1; 1679b50d902SRodney W. Grimes } else { 1689b50d902SRodney W. Grimes ignoring = 0; 1699b50d902SRodney W. Grimes *cp2 = c; /* restore */ 1709b50d902SRodney W. Grimes } 1719b50d902SRodney W. Grimes infld = 1; 1729b50d902SRodney W. Grimes } 1739b50d902SRodney W. Grimes } 1749b50d902SRodney W. Grimes if (!ignoring) { 1759b50d902SRodney W. Grimes /* 1769b50d902SRodney W. Grimes * Strip trailing whitespace from prefix 1779b50d902SRodney W. Grimes * if line is blank. 1789b50d902SRodney W. Grimes */ 1790c3a8314SMike Heffner if (prefix != NOSTR) { 1809b50d902SRodney W. Grimes if (length > 1) 1819b50d902SRodney W. Grimes fputs(prefix, obuf); 1829b50d902SRodney W. Grimes else 1839b50d902SRodney W. Grimes (void) fwrite(prefix, sizeof *prefix, 1849b50d902SRodney W. Grimes prefixlen, obuf); 1850c3a8314SMike Heffner } 1869b50d902SRodney W. Grimes (void) fwrite(line, sizeof *line, length, obuf); 1879b50d902SRodney W. Grimes if (ferror(obuf)) 1889b50d902SRodney W. Grimes return -1; 1899b50d902SRodney W. Grimes } 1909b50d902SRodney W. Grimes } 1919b50d902SRodney W. Grimes /* 1929b50d902SRodney W. Grimes * Copy out message body 1939b50d902SRodney W. Grimes */ 1949b50d902SRodney W. Grimes if (doign == ignoreall) 1959b50d902SRodney W. Grimes count--; /* skip final blank line */ 1969b50d902SRodney W. Grimes if (prefix != NOSTR) 1979b50d902SRodney W. Grimes while (count > 0) { 1980c3a8314SMike Heffner if (fgets(line, sizeof(line), ibuf) == NULL) { 1999b50d902SRodney W. Grimes c = 0; 2009b50d902SRodney W. Grimes break; 2019b50d902SRodney W. Grimes } 2029b50d902SRodney W. Grimes count -= c = strlen(line); 2039b50d902SRodney W. Grimes /* 2049b50d902SRodney W. Grimes * Strip trailing whitespace from prefix 2059b50d902SRodney W. Grimes * if line is blank. 2069b50d902SRodney W. Grimes */ 2079b50d902SRodney W. Grimes if (c > 1) 2089b50d902SRodney W. Grimes fputs(prefix, obuf); 2099b50d902SRodney W. Grimes else 2109b50d902SRodney W. Grimes (void) fwrite(prefix, sizeof *prefix, 2119b50d902SRodney W. Grimes prefixlen, obuf); 2129b50d902SRodney W. Grimes (void) fwrite(line, sizeof *line, c, obuf); 2139b50d902SRodney W. Grimes if (ferror(obuf)) 2149b50d902SRodney W. Grimes return -1; 2159b50d902SRodney W. Grimes } 2169b50d902SRodney W. Grimes else 2179b50d902SRodney W. Grimes while (count > 0) { 2189b50d902SRodney W. Grimes c = count < LINESIZE ? count : LINESIZE; 2199b50d902SRodney W. Grimes if ((c = fread(line, sizeof *line, c, ibuf)) <= 0) 2209b50d902SRodney W. Grimes break; 2219b50d902SRodney W. Grimes count -= c; 2229b50d902SRodney W. Grimes if (fwrite(line, sizeof *line, c, obuf) != c) 2239b50d902SRodney W. Grimes return -1; 2249b50d902SRodney W. Grimes } 2259b50d902SRodney W. Grimes if (doign == ignoreall && c > 0 && line[c - 1] != '\n') 2269b50d902SRodney W. Grimes /* no final blank line */ 2279b50d902SRodney W. Grimes if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF) 2289b50d902SRodney W. Grimes return -1; 2299b50d902SRodney W. Grimes return 0; 2309b50d902SRodney W. Grimes } 2319b50d902SRodney W. Grimes 2329b50d902SRodney W. Grimes /* 2339b50d902SRodney W. Grimes * Output a reasonable looking status field. 2349b50d902SRodney W. Grimes */ 2359b50d902SRodney W. Grimes void 2369b50d902SRodney W. Grimes statusput(mp, obuf, prefix) 2379b50d902SRodney W. Grimes register struct message *mp; 2389b50d902SRodney W. Grimes FILE *obuf; 2399b50d902SRodney W. Grimes char *prefix; 2409b50d902SRodney W. Grimes { 2419b50d902SRodney W. Grimes char statout[3]; 2429b50d902SRodney W. Grimes register char *cp = statout; 2439b50d902SRodney W. Grimes 2449b50d902SRodney W. Grimes if (mp->m_flag & MREAD) 2459b50d902SRodney W. Grimes *cp++ = 'R'; 2469b50d902SRodney W. Grimes if ((mp->m_flag & MNEW) == 0) 2479b50d902SRodney W. Grimes *cp++ = 'O'; 2489b50d902SRodney W. Grimes *cp = 0; 2499b50d902SRodney W. Grimes if (statout[0]) 2509b50d902SRodney W. Grimes fprintf(obuf, "%sStatus: %s\n", 2519b50d902SRodney W. Grimes prefix == NOSTR ? "" : prefix, statout); 2529b50d902SRodney W. Grimes } 2539b50d902SRodney W. Grimes 2549b50d902SRodney W. Grimes /* 2559b50d902SRodney W. Grimes * Interface between the argument list and the mail1 routine 2569b50d902SRodney W. Grimes * which does all the dirty work. 2579b50d902SRodney W. Grimes */ 2589b50d902SRodney W. Grimes int 25999bd6601SJoerg Wunsch mail(to, cc, bcc, smopts, subject, replyto) 2609b50d902SRodney W. Grimes struct name *to, *cc, *bcc, *smopts; 26199bd6601SJoerg Wunsch char *subject, *replyto; 2629b50d902SRodney W. Grimes { 2639b50d902SRodney W. Grimes struct header head; 2649b50d902SRodney W. Grimes 2659b50d902SRodney W. Grimes head.h_to = to; 2669b50d902SRodney W. Grimes head.h_subject = subject; 2679b50d902SRodney W. Grimes head.h_cc = cc; 2689b50d902SRodney W. Grimes head.h_bcc = bcc; 2699b50d902SRodney W. Grimes head.h_smopts = smopts; 27099bd6601SJoerg Wunsch head.h_replyto = replyto; 27199bd6601SJoerg Wunsch head.h_inreplyto = NOSTR; 2729b50d902SRodney W. Grimes mail1(&head, 0); 2739b50d902SRodney W. Grimes return(0); 2749b50d902SRodney W. Grimes } 2759b50d902SRodney W. Grimes 2769b50d902SRodney W. Grimes 2779b50d902SRodney W. Grimes /* 2789b50d902SRodney W. Grimes * Send mail to a bunch of user names. The interface is through 2799b50d902SRodney W. Grimes * the mail routine below. 2809b50d902SRodney W. Grimes */ 2819b50d902SRodney W. Grimes int 2829b50d902SRodney W. Grimes sendmail(str) 2839b50d902SRodney W. Grimes char *str; 2849b50d902SRodney W. Grimes { 2859b50d902SRodney W. Grimes struct header head; 2869b50d902SRodney W. Grimes 2879b50d902SRodney W. Grimes head.h_to = extract(str, GTO); 2889b50d902SRodney W. Grimes head.h_subject = NOSTR; 2899b50d902SRodney W. Grimes head.h_cc = NIL; 2909b50d902SRodney W. Grimes head.h_bcc = NIL; 2919b50d902SRodney W. Grimes head.h_smopts = NIL; 29299bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 29399bd6601SJoerg Wunsch head.h_replyto = NOSTR; 29499bd6601SJoerg Wunsch head.h_inreplyto = NOSTR; 2959b50d902SRodney W. Grimes mail1(&head, 0); 2969b50d902SRodney W. Grimes return(0); 2979b50d902SRodney W. Grimes } 2989b50d902SRodney W. Grimes 2999b50d902SRodney W. Grimes /* 3009b50d902SRodney W. Grimes * Mail a message on standard input to the people indicated 3019b50d902SRodney W. Grimes * in the passed header. (Internal interface). 3029b50d902SRodney W. Grimes */ 3039b50d902SRodney W. Grimes void 3049b50d902SRodney W. Grimes mail1(hp, printheaders) 3059b50d902SRodney W. Grimes struct header *hp; 3069b50d902SRodney W. Grimes int printheaders; 3079b50d902SRodney W. Grimes { 3089b50d902SRodney W. Grimes char *cp; 3099b50d902SRodney W. Grimes int pid; 3109b50d902SRodney W. Grimes char **namelist; 3119b50d902SRodney W. Grimes struct name *to; 3129b50d902SRodney W. Grimes FILE *mtf; 3139b50d902SRodney W. Grimes 3149b50d902SRodney W. Grimes /* 3159b50d902SRodney W. Grimes * Collect user's mail from standard input. 3169b50d902SRodney W. Grimes * Get the result as mtf. 3179b50d902SRodney W. Grimes */ 3189b50d902SRodney W. Grimes if ((mtf = collect(hp, printheaders)) == NULL) 3199b50d902SRodney W. Grimes return; 3200c3a8314SMike Heffner if (value("interactive") != NOSTR) { 3219b50d902SRodney W. Grimes if (value("askcc") != NOSTR) 3229b50d902SRodney W. Grimes grabh(hp, GCC); 3239b50d902SRodney W. Grimes else { 3249b50d902SRodney W. Grimes printf("EOT\n"); 3259b50d902SRodney W. Grimes (void) fflush(stdout); 3269b50d902SRodney W. Grimes } 3270c3a8314SMike Heffner } 3280c3a8314SMike Heffner if (fsize(mtf) == 0) { 3299b50d902SRodney W. Grimes if (hp->h_subject == NOSTR) 3309b50d902SRodney W. Grimes printf("No message, no subject; hope that's ok\n"); 3319b50d902SRodney W. Grimes else 3329b50d902SRodney W. Grimes printf("Null message body; hope that's ok\n"); 3330c3a8314SMike Heffner } 3349b50d902SRodney W. Grimes /* 3359b50d902SRodney W. Grimes * Now, take the user names from the combined 3369b50d902SRodney W. Grimes * to and cc lists and do all the alias 3379b50d902SRodney W. Grimes * processing. 3389b50d902SRodney W. Grimes */ 3399b50d902SRodney W. Grimes senderr = 0; 3409b50d902SRodney W. Grimes to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc))); 3419b50d902SRodney W. Grimes if (to == NIL) { 3429b50d902SRodney W. Grimes printf("No recipients specified\n"); 3439b50d902SRodney W. Grimes senderr++; 3449b50d902SRodney W. Grimes } 3459b50d902SRodney W. Grimes /* 3469b50d902SRodney W. Grimes * Look through the recipient list for names with /'s 3479b50d902SRodney W. Grimes * in them which we write to as files directly. 3489b50d902SRodney W. Grimes */ 3499b50d902SRodney W. Grimes to = outof(to, mtf, hp); 3509b50d902SRodney W. Grimes if (senderr) 3519b50d902SRodney W. Grimes savedeadletter(mtf); 3529b50d902SRodney W. Grimes to = elide(to); 3539b50d902SRodney W. Grimes if (count(to) == 0) 3549b50d902SRodney W. Grimes goto out; 3559b50d902SRodney W. Grimes fixhead(hp, to); 3569b50d902SRodney W. Grimes if ((mtf = infix(hp, mtf)) == NULL) { 3579b50d902SRodney W. Grimes fprintf(stderr, ". . . message lost, sorry.\n"); 3589b50d902SRodney W. Grimes return; 3599b50d902SRodney W. Grimes } 3609b50d902SRodney W. Grimes namelist = unpack(cat(hp->h_smopts, to)); 3619b50d902SRodney W. Grimes if (debug) { 3629b50d902SRodney W. Grimes char **t; 3639b50d902SRodney W. Grimes 3649b50d902SRodney W. Grimes printf("Sendmail arguments:"); 3659b50d902SRodney W. Grimes for (t = namelist; *t != NOSTR; t++) 3669b50d902SRodney W. Grimes printf(" \"%s\"", *t); 3679b50d902SRodney W. Grimes printf("\n"); 3689b50d902SRodney W. Grimes goto out; 3699b50d902SRodney W. Grimes } 3709b50d902SRodney W. Grimes if ((cp = value("record")) != NOSTR) 3719b50d902SRodney W. Grimes (void) savemail(expand(cp), mtf); 3729b50d902SRodney W. Grimes /* 3739b50d902SRodney W. Grimes * Fork, set up the temporary mail file as standard 3749b50d902SRodney W. Grimes * input for "mail", and exec with the user list we generated 3759b50d902SRodney W. Grimes * far above. 3769b50d902SRodney W. Grimes */ 3779b50d902SRodney W. Grimes pid = fork(); 3789b50d902SRodney W. Grimes if (pid == -1) { 3790c3a8314SMike Heffner warn("fork"); 3809b50d902SRodney W. Grimes savedeadletter(mtf); 3819b50d902SRodney W. Grimes goto out; 3829b50d902SRodney W. Grimes } 3839b50d902SRodney W. Grimes if (pid == 0) { 3849b50d902SRodney W. Grimes prepare_child(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT)| 3859b50d902SRodney W. Grimes sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU), 3869b50d902SRodney W. Grimes fileno(mtf), -1); 3879b50d902SRodney W. Grimes if ((cp = value("sendmail")) != NOSTR) 3889b50d902SRodney W. Grimes cp = expand(cp); 3899b50d902SRodney W. Grimes else 3909b50d902SRodney W. Grimes cp = _PATH_SENDMAIL; 3919b50d902SRodney W. Grimes execv(cp, namelist); 3920c3a8314SMike Heffner warn("%s", cp); 3939b50d902SRodney W. Grimes _exit(1); 3949b50d902SRodney W. Grimes } 3959b50d902SRodney W. Grimes if (value("verbose") != NOSTR) 3969b50d902SRodney W. Grimes (void) wait_child(pid); 3979b50d902SRodney W. Grimes else 3989b50d902SRodney W. Grimes free_child(pid); 3999b50d902SRodney W. Grimes out: 4009b50d902SRodney W. Grimes (void) Fclose(mtf); 4019b50d902SRodney W. Grimes } 4029b50d902SRodney W. Grimes 4039b50d902SRodney W. Grimes /* 4049b50d902SRodney W. Grimes * Fix the header by glopping all of the expanded names from 4059b50d902SRodney W. Grimes * the distribution list into the appropriate fields. 4069b50d902SRodney W. Grimes */ 4079b50d902SRodney W. Grimes void 4089b50d902SRodney W. Grimes fixhead(hp, tolist) 4099b50d902SRodney W. Grimes struct header *hp; 4109b50d902SRodney W. Grimes struct name *tolist; 4119b50d902SRodney W. Grimes { 4129b50d902SRodney W. Grimes register struct name *np; 4139b50d902SRodney W. Grimes 4149b50d902SRodney W. Grimes hp->h_to = NIL; 4159b50d902SRodney W. Grimes hp->h_cc = NIL; 4169b50d902SRodney W. Grimes hp->h_bcc = NIL; 4179b50d902SRodney W. Grimes for (np = tolist; np != NIL; np = np->n_flink) 4189b50d902SRodney W. Grimes if ((np->n_type & GMASK) == GTO) 4199b50d902SRodney W. Grimes hp->h_to = 4209b50d902SRodney W. Grimes cat(hp->h_to, nalloc(np->n_name, np->n_type)); 4219b50d902SRodney W. Grimes else if ((np->n_type & GMASK) == GCC) 4229b50d902SRodney W. Grimes hp->h_cc = 4239b50d902SRodney W. Grimes cat(hp->h_cc, nalloc(np->n_name, np->n_type)); 4249b50d902SRodney W. Grimes else if ((np->n_type & GMASK) == GBCC) 4259b50d902SRodney W. Grimes hp->h_bcc = 4269b50d902SRodney W. Grimes cat(hp->h_bcc, nalloc(np->n_name, np->n_type)); 4279b50d902SRodney W. Grimes } 4289b50d902SRodney W. Grimes 4299b50d902SRodney W. Grimes /* 4309b50d902SRodney W. Grimes * Prepend a header in front of the collected stuff 4319b50d902SRodney W. Grimes * and return the new file. 4329b50d902SRodney W. Grimes */ 4339b50d902SRodney W. Grimes FILE * 4349b50d902SRodney W. Grimes infix(hp, fi) 4359b50d902SRodney W. Grimes struct header *hp; 4369b50d902SRodney W. Grimes FILE *fi; 4379b50d902SRodney W. Grimes { 4389b50d902SRodney W. Grimes register FILE *nfo, *nfi; 4399b50d902SRodney W. Grimes register int c; 4400c3a8314SMike Heffner int fd; 4410c3a8314SMike Heffner char tempname[PATHSIZE]; 4429b50d902SRodney W. Grimes 4430c3a8314SMike Heffner snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir); 4440c3a8314SMike Heffner if ((fd = mkstemp(tempname)) == -1 || 4450c3a8314SMike Heffner (nfo = Fdopen(fd, "w")) == NULL) { 4460c3a8314SMike Heffner warn("%s", tempname); 4479b50d902SRodney W. Grimes return(fi); 4489b50d902SRodney W. Grimes } 4490c3a8314SMike Heffner if ((nfi = Fopen(tempname, "r")) == NULL) { 4500c3a8314SMike Heffner warn("%s", tempname); 4519b50d902SRodney W. Grimes (void) Fclose(nfo); 4520c3a8314SMike Heffner (void) rm(tempname); 4539b50d902SRodney W. Grimes return(fi); 4549b50d902SRodney W. Grimes } 4550c3a8314SMike Heffner (void) rm(tempname); 45657392071SJoerg Wunsch (void) puthead(hp, nfo, 45757392071SJoerg Wunsch GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO|GNL|GCOMMA); 4589b50d902SRodney W. Grimes c = getc(fi); 4599b50d902SRodney W. Grimes while (c != EOF) { 4609b50d902SRodney W. Grimes (void) putc(c, nfo); 4619b50d902SRodney W. Grimes c = getc(fi); 4629b50d902SRodney W. Grimes } 4639b50d902SRodney W. Grimes if (ferror(fi)) { 4640c3a8314SMike Heffner warnx("read"); 4659b50d902SRodney W. Grimes rewind(fi); 4669b50d902SRodney W. Grimes return(fi); 4679b50d902SRodney W. Grimes } 4689b50d902SRodney W. Grimes (void) fflush(nfo); 4699b50d902SRodney W. Grimes if (ferror(nfo)) { 4700c3a8314SMike Heffner warn("%s", tempname); 4719b50d902SRodney W. Grimes (void) Fclose(nfo); 4729b50d902SRodney W. Grimes (void) Fclose(nfi); 4739b50d902SRodney W. Grimes rewind(fi); 4749b50d902SRodney W. Grimes return(fi); 4759b50d902SRodney W. Grimes } 4769b50d902SRodney W. Grimes (void) Fclose(nfo); 4779b50d902SRodney W. Grimes (void) Fclose(fi); 4789b50d902SRodney W. Grimes rewind(nfi); 4799b50d902SRodney W. Grimes return(nfi); 4809b50d902SRodney W. Grimes } 4819b50d902SRodney W. Grimes 4829b50d902SRodney W. Grimes /* 4839b50d902SRodney W. Grimes * Dump the to, subject, cc header on the 4849b50d902SRodney W. Grimes * passed file buffer. 4859b50d902SRodney W. Grimes */ 4869b50d902SRodney W. Grimes int 4879b50d902SRodney W. Grimes puthead(hp, fo, w) 4889b50d902SRodney W. Grimes struct header *hp; 4899b50d902SRodney W. Grimes FILE *fo; 4909b50d902SRodney W. Grimes int w; 4919b50d902SRodney W. Grimes { 4929b50d902SRodney W. Grimes register int gotcha; 4939b50d902SRodney W. Grimes 4949b50d902SRodney W. Grimes gotcha = 0; 4959b50d902SRodney W. Grimes if (hp->h_to != NIL && w & GTO) 4969b50d902SRodney W. Grimes fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++; 4979b50d902SRodney W. Grimes if (hp->h_subject != NOSTR && w & GSUBJECT) 4989b50d902SRodney W. Grimes fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 4999b50d902SRodney W. Grimes if (hp->h_cc != NIL && w & GCC) 5009b50d902SRodney W. Grimes fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++; 5019b50d902SRodney W. Grimes if (hp->h_bcc != NIL && w & GBCC) 5029b50d902SRodney W. Grimes fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++; 50357392071SJoerg Wunsch if (hp->h_replyto != NOSTR && w & GREPLYTO) 50499bd6601SJoerg Wunsch fprintf(fo, "Reply-To: %s\n", hp->h_replyto), gotcha++; 50557392071SJoerg Wunsch if (hp->h_inreplyto != NOSTR && w & GINREPLYTO) 50699bd6601SJoerg Wunsch fprintf(fo, "In-Reply-To: <%s>\n", hp->h_inreplyto), gotcha++; 5079b50d902SRodney W. Grimes if (gotcha && w & GNL) 5089b50d902SRodney W. Grimes (void) putc('\n', fo); 5099b50d902SRodney W. Grimes return(0); 5109b50d902SRodney W. Grimes } 5119b50d902SRodney W. Grimes 5129b50d902SRodney W. Grimes /* 5139b50d902SRodney W. Grimes * Format the given header line to not exceed 72 characters. 5149b50d902SRodney W. Grimes */ 5159b50d902SRodney W. Grimes void 5169b50d902SRodney W. Grimes fmt(str, np, fo, comma) 5179b50d902SRodney W. Grimes char *str; 5189b50d902SRodney W. Grimes register struct name *np; 5199b50d902SRodney W. Grimes FILE *fo; 5209b50d902SRodney W. Grimes int comma; 5219b50d902SRodney W. Grimes { 5229b50d902SRodney W. Grimes register col, len; 5239b50d902SRodney W. Grimes 5249b50d902SRodney W. Grimes comma = comma ? 1 : 0; 5259b50d902SRodney W. Grimes col = strlen(str); 5269b50d902SRodney W. Grimes if (col) 5279b50d902SRodney W. Grimes fputs(str, fo); 5289b50d902SRodney W. Grimes for (; np != NIL; np = np->n_flink) { 5299b50d902SRodney W. Grimes if (np->n_flink == NIL) 5309b50d902SRodney W. Grimes comma = 0; 5319b50d902SRodney W. Grimes len = strlen(np->n_name); 5329b50d902SRodney W. Grimes col++; /* for the space */ 5339b50d902SRodney W. Grimes if (col + len + comma > 72 && col > 4) { 5349b50d902SRodney W. Grimes fputs("\n ", fo); 5359b50d902SRodney W. Grimes col = 4; 5369b50d902SRodney W. Grimes } else 5379b50d902SRodney W. Grimes putc(' ', fo); 5389b50d902SRodney W. Grimes fputs(np->n_name, fo); 5399b50d902SRodney W. Grimes if (comma) 5409b50d902SRodney W. Grimes putc(',', fo); 5419b50d902SRodney W. Grimes col += len + comma; 5429b50d902SRodney W. Grimes } 5439b50d902SRodney W. Grimes putc('\n', fo); 5449b50d902SRodney W. Grimes } 5459b50d902SRodney W. Grimes 5469b50d902SRodney W. Grimes /* 5479b50d902SRodney W. Grimes * Save the outgoing mail on the passed file. 5489b50d902SRodney W. Grimes */ 5499b50d902SRodney W. Grimes 5509b50d902SRodney W. Grimes /*ARGSUSED*/ 5519b50d902SRodney W. Grimes int 5529b50d902SRodney W. Grimes savemail(name, fi) 5539b50d902SRodney W. Grimes char name[]; 5549b50d902SRodney W. Grimes register FILE *fi; 5559b50d902SRodney W. Grimes { 5569b50d902SRodney W. Grimes register FILE *fo; 5579b50d902SRodney W. Grimes char buf[BUFSIZ]; 5589b50d902SRodney W. Grimes register i; 5599b50d902SRodney W. Grimes time_t now, time(); 5609b50d902SRodney W. Grimes char *ctime(); 5619b50d902SRodney W. Grimes 5629b50d902SRodney W. Grimes if ((fo = Fopen(name, "a")) == NULL) { 5630c3a8314SMike Heffner warn("%s", name); 5649b50d902SRodney W. Grimes return (-1); 5659b50d902SRodney W. Grimes } 5669b50d902SRodney W. Grimes (void) time(&now); 5679b50d902SRodney W. Grimes fprintf(fo, "From %s %s", myname, ctime(&now)); 5689b50d902SRodney W. Grimes while ((i = fread(buf, 1, sizeof buf, fi)) > 0) 5699b50d902SRodney W. Grimes (void) fwrite(buf, 1, i, fo); 5709b50d902SRodney W. Grimes (void) putc('\n', fo); 5719b50d902SRodney W. Grimes (void) fflush(fo); 5729b50d902SRodney W. Grimes if (ferror(fo)) 5730c3a8314SMike Heffner warn("%s", name); 5749b50d902SRodney W. Grimes (void) Fclose(fo); 5759b50d902SRodney W. Grimes rewind(fi); 5769b50d902SRodney W. Grimes return (0); 5779b50d902SRodney W. Grimes } 578