17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*6c83d09fSrobbin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*6c83d09fSrobbin /* All Rights Reserved */ 30*6c83d09fSrobbin 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 337c478bd9Sstevel@tonic-gate * The Regents of the University of California 347c478bd9Sstevel@tonic-gate * All Rights Reserved 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 377c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 387c478bd9Sstevel@tonic-gate * contributors. 397c478bd9Sstevel@tonic-gate */ 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include "rcv.h" 447c478bd9Sstevel@tonic-gate #include <locale.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* 477c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 487c478bd9Sstevel@tonic-gate * mail program 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * Mail to others. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate static void fmt(register char *str, register FILE *fo); 547c478bd9Sstevel@tonic-gate static FILE *infix(struct header *hp, FILE *fi); 557c478bd9Sstevel@tonic-gate static void statusput(register struct message *mp, register FILE *obuf, int doign, int (*fp)(const char *, FILE *)); 567c478bd9Sstevel@tonic-gate static int savemail(char name[], struct header *hp, FILE *fi); 577c478bd9Sstevel@tonic-gate static int sendmail(char *str); 587c478bd9Sstevel@tonic-gate static int Sendmail(char *str); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static off_t textpos; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * Send message described by the passed pointer to the 647c478bd9Sstevel@tonic-gate * passed output buffer. Return -1 on error, but normally 657c478bd9Sstevel@tonic-gate * the number of lines written. Adjust the status: field 667c478bd9Sstevel@tonic-gate * if need be. If doign is set, suppress ignored header fields. 677c478bd9Sstevel@tonic-gate * Call (*fp)(line, obuf) to print the line. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate long 707c478bd9Sstevel@tonic-gate msend( 717c478bd9Sstevel@tonic-gate struct message *mailp, 727c478bd9Sstevel@tonic-gate FILE *obuf, 737c478bd9Sstevel@tonic-gate int flag, 747c478bd9Sstevel@tonic-gate int (*fp)(const char *, FILE *)) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate register struct message *mp; 777c478bd9Sstevel@tonic-gate long clen, n, c; 787c478bd9Sstevel@tonic-gate FILE *ibuf; 797c478bd9Sstevel@tonic-gate char line[LINESIZE], field[BUFSIZ]; 807c478bd9Sstevel@tonic-gate int ishead, infld, fline, dostat, doclen, nread, unused; 817c478bd9Sstevel@tonic-gate char *cp, *cp2; 827c478bd9Sstevel@tonic-gate int doign = flag & M_IGNORE; 837c478bd9Sstevel@tonic-gate int oldign = 0; /* previous line was ignored */ 847c478bd9Sstevel@tonic-gate long lc; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate mp = mailp; 877c478bd9Sstevel@tonic-gate if (mp->m_clen == 0) 887c478bd9Sstevel@tonic-gate setclen(mp); 897c478bd9Sstevel@tonic-gate ibuf = setinput(mp); 907c478bd9Sstevel@tonic-gate c = mp->m_size; 917c478bd9Sstevel@tonic-gate ishead = 1; 927c478bd9Sstevel@tonic-gate dostat = 1; 937c478bd9Sstevel@tonic-gate doclen = 1; 947c478bd9Sstevel@tonic-gate infld = 0; 957c478bd9Sstevel@tonic-gate fline = 1; 967c478bd9Sstevel@tonic-gate lc = 0; 977c478bd9Sstevel@tonic-gate clearerr(obuf); 987c478bd9Sstevel@tonic-gate while (c > 0L) { 997c478bd9Sstevel@tonic-gate nread = getline(line, LINESIZE, ibuf, &unused); 1007c478bd9Sstevel@tonic-gate c -= nread; 1017c478bd9Sstevel@tonic-gate lc++; 1027c478bd9Sstevel@tonic-gate if (ishead) { 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * First line is the From line, so no headers 1057c478bd9Sstevel@tonic-gate * there to worry about 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate if (fline) { 1087c478bd9Sstevel@tonic-gate fline = 0; 1097c478bd9Sstevel@tonic-gate goto writeit; 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * If line is blank, we've reached end of 1137c478bd9Sstevel@tonic-gate * headers, so force out status: field 1147c478bd9Sstevel@tonic-gate * and note that we are no longer in header 1157c478bd9Sstevel@tonic-gate * fields. Also force out Content-Length: field. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate if (line[0] == '\n') { 1187c478bd9Sstevel@tonic-gate if (dostat) { 1197c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 1207c478bd9Sstevel@tonic-gate dostat = 0; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate if (doclen && 1237c478bd9Sstevel@tonic-gate !isign("content-length", flag&M_SAVING)) { 1247c478bd9Sstevel@tonic-gate snprintf(field, sizeof (field), 1257c478bd9Sstevel@tonic-gate "Content-Length: %ld\n", 1267c478bd9Sstevel@tonic-gate mp->m_clen - 1); 1277c478bd9Sstevel@tonic-gate (*fp)(field, obuf); 1287c478bd9Sstevel@tonic-gate if (ferror(obuf)) 1297c478bd9Sstevel@tonic-gate return(-1); 1307c478bd9Sstevel@tonic-gate doclen = 0; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate ishead = 0; 1337c478bd9Sstevel@tonic-gate goto writeit; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * If this line is a continuation 1377c478bd9Sstevel@tonic-gate * of a previous header field, just echo it. 1387c478bd9Sstevel@tonic-gate */ 1397c478bd9Sstevel@tonic-gate if (isspace(line[0]) && infld) 1407c478bd9Sstevel@tonic-gate if (oldign) 1417c478bd9Sstevel@tonic-gate continue; 1427c478bd9Sstevel@tonic-gate else 1437c478bd9Sstevel@tonic-gate goto writeit; 1447c478bd9Sstevel@tonic-gate infld = 0; 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * If we are no longer looking at real 1477c478bd9Sstevel@tonic-gate * header lines, force out status: 1487c478bd9Sstevel@tonic-gate * This happens in uucp style mail where 1497c478bd9Sstevel@tonic-gate * there are no headers at all. 1507c478bd9Sstevel@tonic-gate */ 1517c478bd9Sstevel@tonic-gate if (!headerp(line)) { 1527c478bd9Sstevel@tonic-gate if (dostat) { 1537c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 1547c478bd9Sstevel@tonic-gate dostat = 0; 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate (*fp)("\n", obuf); 1577c478bd9Sstevel@tonic-gate ishead = 0; 1587c478bd9Sstevel@tonic-gate goto writeit; 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate infld++; 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Pick up the header field. 1637c478bd9Sstevel@tonic-gate * If it is an ignored field and 1647c478bd9Sstevel@tonic-gate * we care about such things, skip it. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate cp = line; 1677c478bd9Sstevel@tonic-gate cp2 = field; 1687c478bd9Sstevel@tonic-gate while (*cp && *cp != ':' && !isspace(*cp)) 1697c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 1707c478bd9Sstevel@tonic-gate *cp2 = 0; 1717c478bd9Sstevel@tonic-gate oldign = doign && isign(field, flag&M_SAVING); 1727c478bd9Sstevel@tonic-gate if (oldign) 1737c478bd9Sstevel@tonic-gate continue; 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * If the field is "status," go compute and print the 1767c478bd9Sstevel@tonic-gate * real Status: field 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate if (icequal(field, "status")) { 1797c478bd9Sstevel@tonic-gate if (dostat) { 1807c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 1817c478bd9Sstevel@tonic-gate dostat = 0; 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate continue; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate if (icequal(field, "content-length")) { 1867c478bd9Sstevel@tonic-gate if (doclen) { 1877c478bd9Sstevel@tonic-gate snprintf(line, sizeof (line), 1887c478bd9Sstevel@tonic-gate "Content-Length: %ld\n", 1897c478bd9Sstevel@tonic-gate mp->m_clen - 1); 1907c478bd9Sstevel@tonic-gate (*fp)(line, obuf); 1917c478bd9Sstevel@tonic-gate if (ferror(obuf)) 1927c478bd9Sstevel@tonic-gate return(-1); 1937c478bd9Sstevel@tonic-gate doclen = 0; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate continue; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate writeit: 1997c478bd9Sstevel@tonic-gate if (!ishead && !mp->m_text && mp->m_clen != 0) { 2007c478bd9Sstevel@tonic-gate if (line[0] == '\n') 2017c478bd9Sstevel@tonic-gate putc('\n', obuf); 2027c478bd9Sstevel@tonic-gate clen = mp->m_clen-1; 2037c478bd9Sstevel@tonic-gate for (;;) { 2047c478bd9Sstevel@tonic-gate n = clen < sizeof line ? clen : sizeof line; 2057c478bd9Sstevel@tonic-gate if ((n = fread(line, 1, (int)n, ibuf)) <= 0) { 2067c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 2077c478bd9Sstevel@tonic-gate "\t(Unexpected end-of-file).\n")); 2087c478bd9Sstevel@tonic-gate clen = 0; 2097c478bd9Sstevel@tonic-gate } else { 2107c478bd9Sstevel@tonic-gate if (fwrite(line, 1, (int)n, obuf) != n) { 2117c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 2127c478bd9Sstevel@tonic-gate "\tError writing to the new file.\n")); 2137c478bd9Sstevel@tonic-gate fflush(obuf); 2147c478bd9Sstevel@tonic-gate if (fferror(obuf)) 2157c478bd9Sstevel@tonic-gate return (-1); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate clen -= n; 2197c478bd9Sstevel@tonic-gate if (clen <= 0) { 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate c = 0L; 2247c478bd9Sstevel@tonic-gate } else { 2257c478bd9Sstevel@tonic-gate (*fp)(line, obuf); 2267c478bd9Sstevel@tonic-gate if (ferror(obuf)) 2277c478bd9Sstevel@tonic-gate return(-1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate fflush(obuf); 2317c478bd9Sstevel@tonic-gate if (ferror(obuf)) 2327c478bd9Sstevel@tonic-gate return(-1); 2337c478bd9Sstevel@tonic-gate if (ishead && (mailp->m_flag & MSTATUS)) 2347c478bd9Sstevel@tonic-gate printf(gettext("failed to fix up status field\n")); 2357c478bd9Sstevel@tonic-gate return(lc); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Test if the passed line is a header line, RFC 822 style. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate int 2427c478bd9Sstevel@tonic-gate headerp(register char *line) 2437c478bd9Sstevel@tonic-gate { 2447c478bd9Sstevel@tonic-gate register char *cp = line; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t' && *cp != ':') 2477c478bd9Sstevel@tonic-gate cp++; 2487c478bd9Sstevel@tonic-gate return(*cp == ':'); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Output a reasonable looking status field. 2537c478bd9Sstevel@tonic-gate * But if "status" is ignored and doign, forget it. 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate static void 2567c478bd9Sstevel@tonic-gate statusput( 2577c478bd9Sstevel@tonic-gate register struct message *mp, 2587c478bd9Sstevel@tonic-gate register FILE *obuf, 2597c478bd9Sstevel@tonic-gate int doign, 2607c478bd9Sstevel@tonic-gate int (*fp)(const char *, FILE *)) 2617c478bd9Sstevel@tonic-gate { 2627c478bd9Sstevel@tonic-gate char statout[12]; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (doign && isign("status", 0)) 2657c478bd9Sstevel@tonic-gate return; 2667c478bd9Sstevel@tonic-gate if ((mp->m_flag & (MNEW|MREAD)) == MNEW) 2677c478bd9Sstevel@tonic-gate return; 2687c478bd9Sstevel@tonic-gate strcpy(statout, "Status: "); 2697c478bd9Sstevel@tonic-gate if (mp->m_flag & MREAD) 2707c478bd9Sstevel@tonic-gate strcat(statout, "R"); 2717c478bd9Sstevel@tonic-gate if ((mp->m_flag & MNEW) == 0) 2727c478bd9Sstevel@tonic-gate strcat(statout, "O"); 2737c478bd9Sstevel@tonic-gate strcat(statout, "\n"); 2747c478bd9Sstevel@tonic-gate (*fp)(statout, obuf); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Interface between the argument list and the mail1 routine 2797c478bd9Sstevel@tonic-gate * which does all the dirty work. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate int 2837c478bd9Sstevel@tonic-gate mail(char **people) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate register char *cp2, *cp3; 2867c478bd9Sstevel@tonic-gate register int s; 2877c478bd9Sstevel@tonic-gate char *buf, **ap; 2887c478bd9Sstevel@tonic-gate struct header head; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate for (s = 0, ap = people; *ap; ap++) 2917c478bd9Sstevel@tonic-gate s += strlen(*ap) + 2; 2927c478bd9Sstevel@tonic-gate buf = (char *)salloc((unsigned)(s+1)); 2937c478bd9Sstevel@tonic-gate cp2 = buf; 2947c478bd9Sstevel@tonic-gate for (ap = people; *ap; ap++) { 2957c478bd9Sstevel@tonic-gate for (cp3 = *ap; *cp3; ) { 2967c478bd9Sstevel@tonic-gate if (*cp3 == ' ' || *cp3 == '\t') { 2977c478bd9Sstevel@tonic-gate *cp3++ = ','; 2987c478bd9Sstevel@tonic-gate while (*cp3 == ' ' || *cp3 == '\t') 2997c478bd9Sstevel@tonic-gate cp3++; 3007c478bd9Sstevel@tonic-gate } else 3017c478bd9Sstevel@tonic-gate cp3++; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate cp2 = copy(*ap, cp2); 3047c478bd9Sstevel@tonic-gate *cp2++ = ','; 3057c478bd9Sstevel@tonic-gate *cp2++ = ' '; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate *cp2 = '\0'; 3087c478bd9Sstevel@tonic-gate head.h_to = buf; 3097c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 3107c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 3117c478bd9Sstevel@tonic-gate head.h_seq = 0; 3127c478bd9Sstevel@tonic-gate mail1(&head, Fflag, NOSTR); 3137c478bd9Sstevel@tonic-gate return(0); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate int 3177c478bd9Sstevel@tonic-gate sendm(char *str) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate if (value("flipm") != NOSTR) 3207c478bd9Sstevel@tonic-gate return(Sendmail(str)); 3217c478bd9Sstevel@tonic-gate else return(sendmail(str)); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate int 3257c478bd9Sstevel@tonic-gate Sendm(char *str) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate if (value("flipm") != NOSTR) 3287c478bd9Sstevel@tonic-gate return(sendmail(str)); 3297c478bd9Sstevel@tonic-gate else return(Sendmail(str)); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Interface to the mail1 routine for the -t flag 3347c478bd9Sstevel@tonic-gate * (read headers from text). 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate int 3377c478bd9Sstevel@tonic-gate tmail(void) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate struct header head; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 3427c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 3437c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 3447c478bd9Sstevel@tonic-gate head.h_seq = 0; 3457c478bd9Sstevel@tonic-gate mail1(&head, Fflag, NOSTR); 3467c478bd9Sstevel@tonic-gate return(0); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Send mail to a bunch of user names. The interface is through 3517c478bd9Sstevel@tonic-gate * the mail routine below. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate static int 3547c478bd9Sstevel@tonic-gate sendmail(char *str) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate struct header head; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (blankline(str)) 3597c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 3607c478bd9Sstevel@tonic-gate else 3617c478bd9Sstevel@tonic-gate head.h_to = addto(NOSTR, str); 3627c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 3637c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 3647c478bd9Sstevel@tonic-gate head.h_seq = 0; 3657c478bd9Sstevel@tonic-gate mail1(&head, 0, NOSTR); 3667c478bd9Sstevel@tonic-gate return(0); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * Send mail to a bunch of user names. The interface is through 3717c478bd9Sstevel@tonic-gate * the mail routine below. 3727c478bd9Sstevel@tonic-gate * save a copy of the letter 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate static int 3757c478bd9Sstevel@tonic-gate Sendmail(char *str) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate struct header head; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if (blankline(str)) 3807c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 3817c478bd9Sstevel@tonic-gate else 3827c478bd9Sstevel@tonic-gate head.h_to = addto(NOSTR, str); 3837c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 3847c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 3857c478bd9Sstevel@tonic-gate head.h_seq = 0; 3867c478bd9Sstevel@tonic-gate mail1(&head, 1, NOSTR); 3877c478bd9Sstevel@tonic-gate return(0); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * Walk the list of fds, closing all but one. 3927c478bd9Sstevel@tonic-gate */ 3937c478bd9Sstevel@tonic-gate static int 3947c478bd9Sstevel@tonic-gate closefd_walk(void *special_fd, int fd) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate if (fd > STDERR_FILENO && fd != *(int *)special_fd) 3977c478bd9Sstevel@tonic-gate (void) close(fd); 3987c478bd9Sstevel@tonic-gate return (0); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Mail a message on standard input to the people indicated 4037c478bd9Sstevel@tonic-gate * in the passed header. (Internal interface). 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate void 4067c478bd9Sstevel@tonic-gate mail1(struct header *hp, int use_to, char *orig_to) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate pid_t p, pid; 4097c478bd9Sstevel@tonic-gate int i, s, gotcha; 4107c478bd9Sstevel@tonic-gate char **namelist, *deliver; 4117c478bd9Sstevel@tonic-gate struct name *to, *np; 4127c478bd9Sstevel@tonic-gate FILE *mtf, *fp; 4137c478bd9Sstevel@tonic-gate int remote = rflag != NOSTR || rmail; 4147c478bd9Sstevel@tonic-gate char **t; 4157c478bd9Sstevel@tonic-gate char *deadletter; 4167c478bd9Sstevel@tonic-gate char recfile[PATHSIZE]; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * Collect user's mail from standard input. 4207c478bd9Sstevel@tonic-gate * Get the result as mtf. 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate pid = (pid_t)-1; 4247c478bd9Sstevel@tonic-gate if ((mtf = collect(hp)) == NULL) 4257c478bd9Sstevel@tonic-gate return; 4267c478bd9Sstevel@tonic-gate hp->h_seq = 1; 4277c478bd9Sstevel@tonic-gate if (hp->h_subject == NOSTR) 4287c478bd9Sstevel@tonic-gate hp->h_subject = sflag; 4297c478bd9Sstevel@tonic-gate if (fsize(mtf) == 0 && hp->h_subject == NOSTR) { 4307c478bd9Sstevel@tonic-gate printf(gettext("No message !?!\n")); 4317c478bd9Sstevel@tonic-gate goto out; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate if (intty) { 4347c478bd9Sstevel@tonic-gate printf(gettext("EOT\n")); 4357c478bd9Sstevel@tonic-gate flush(); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * If we need to use the To: line to determine the record 4407c478bd9Sstevel@tonic-gate * file, save a copy of it before it's sorted below. 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if (use_to && orig_to == NOSTR && hp->h_to != NOSTR) 4447c478bd9Sstevel@tonic-gate orig_to = strcpy((char *)salloc(strlen(hp->h_to)+1), hp->h_to); 4457c478bd9Sstevel@tonic-gate else if (orig_to == NOSTR) 4467c478bd9Sstevel@tonic-gate orig_to = ""; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * Now, take the user names from the combined 4507c478bd9Sstevel@tonic-gate * to and cc lists and do all the alias 4517c478bd9Sstevel@tonic-gate * processing. 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate senderr = 0; 4557c478bd9Sstevel@tonic-gate to = cat(extract(hp->h_bcc, GBCC), 4567c478bd9Sstevel@tonic-gate cat(extract(hp->h_to, GTO), 4577c478bd9Sstevel@tonic-gate extract(hp->h_cc, GCC))); 4587c478bd9Sstevel@tonic-gate to = translate(outpre(elide(usermap(to)))); 4597c478bd9Sstevel@tonic-gate if (!senderr) 4607c478bd9Sstevel@tonic-gate mapf(to, myname); 4617c478bd9Sstevel@tonic-gate mechk(to); 4627c478bd9Sstevel@tonic-gate for (gotcha = 0, np = to; np != NIL; np = np->n_flink) 4637c478bd9Sstevel@tonic-gate if ((np->n_type & GDEL) == 0) 4647c478bd9Sstevel@tonic-gate gotcha++; 4657c478bd9Sstevel@tonic-gate hp->h_to = detract(to, GTO); 4667c478bd9Sstevel@tonic-gate hp->h_cc = detract(to, GCC); 4677c478bd9Sstevel@tonic-gate hp->h_bcc = detract(to, GBCC); 4687c478bd9Sstevel@tonic-gate if ((mtf = infix(hp, mtf)) == NULL) { 4697c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(". . . message lost, sorry.\n")); 4707c478bd9Sstevel@tonic-gate return; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate rewind(mtf); 4737c478bd9Sstevel@tonic-gate if (askme && isatty(0)) { 4747c478bd9Sstevel@tonic-gate char ans[64]; 4757c478bd9Sstevel@tonic-gate puthead(hp, stdout, GTO|GCC|GBCC, 0); 4767c478bd9Sstevel@tonic-gate printf(gettext("Send? ")); 4777c478bd9Sstevel@tonic-gate printf("[yes] "); 4787c478bd9Sstevel@tonic-gate if (fgets(ans, sizeof(ans), stdin) && ans[0] && 4797c478bd9Sstevel@tonic-gate (tolower(ans[0]) != 'y' && ans[0] != '\n')) 4807c478bd9Sstevel@tonic-gate goto dead; 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate if (senderr) 4837c478bd9Sstevel@tonic-gate goto dead; 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Look through the recipient list for names with /'s 4867c478bd9Sstevel@tonic-gate * in them which we write to as files directly. 4877c478bd9Sstevel@tonic-gate */ 4887c478bd9Sstevel@tonic-gate i = outof(to, mtf); 4897c478bd9Sstevel@tonic-gate rewind(mtf); 4907c478bd9Sstevel@tonic-gate if (!gotcha && !i) { 4917c478bd9Sstevel@tonic-gate printf(gettext("No recipients specified\n")); 4927c478bd9Sstevel@tonic-gate goto dead; 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate if (senderr) 4957c478bd9Sstevel@tonic-gate goto dead; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate getrecf(orig_to, recfile, use_to, sizeof (recfile)); 4987c478bd9Sstevel@tonic-gate if (recfile != NOSTR && *recfile) 4997c478bd9Sstevel@tonic-gate savemail(safeexpand(recfile), hp, mtf); 5007c478bd9Sstevel@tonic-gate if (!gotcha) 5017c478bd9Sstevel@tonic-gate goto out; 5027c478bd9Sstevel@tonic-gate namelist = unpack(to); 5037c478bd9Sstevel@tonic-gate if (debug) { 5047c478bd9Sstevel@tonic-gate fprintf(stderr, "Recipients of message:\n"); 5057c478bd9Sstevel@tonic-gate for (t = namelist; *t != NOSTR; t++) 5067c478bd9Sstevel@tonic-gate fprintf(stderr, " \"%s\"", *t); 5077c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 5087c478bd9Sstevel@tonic-gate return; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * Wait, to absorb a potential zombie, then 5137c478bd9Sstevel@tonic-gate * fork, set up the temporary mail file as standard 5147c478bd9Sstevel@tonic-gate * input for "mail" and exec with the user list we generated 5157c478bd9Sstevel@tonic-gate * far above. Return the process id to caller in case he 5167c478bd9Sstevel@tonic-gate * wants to await the completion of mail. 5177c478bd9Sstevel@tonic-gate */ 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate #ifdef VMUNIX 5207c478bd9Sstevel@tonic-gate while (wait3((int *)0, WNOHANG, (struct rusage *)0) > 0) 5217c478bd9Sstevel@tonic-gate ; 5227c478bd9Sstevel@tonic-gate #else 5237c478bd9Sstevel@tonic-gate #ifdef preSVr4 5247c478bd9Sstevel@tonic-gate wait((int *)0); 5257c478bd9Sstevel@tonic-gate #else 5267c478bd9Sstevel@tonic-gate while (waitpid((pid_t)-1, (int *)0, WNOHANG) > 0) 5277c478bd9Sstevel@tonic-gate ; 5287c478bd9Sstevel@tonic-gate #endif 5297c478bd9Sstevel@tonic-gate #endif 5307c478bd9Sstevel@tonic-gate rewind(mtf); 5317c478bd9Sstevel@tonic-gate pid = fork(); 5327c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) { 5337c478bd9Sstevel@tonic-gate perror("fork"); 5347c478bd9Sstevel@tonic-gate dead: 5357c478bd9Sstevel@tonic-gate deadletter = Getf("DEAD"); 5367c478bd9Sstevel@tonic-gate if (fp = fopen(deadletter, 5377c478bd9Sstevel@tonic-gate value("appenddeadletter") == NOSTR ? "w" : "a")) { 5387c478bd9Sstevel@tonic-gate chmod(deadletter, DEADPERM); 5397c478bd9Sstevel@tonic-gate puthead(hp, fp, GMASK|GCLEN, fsize(mtf) - textpos); 5407c478bd9Sstevel@tonic-gate fseek(mtf, textpos, 0); 5417c478bd9Sstevel@tonic-gate lcwrite(deadletter, mtf, fp, 5427c478bd9Sstevel@tonic-gate value("appenddeadletter") != NOSTR); 5437c478bd9Sstevel@tonic-gate fclose(fp); 5447c478bd9Sstevel@tonic-gate } else 5457c478bd9Sstevel@tonic-gate perror(deadletter); 5467c478bd9Sstevel@tonic-gate goto out; 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate if (pid == 0) { 5497c478bd9Sstevel@tonic-gate sigchild(); 5507c478bd9Sstevel@tonic-gate #ifdef SIGTSTP 5517c478bd9Sstevel@tonic-gate if (remote == 0) { 5527c478bd9Sstevel@tonic-gate sigset(SIGTSTP, SIG_IGN); 5537c478bd9Sstevel@tonic-gate sigset(SIGTTIN, SIG_IGN); 5547c478bd9Sstevel@tonic-gate sigset(SIGTTOU, SIG_IGN); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate #endif 5577c478bd9Sstevel@tonic-gate sigset(SIGHUP, SIG_IGN); 5587c478bd9Sstevel@tonic-gate sigset(SIGINT, SIG_IGN); 5597c478bd9Sstevel@tonic-gate sigset(SIGQUIT, SIG_IGN); 5607c478bd9Sstevel@tonic-gate s = fileno(mtf); 5617c478bd9Sstevel@tonic-gate (void) fdwalk(closefd_walk, &s); 5627c478bd9Sstevel@tonic-gate close(0); 5637c478bd9Sstevel@tonic-gate dup(s); 5647c478bd9Sstevel@tonic-gate close(s); 5657c478bd9Sstevel@tonic-gate #ifdef CC 5667c478bd9Sstevel@tonic-gate submit(getpid()); 5677c478bd9Sstevel@tonic-gate #endif /* CC */ 5687c478bd9Sstevel@tonic-gate if ((deliver = value("sendmail")) == NOSTR) 5697c478bd9Sstevel@tonic-gate #ifdef SENDMAIL 5707c478bd9Sstevel@tonic-gate deliver = SENDMAIL; 5717c478bd9Sstevel@tonic-gate #else 5727c478bd9Sstevel@tonic-gate deliver = MAIL; 5737c478bd9Sstevel@tonic-gate #endif 5747c478bd9Sstevel@tonic-gate execvp(safeexpand(deliver), namelist); 5757c478bd9Sstevel@tonic-gate perror(deliver); 5767c478bd9Sstevel@tonic-gate exit(1); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (value("sendwait")!=NOSTR) 5807c478bd9Sstevel@tonic-gate remote++; 5817c478bd9Sstevel@tonic-gate out: 5827c478bd9Sstevel@tonic-gate if (remote) { 5837c478bd9Sstevel@tonic-gate while ((p = wait(&s)) != pid && p != (pid_t)-1) 5847c478bd9Sstevel@tonic-gate ; 5857c478bd9Sstevel@tonic-gate if (s != 0) 5867c478bd9Sstevel@tonic-gate senderr++; 5877c478bd9Sstevel@tonic-gate pid = 0; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate fclose(mtf); 5907c478bd9Sstevel@tonic-gate return; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * Prepend a header in front of the collected stuff 5957c478bd9Sstevel@tonic-gate * and return the new file. 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate static FILE * 5997c478bd9Sstevel@tonic-gate infix(struct header *hp, FILE *fi) 6007c478bd9Sstevel@tonic-gate { 6017c478bd9Sstevel@tonic-gate register FILE *nfo, *nfi; 6027c478bd9Sstevel@tonic-gate register int c; 6037c478bd9Sstevel@tonic-gate char *postmark, *returnaddr; 6047c478bd9Sstevel@tonic-gate int fd = -1; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate rewind(fi); 6077c478bd9Sstevel@tonic-gate if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 6087c478bd9Sstevel@tonic-gate (nfo = fdopen(fd, "w")) == NULL) { 6097c478bd9Sstevel@tonic-gate perror(tempMail); 6107c478bd9Sstevel@tonic-gate return(fi); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate if ((nfi = fopen(tempMail, "r")) == NULL) { 6137c478bd9Sstevel@tonic-gate perror(tempMail); 6147c478bd9Sstevel@tonic-gate fclose(nfo); 6157c478bd9Sstevel@tonic-gate return(fi); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate removefile(tempMail); 6187c478bd9Sstevel@tonic-gate postmark = value("postmark"); 6197c478bd9Sstevel@tonic-gate returnaddr = value("returnaddr"); 6207c478bd9Sstevel@tonic-gate if ((postmark != NOSTR) || (returnaddr != NOSTR)) { 6217c478bd9Sstevel@tonic-gate if (returnaddr && *returnaddr) 6227c478bd9Sstevel@tonic-gate fprintf(nfo, "From: %s", returnaddr); 6237c478bd9Sstevel@tonic-gate else 6247c478bd9Sstevel@tonic-gate fprintf(nfo, "From: %s@%s", myname, host); 6257c478bd9Sstevel@tonic-gate if (postmark && *postmark) 6267c478bd9Sstevel@tonic-gate fprintf(nfo, " (%s)", postmark); 6277c478bd9Sstevel@tonic-gate putc('\n', nfo); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate puthead(hp, nfo, (GMASK & ~GBCC) | GCLEN, fsize(fi)); 6307c478bd9Sstevel@tonic-gate textpos = ftell(nfo); 6317c478bd9Sstevel@tonic-gate while ((c = getc(fi)) != EOF) 6327c478bd9Sstevel@tonic-gate putc(c, nfo); 6337c478bd9Sstevel@tonic-gate if (ferror(fi)) { 6347c478bd9Sstevel@tonic-gate perror("read"); 6357c478bd9Sstevel@tonic-gate return(fi); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate fflush(nfo); 6387c478bd9Sstevel@tonic-gate if (fferror(nfo)) { 6397c478bd9Sstevel@tonic-gate perror(tempMail); 6407c478bd9Sstevel@tonic-gate fclose(nfo); 6417c478bd9Sstevel@tonic-gate fclose(nfi); 6427c478bd9Sstevel@tonic-gate return(fi); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate fclose(nfo); 6457c478bd9Sstevel@tonic-gate fclose(fi); 6467c478bd9Sstevel@tonic-gate rewind(nfi); 6477c478bd9Sstevel@tonic-gate return(nfi); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * Dump the message header on the 6527c478bd9Sstevel@tonic-gate * passed file buffer. 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate 655*6c83d09fSrobbin int 6567c478bd9Sstevel@tonic-gate puthead(struct header *hp, FILE *fo, int w, long clen) 6577c478bd9Sstevel@tonic-gate { 6587c478bd9Sstevel@tonic-gate register int gotcha; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate gotcha = 0; 6617c478bd9Sstevel@tonic-gate if (hp->h_to != NOSTR && (w & GTO)) 6627c478bd9Sstevel@tonic-gate fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++; 6637c478bd9Sstevel@tonic-gate if ((w & GSUBJECT) && (int)value("bsdcompat")) 6647c478bd9Sstevel@tonic-gate if (hp->h_subject != NOSTR && *hp->h_subject) 6657c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 6667c478bd9Sstevel@tonic-gate else 6677c478bd9Sstevel@tonic-gate if (sflag && *sflag) 6687c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", sflag), gotcha++; 6697c478bd9Sstevel@tonic-gate if (hp->h_cc != NOSTR && (w & GCC)) 6707c478bd9Sstevel@tonic-gate fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++; 6717c478bd9Sstevel@tonic-gate if (hp->h_bcc != NOSTR && (w & GBCC)) 6727c478bd9Sstevel@tonic-gate fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++; 6737c478bd9Sstevel@tonic-gate if (hp->h_defopt != NOSTR && (w & GDEFOPT)) 6747c478bd9Sstevel@tonic-gate if (receipt_flg) 6757c478bd9Sstevel@tonic-gate fprintf(fo, "Return-Receipt-To: %s\n", 6767c478bd9Sstevel@tonic-gate hp->h_defopt), gotcha++; 6777c478bd9Sstevel@tonic-gate else 6787c478bd9Sstevel@tonic-gate fprintf(fo, "Default-Options: %s\n", hp->h_defopt), gotcha++; 6797c478bd9Sstevel@tonic-gate if ((w & GSUBJECT) && !(int)value("bsdcompat")) 6807c478bd9Sstevel@tonic-gate if (hp->h_subject != NOSTR && *hp->h_subject) 6817c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 6827c478bd9Sstevel@tonic-gate else 6837c478bd9Sstevel@tonic-gate if (sflag && *sflag) 6847c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", sflag), gotcha++; 6857c478bd9Sstevel@tonic-gate if (hp->h_others != NOSTRPTR && (w & GOTHER)) { 6867c478bd9Sstevel@tonic-gate char **p; 6877c478bd9Sstevel@tonic-gate for (p = hp->h_others; *p; p++) 6887c478bd9Sstevel@tonic-gate fprintf(fo, "%s\n", *p); 6897c478bd9Sstevel@tonic-gate gotcha++; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate #ifndef preSVr4 6927c478bd9Sstevel@tonic-gate if (w & GCLEN) 6937c478bd9Sstevel@tonic-gate fprintf(fo, "Content-Length: %ld\n", clen), gotcha++; 6947c478bd9Sstevel@tonic-gate #endif 6957c478bd9Sstevel@tonic-gate if (gotcha && (w & GNL)) 6967c478bd9Sstevel@tonic-gate putc('\n', fo); 6977c478bd9Sstevel@tonic-gate return(0); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* 7017c478bd9Sstevel@tonic-gate * Format the given text to not exceed 78 characters. 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate static void 7047c478bd9Sstevel@tonic-gate fmt(register char *str, register FILE *fo) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate register int col = 4; 7077c478bd9Sstevel@tonic-gate char name[256]; 7087c478bd9Sstevel@tonic-gate int len; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate str = strcpy((char *)salloc(strlen(str)+1), str); 7117c478bd9Sstevel@tonic-gate while (str = yankword(str, name, sizeof (name), 1)) { 7127c478bd9Sstevel@tonic-gate len = strlen(name); 7137c478bd9Sstevel@tonic-gate if (col > 4) { 7147c478bd9Sstevel@tonic-gate if (col + len > 76) { 7157c478bd9Sstevel@tonic-gate fputs(",\n ", fo); 7167c478bd9Sstevel@tonic-gate col = 4; 7177c478bd9Sstevel@tonic-gate } else { 7187c478bd9Sstevel@tonic-gate fputs(", ", fo); 7197c478bd9Sstevel@tonic-gate col += 2; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate fputs(name, fo); 7237c478bd9Sstevel@tonic-gate col += len; 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate putc('\n', fo); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * Save the outgoing mail on the passed file. 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate static int 7327c478bd9Sstevel@tonic-gate savemail(char name[], struct header *hp, FILE *fi) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate register FILE *fo; 7357c478bd9Sstevel@tonic-gate time_t now; 7367c478bd9Sstevel@tonic-gate char *n; 7377c478bd9Sstevel@tonic-gate #ifdef preSVr4 7387c478bd9Sstevel@tonic-gate char line[BUFSIZ]; 7397c478bd9Sstevel@tonic-gate #else 7407c478bd9Sstevel@tonic-gate int c; 7417c478bd9Sstevel@tonic-gate #endif 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (debug) 7447c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("save in '%s'\n"), name); 7457c478bd9Sstevel@tonic-gate if ((fo = fopen(name, "a")) == NULL) { 7467c478bd9Sstevel@tonic-gate perror(name); 7477c478bd9Sstevel@tonic-gate return(-1); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate time(&now); 7507c478bd9Sstevel@tonic-gate n = rflag; 7517c478bd9Sstevel@tonic-gate if (n == NOSTR) 7527c478bd9Sstevel@tonic-gate n = myname; 7537c478bd9Sstevel@tonic-gate fprintf(fo, "From %s %s", n, ctime(&now)); 7547c478bd9Sstevel@tonic-gate puthead(hp, fo, GMASK|GCLEN, fsize(fi) - textpos); 7557c478bd9Sstevel@tonic-gate fseek(fi, textpos, 0); 7567c478bd9Sstevel@tonic-gate #ifdef preSVr4 7577c478bd9Sstevel@tonic-gate while (fgets(line, sizeof line, fi)) { 7587c478bd9Sstevel@tonic-gate if (!strncmp(line, "From ", 5)) 7597c478bd9Sstevel@tonic-gate putc('>', fo); 7607c478bd9Sstevel@tonic-gate fputs(line, fo); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate #else 7637c478bd9Sstevel@tonic-gate while ((c = getc(fi)) != EOF) 7647c478bd9Sstevel@tonic-gate putc(c, fo); 7657c478bd9Sstevel@tonic-gate #endif 7667c478bd9Sstevel@tonic-gate putc('\n', fo); 7677c478bd9Sstevel@tonic-gate fflush(fo); 7687c478bd9Sstevel@tonic-gate if (fferror(fo)) 7697c478bd9Sstevel@tonic-gate perror(name); 7707c478bd9Sstevel@tonic-gate fclose(fo); 7717c478bd9Sstevel@tonic-gate return(0); 7727c478bd9Sstevel@tonic-gate } 773