1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 33*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 34*7c478bd9Sstevel@tonic-gate * All Rights Reserved 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 37*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 38*7c478bd9Sstevel@tonic-gate * contributors. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "rcv.h" 44*7c478bd9Sstevel@tonic-gate #include <locale.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* 47*7c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 48*7c478bd9Sstevel@tonic-gate * mail program 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * Mail to others. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate static void fmt(register char *str, register FILE *fo); 54*7c478bd9Sstevel@tonic-gate static FILE *infix(struct header *hp, FILE *fi); 55*7c478bd9Sstevel@tonic-gate static void statusput(register struct message *mp, register FILE *obuf, int doign, int (*fp)(const char *, FILE *)); 56*7c478bd9Sstevel@tonic-gate static int savemail(char name[], struct header *hp, FILE *fi); 57*7c478bd9Sstevel@tonic-gate static int sendmail(char *str); 58*7c478bd9Sstevel@tonic-gate static int Sendmail(char *str); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static off_t textpos; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* 63*7c478bd9Sstevel@tonic-gate * Send message described by the passed pointer to the 64*7c478bd9Sstevel@tonic-gate * passed output buffer. Return -1 on error, but normally 65*7c478bd9Sstevel@tonic-gate * the number of lines written. Adjust the status: field 66*7c478bd9Sstevel@tonic-gate * if need be. If doign is set, suppress ignored header fields. 67*7c478bd9Sstevel@tonic-gate * Call (*fp)(line, obuf) to print the line. 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate long 70*7c478bd9Sstevel@tonic-gate msend( 71*7c478bd9Sstevel@tonic-gate struct message *mailp, 72*7c478bd9Sstevel@tonic-gate FILE *obuf, 73*7c478bd9Sstevel@tonic-gate int flag, 74*7c478bd9Sstevel@tonic-gate int (*fp)(const char *, FILE *)) 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate register struct message *mp; 77*7c478bd9Sstevel@tonic-gate long clen, n, c; 78*7c478bd9Sstevel@tonic-gate FILE *ibuf; 79*7c478bd9Sstevel@tonic-gate char line[LINESIZE], field[BUFSIZ]; 80*7c478bd9Sstevel@tonic-gate int ishead, infld, fline, dostat, doclen, nread, unused; 81*7c478bd9Sstevel@tonic-gate char *cp, *cp2; 82*7c478bd9Sstevel@tonic-gate int doign = flag & M_IGNORE; 83*7c478bd9Sstevel@tonic-gate int oldign = 0; /* previous line was ignored */ 84*7c478bd9Sstevel@tonic-gate long lc; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate mp = mailp; 87*7c478bd9Sstevel@tonic-gate if (mp->m_clen == 0) 88*7c478bd9Sstevel@tonic-gate setclen(mp); 89*7c478bd9Sstevel@tonic-gate ibuf = setinput(mp); 90*7c478bd9Sstevel@tonic-gate c = mp->m_size; 91*7c478bd9Sstevel@tonic-gate ishead = 1; 92*7c478bd9Sstevel@tonic-gate dostat = 1; 93*7c478bd9Sstevel@tonic-gate doclen = 1; 94*7c478bd9Sstevel@tonic-gate infld = 0; 95*7c478bd9Sstevel@tonic-gate fline = 1; 96*7c478bd9Sstevel@tonic-gate lc = 0; 97*7c478bd9Sstevel@tonic-gate clearerr(obuf); 98*7c478bd9Sstevel@tonic-gate while (c > 0L) { 99*7c478bd9Sstevel@tonic-gate nread = getline(line, LINESIZE, ibuf, &unused); 100*7c478bd9Sstevel@tonic-gate c -= nread; 101*7c478bd9Sstevel@tonic-gate lc++; 102*7c478bd9Sstevel@tonic-gate if (ishead) { 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * First line is the From line, so no headers 105*7c478bd9Sstevel@tonic-gate * there to worry about 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate if (fline) { 108*7c478bd9Sstevel@tonic-gate fline = 0; 109*7c478bd9Sstevel@tonic-gate goto writeit; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * If line is blank, we've reached end of 113*7c478bd9Sstevel@tonic-gate * headers, so force out status: field 114*7c478bd9Sstevel@tonic-gate * and note that we are no longer in header 115*7c478bd9Sstevel@tonic-gate * fields. Also force out Content-Length: field. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate if (line[0] == '\n') { 118*7c478bd9Sstevel@tonic-gate if (dostat) { 119*7c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 120*7c478bd9Sstevel@tonic-gate dostat = 0; 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate if (doclen && 123*7c478bd9Sstevel@tonic-gate !isign("content-length", flag&M_SAVING)) { 124*7c478bd9Sstevel@tonic-gate snprintf(field, sizeof (field), 125*7c478bd9Sstevel@tonic-gate "Content-Length: %ld\n", 126*7c478bd9Sstevel@tonic-gate mp->m_clen - 1); 127*7c478bd9Sstevel@tonic-gate (*fp)(field, obuf); 128*7c478bd9Sstevel@tonic-gate if (ferror(obuf)) 129*7c478bd9Sstevel@tonic-gate return(-1); 130*7c478bd9Sstevel@tonic-gate doclen = 0; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate ishead = 0; 133*7c478bd9Sstevel@tonic-gate goto writeit; 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * If this line is a continuation 137*7c478bd9Sstevel@tonic-gate * of a previous header field, just echo it. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate if (isspace(line[0]) && infld) 140*7c478bd9Sstevel@tonic-gate if (oldign) 141*7c478bd9Sstevel@tonic-gate continue; 142*7c478bd9Sstevel@tonic-gate else 143*7c478bd9Sstevel@tonic-gate goto writeit; 144*7c478bd9Sstevel@tonic-gate infld = 0; 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * If we are no longer looking at real 147*7c478bd9Sstevel@tonic-gate * header lines, force out status: 148*7c478bd9Sstevel@tonic-gate * This happens in uucp style mail where 149*7c478bd9Sstevel@tonic-gate * there are no headers at all. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate if (!headerp(line)) { 152*7c478bd9Sstevel@tonic-gate if (dostat) { 153*7c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 154*7c478bd9Sstevel@tonic-gate dostat = 0; 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate (*fp)("\n", obuf); 157*7c478bd9Sstevel@tonic-gate ishead = 0; 158*7c478bd9Sstevel@tonic-gate goto writeit; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate infld++; 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Pick up the header field. 163*7c478bd9Sstevel@tonic-gate * If it is an ignored field and 164*7c478bd9Sstevel@tonic-gate * we care about such things, skip it. 165*7c478bd9Sstevel@tonic-gate */ 166*7c478bd9Sstevel@tonic-gate cp = line; 167*7c478bd9Sstevel@tonic-gate cp2 = field; 168*7c478bd9Sstevel@tonic-gate while (*cp && *cp != ':' && !isspace(*cp)) 169*7c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 170*7c478bd9Sstevel@tonic-gate *cp2 = 0; 171*7c478bd9Sstevel@tonic-gate oldign = doign && isign(field, flag&M_SAVING); 172*7c478bd9Sstevel@tonic-gate if (oldign) 173*7c478bd9Sstevel@tonic-gate continue; 174*7c478bd9Sstevel@tonic-gate /* 175*7c478bd9Sstevel@tonic-gate * If the field is "status," go compute and print the 176*7c478bd9Sstevel@tonic-gate * real Status: field 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate if (icequal(field, "status")) { 179*7c478bd9Sstevel@tonic-gate if (dostat) { 180*7c478bd9Sstevel@tonic-gate statusput(mailp, obuf, doign, fp); 181*7c478bd9Sstevel@tonic-gate dostat = 0; 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate continue; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate if (icequal(field, "content-length")) { 186*7c478bd9Sstevel@tonic-gate if (doclen) { 187*7c478bd9Sstevel@tonic-gate snprintf(line, sizeof (line), 188*7c478bd9Sstevel@tonic-gate "Content-Length: %ld\n", 189*7c478bd9Sstevel@tonic-gate mp->m_clen - 1); 190*7c478bd9Sstevel@tonic-gate (*fp)(line, obuf); 191*7c478bd9Sstevel@tonic-gate if (ferror(obuf)) 192*7c478bd9Sstevel@tonic-gate return(-1); 193*7c478bd9Sstevel@tonic-gate doclen = 0; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate continue; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate writeit: 199*7c478bd9Sstevel@tonic-gate if (!ishead && !mp->m_text && mp->m_clen != 0) { 200*7c478bd9Sstevel@tonic-gate if (line[0] == '\n') 201*7c478bd9Sstevel@tonic-gate putc('\n', obuf); 202*7c478bd9Sstevel@tonic-gate clen = mp->m_clen-1; 203*7c478bd9Sstevel@tonic-gate for (;;) { 204*7c478bd9Sstevel@tonic-gate n = clen < sizeof line ? clen : sizeof line; 205*7c478bd9Sstevel@tonic-gate if ((n = fread(line, 1, (int)n, ibuf)) <= 0) { 206*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 207*7c478bd9Sstevel@tonic-gate "\t(Unexpected end-of-file).\n")); 208*7c478bd9Sstevel@tonic-gate clen = 0; 209*7c478bd9Sstevel@tonic-gate } else { 210*7c478bd9Sstevel@tonic-gate if (fwrite(line, 1, (int)n, obuf) != n) { 211*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 212*7c478bd9Sstevel@tonic-gate "\tError writing to the new file.\n")); 213*7c478bd9Sstevel@tonic-gate fflush(obuf); 214*7c478bd9Sstevel@tonic-gate if (fferror(obuf)) 215*7c478bd9Sstevel@tonic-gate return (-1); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate clen -= n; 219*7c478bd9Sstevel@tonic-gate if (clen <= 0) { 220*7c478bd9Sstevel@tonic-gate break; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate c = 0L; 224*7c478bd9Sstevel@tonic-gate } else { 225*7c478bd9Sstevel@tonic-gate (*fp)(line, obuf); 226*7c478bd9Sstevel@tonic-gate if (ferror(obuf)) 227*7c478bd9Sstevel@tonic-gate return(-1); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate fflush(obuf); 231*7c478bd9Sstevel@tonic-gate if (ferror(obuf)) 232*7c478bd9Sstevel@tonic-gate return(-1); 233*7c478bd9Sstevel@tonic-gate if (ishead && (mailp->m_flag & MSTATUS)) 234*7c478bd9Sstevel@tonic-gate printf(gettext("failed to fix up status field\n")); 235*7c478bd9Sstevel@tonic-gate return(lc); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * Test if the passed line is a header line, RFC 822 style. 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate int 242*7c478bd9Sstevel@tonic-gate headerp(register char *line) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate register char *cp = line; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t' && *cp != ':') 247*7c478bd9Sstevel@tonic-gate cp++; 248*7c478bd9Sstevel@tonic-gate return(*cp == ':'); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * Output a reasonable looking status field. 253*7c478bd9Sstevel@tonic-gate * But if "status" is ignored and doign, forget it. 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate static void 256*7c478bd9Sstevel@tonic-gate statusput( 257*7c478bd9Sstevel@tonic-gate register struct message *mp, 258*7c478bd9Sstevel@tonic-gate register FILE *obuf, 259*7c478bd9Sstevel@tonic-gate int doign, 260*7c478bd9Sstevel@tonic-gate int (*fp)(const char *, FILE *)) 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate char statout[12]; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (doign && isign("status", 0)) 265*7c478bd9Sstevel@tonic-gate return; 266*7c478bd9Sstevel@tonic-gate if ((mp->m_flag & (MNEW|MREAD)) == MNEW) 267*7c478bd9Sstevel@tonic-gate return; 268*7c478bd9Sstevel@tonic-gate strcpy(statout, "Status: "); 269*7c478bd9Sstevel@tonic-gate if (mp->m_flag & MREAD) 270*7c478bd9Sstevel@tonic-gate strcat(statout, "R"); 271*7c478bd9Sstevel@tonic-gate if ((mp->m_flag & MNEW) == 0) 272*7c478bd9Sstevel@tonic-gate strcat(statout, "O"); 273*7c478bd9Sstevel@tonic-gate strcat(statout, "\n"); 274*7c478bd9Sstevel@tonic-gate (*fp)(statout, obuf); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate /* 278*7c478bd9Sstevel@tonic-gate * Interface between the argument list and the mail1 routine 279*7c478bd9Sstevel@tonic-gate * which does all the dirty work. 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate int 283*7c478bd9Sstevel@tonic-gate mail(char **people) 284*7c478bd9Sstevel@tonic-gate { 285*7c478bd9Sstevel@tonic-gate register char *cp2, *cp3; 286*7c478bd9Sstevel@tonic-gate register int s; 287*7c478bd9Sstevel@tonic-gate char *buf, **ap; 288*7c478bd9Sstevel@tonic-gate struct header head; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate for (s = 0, ap = people; *ap; ap++) 291*7c478bd9Sstevel@tonic-gate s += strlen(*ap) + 2; 292*7c478bd9Sstevel@tonic-gate buf = (char *)salloc((unsigned)(s+1)); 293*7c478bd9Sstevel@tonic-gate cp2 = buf; 294*7c478bd9Sstevel@tonic-gate for (ap = people; *ap; ap++) { 295*7c478bd9Sstevel@tonic-gate for (cp3 = *ap; *cp3; ) { 296*7c478bd9Sstevel@tonic-gate if (*cp3 == ' ' || *cp3 == '\t') { 297*7c478bd9Sstevel@tonic-gate *cp3++ = ','; 298*7c478bd9Sstevel@tonic-gate while (*cp3 == ' ' || *cp3 == '\t') 299*7c478bd9Sstevel@tonic-gate cp3++; 300*7c478bd9Sstevel@tonic-gate } else 301*7c478bd9Sstevel@tonic-gate cp3++; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate cp2 = copy(*ap, cp2); 304*7c478bd9Sstevel@tonic-gate *cp2++ = ','; 305*7c478bd9Sstevel@tonic-gate *cp2++ = ' '; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate *cp2 = '\0'; 308*7c478bd9Sstevel@tonic-gate head.h_to = buf; 309*7c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 310*7c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 311*7c478bd9Sstevel@tonic-gate head.h_seq = 0; 312*7c478bd9Sstevel@tonic-gate mail1(&head, Fflag, NOSTR); 313*7c478bd9Sstevel@tonic-gate return(0); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate int 317*7c478bd9Sstevel@tonic-gate sendm(char *str) 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate if (value("flipm") != NOSTR) 320*7c478bd9Sstevel@tonic-gate return(Sendmail(str)); 321*7c478bd9Sstevel@tonic-gate else return(sendmail(str)); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate int 325*7c478bd9Sstevel@tonic-gate Sendm(char *str) 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate if (value("flipm") != NOSTR) 328*7c478bd9Sstevel@tonic-gate return(sendmail(str)); 329*7c478bd9Sstevel@tonic-gate else return(Sendmail(str)); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * Interface to the mail1 routine for the -t flag 334*7c478bd9Sstevel@tonic-gate * (read headers from text). 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate int 337*7c478bd9Sstevel@tonic-gate tmail(void) 338*7c478bd9Sstevel@tonic-gate { 339*7c478bd9Sstevel@tonic-gate struct header head; 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 342*7c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 343*7c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 344*7c478bd9Sstevel@tonic-gate head.h_seq = 0; 345*7c478bd9Sstevel@tonic-gate mail1(&head, Fflag, NOSTR); 346*7c478bd9Sstevel@tonic-gate return(0); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* 350*7c478bd9Sstevel@tonic-gate * Send mail to a bunch of user names. The interface is through 351*7c478bd9Sstevel@tonic-gate * the mail routine below. 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate static int 354*7c478bd9Sstevel@tonic-gate sendmail(char *str) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate struct header head; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if (blankline(str)) 359*7c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 360*7c478bd9Sstevel@tonic-gate else 361*7c478bd9Sstevel@tonic-gate head.h_to = addto(NOSTR, str); 362*7c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 363*7c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 364*7c478bd9Sstevel@tonic-gate head.h_seq = 0; 365*7c478bd9Sstevel@tonic-gate mail1(&head, 0, NOSTR); 366*7c478bd9Sstevel@tonic-gate return(0); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * Send mail to a bunch of user names. The interface is through 371*7c478bd9Sstevel@tonic-gate * the mail routine below. 372*7c478bd9Sstevel@tonic-gate * save a copy of the letter 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate static int 375*7c478bd9Sstevel@tonic-gate Sendmail(char *str) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate struct header head; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate if (blankline(str)) 380*7c478bd9Sstevel@tonic-gate head.h_to = NOSTR; 381*7c478bd9Sstevel@tonic-gate else 382*7c478bd9Sstevel@tonic-gate head.h_to = addto(NOSTR, str); 383*7c478bd9Sstevel@tonic-gate head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR; 384*7c478bd9Sstevel@tonic-gate head.h_others = NOSTRPTR; 385*7c478bd9Sstevel@tonic-gate head.h_seq = 0; 386*7c478bd9Sstevel@tonic-gate mail1(&head, 1, NOSTR); 387*7c478bd9Sstevel@tonic-gate return(0); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate * Walk the list of fds, closing all but one. 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate static int 394*7c478bd9Sstevel@tonic-gate closefd_walk(void *special_fd, int fd) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate if (fd > STDERR_FILENO && fd != *(int *)special_fd) 397*7c478bd9Sstevel@tonic-gate (void) close(fd); 398*7c478bd9Sstevel@tonic-gate return (0); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * Mail a message on standard input to the people indicated 403*7c478bd9Sstevel@tonic-gate * in the passed header. (Internal interface). 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate void 406*7c478bd9Sstevel@tonic-gate mail1(struct header *hp, int use_to, char *orig_to) 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate pid_t p, pid; 409*7c478bd9Sstevel@tonic-gate int i, s, gotcha; 410*7c478bd9Sstevel@tonic-gate char **namelist, *deliver; 411*7c478bd9Sstevel@tonic-gate struct name *to, *np; 412*7c478bd9Sstevel@tonic-gate FILE *mtf, *fp; 413*7c478bd9Sstevel@tonic-gate int remote = rflag != NOSTR || rmail; 414*7c478bd9Sstevel@tonic-gate char **t; 415*7c478bd9Sstevel@tonic-gate char *deadletter; 416*7c478bd9Sstevel@tonic-gate char recfile[PATHSIZE]; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * Collect user's mail from standard input. 420*7c478bd9Sstevel@tonic-gate * Get the result as mtf. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate pid = (pid_t)-1; 424*7c478bd9Sstevel@tonic-gate if ((mtf = collect(hp)) == NULL) 425*7c478bd9Sstevel@tonic-gate return; 426*7c478bd9Sstevel@tonic-gate hp->h_seq = 1; 427*7c478bd9Sstevel@tonic-gate if (hp->h_subject == NOSTR) 428*7c478bd9Sstevel@tonic-gate hp->h_subject = sflag; 429*7c478bd9Sstevel@tonic-gate if (fsize(mtf) == 0 && hp->h_subject == NOSTR) { 430*7c478bd9Sstevel@tonic-gate printf(gettext("No message !?!\n")); 431*7c478bd9Sstevel@tonic-gate goto out; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate if (intty) { 434*7c478bd9Sstevel@tonic-gate printf(gettext("EOT\n")); 435*7c478bd9Sstevel@tonic-gate flush(); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * If we need to use the To: line to determine the record 440*7c478bd9Sstevel@tonic-gate * file, save a copy of it before it's sorted below. 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if (use_to && orig_to == NOSTR && hp->h_to != NOSTR) 444*7c478bd9Sstevel@tonic-gate orig_to = strcpy((char *)salloc(strlen(hp->h_to)+1), hp->h_to); 445*7c478bd9Sstevel@tonic-gate else if (orig_to == NOSTR) 446*7c478bd9Sstevel@tonic-gate orig_to = ""; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate /* 449*7c478bd9Sstevel@tonic-gate * Now, take the user names from the combined 450*7c478bd9Sstevel@tonic-gate * to and cc lists and do all the alias 451*7c478bd9Sstevel@tonic-gate * processing. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate senderr = 0; 455*7c478bd9Sstevel@tonic-gate to = cat(extract(hp->h_bcc, GBCC), 456*7c478bd9Sstevel@tonic-gate cat(extract(hp->h_to, GTO), 457*7c478bd9Sstevel@tonic-gate extract(hp->h_cc, GCC))); 458*7c478bd9Sstevel@tonic-gate to = translate(outpre(elide(usermap(to)))); 459*7c478bd9Sstevel@tonic-gate if (!senderr) 460*7c478bd9Sstevel@tonic-gate mapf(to, myname); 461*7c478bd9Sstevel@tonic-gate mechk(to); 462*7c478bd9Sstevel@tonic-gate for (gotcha = 0, np = to; np != NIL; np = np->n_flink) 463*7c478bd9Sstevel@tonic-gate if ((np->n_type & GDEL) == 0) 464*7c478bd9Sstevel@tonic-gate gotcha++; 465*7c478bd9Sstevel@tonic-gate hp->h_to = detract(to, GTO); 466*7c478bd9Sstevel@tonic-gate hp->h_cc = detract(to, GCC); 467*7c478bd9Sstevel@tonic-gate hp->h_bcc = detract(to, GBCC); 468*7c478bd9Sstevel@tonic-gate if ((mtf = infix(hp, mtf)) == NULL) { 469*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(". . . message lost, sorry.\n")); 470*7c478bd9Sstevel@tonic-gate return; 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate rewind(mtf); 473*7c478bd9Sstevel@tonic-gate if (askme && isatty(0)) { 474*7c478bd9Sstevel@tonic-gate char ans[64]; 475*7c478bd9Sstevel@tonic-gate puthead(hp, stdout, GTO|GCC|GBCC, 0); 476*7c478bd9Sstevel@tonic-gate printf(gettext("Send? ")); 477*7c478bd9Sstevel@tonic-gate printf("[yes] "); 478*7c478bd9Sstevel@tonic-gate if (fgets(ans, sizeof(ans), stdin) && ans[0] && 479*7c478bd9Sstevel@tonic-gate (tolower(ans[0]) != 'y' && ans[0] != '\n')) 480*7c478bd9Sstevel@tonic-gate goto dead; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate if (senderr) 483*7c478bd9Sstevel@tonic-gate goto dead; 484*7c478bd9Sstevel@tonic-gate /* 485*7c478bd9Sstevel@tonic-gate * Look through the recipient list for names with /'s 486*7c478bd9Sstevel@tonic-gate * in them which we write to as files directly. 487*7c478bd9Sstevel@tonic-gate */ 488*7c478bd9Sstevel@tonic-gate i = outof(to, mtf); 489*7c478bd9Sstevel@tonic-gate rewind(mtf); 490*7c478bd9Sstevel@tonic-gate if (!gotcha && !i) { 491*7c478bd9Sstevel@tonic-gate printf(gettext("No recipients specified\n")); 492*7c478bd9Sstevel@tonic-gate goto dead; 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate if (senderr) 495*7c478bd9Sstevel@tonic-gate goto dead; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate getrecf(orig_to, recfile, use_to, sizeof (recfile)); 498*7c478bd9Sstevel@tonic-gate if (recfile != NOSTR && *recfile) 499*7c478bd9Sstevel@tonic-gate savemail(safeexpand(recfile), hp, mtf); 500*7c478bd9Sstevel@tonic-gate if (!gotcha) 501*7c478bd9Sstevel@tonic-gate goto out; 502*7c478bd9Sstevel@tonic-gate namelist = unpack(to); 503*7c478bd9Sstevel@tonic-gate if (debug) { 504*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Recipients of message:\n"); 505*7c478bd9Sstevel@tonic-gate for (t = namelist; *t != NOSTR; t++) 506*7c478bd9Sstevel@tonic-gate fprintf(stderr, " \"%s\"", *t); 507*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 508*7c478bd9Sstevel@tonic-gate return; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* 512*7c478bd9Sstevel@tonic-gate * Wait, to absorb a potential zombie, then 513*7c478bd9Sstevel@tonic-gate * fork, set up the temporary mail file as standard 514*7c478bd9Sstevel@tonic-gate * input for "mail" and exec with the user list we generated 515*7c478bd9Sstevel@tonic-gate * far above. Return the process id to caller in case he 516*7c478bd9Sstevel@tonic-gate * wants to await the completion of mail. 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate #ifdef VMUNIX 520*7c478bd9Sstevel@tonic-gate while (wait3((int *)0, WNOHANG, (struct rusage *)0) > 0) 521*7c478bd9Sstevel@tonic-gate ; 522*7c478bd9Sstevel@tonic-gate #else 523*7c478bd9Sstevel@tonic-gate #ifdef preSVr4 524*7c478bd9Sstevel@tonic-gate wait((int *)0); 525*7c478bd9Sstevel@tonic-gate #else 526*7c478bd9Sstevel@tonic-gate while (waitpid((pid_t)-1, (int *)0, WNOHANG) > 0) 527*7c478bd9Sstevel@tonic-gate ; 528*7c478bd9Sstevel@tonic-gate #endif 529*7c478bd9Sstevel@tonic-gate #endif 530*7c478bd9Sstevel@tonic-gate rewind(mtf); 531*7c478bd9Sstevel@tonic-gate pid = fork(); 532*7c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) { 533*7c478bd9Sstevel@tonic-gate perror("fork"); 534*7c478bd9Sstevel@tonic-gate dead: 535*7c478bd9Sstevel@tonic-gate deadletter = Getf("DEAD"); 536*7c478bd9Sstevel@tonic-gate if (fp = fopen(deadletter, 537*7c478bd9Sstevel@tonic-gate value("appenddeadletter") == NOSTR ? "w" : "a")) { 538*7c478bd9Sstevel@tonic-gate chmod(deadletter, DEADPERM); 539*7c478bd9Sstevel@tonic-gate puthead(hp, fp, GMASK|GCLEN, fsize(mtf) - textpos); 540*7c478bd9Sstevel@tonic-gate fseek(mtf, textpos, 0); 541*7c478bd9Sstevel@tonic-gate lcwrite(deadletter, mtf, fp, 542*7c478bd9Sstevel@tonic-gate value("appenddeadletter") != NOSTR); 543*7c478bd9Sstevel@tonic-gate fclose(fp); 544*7c478bd9Sstevel@tonic-gate } else 545*7c478bd9Sstevel@tonic-gate perror(deadletter); 546*7c478bd9Sstevel@tonic-gate goto out; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate if (pid == 0) { 549*7c478bd9Sstevel@tonic-gate sigchild(); 550*7c478bd9Sstevel@tonic-gate #ifdef SIGTSTP 551*7c478bd9Sstevel@tonic-gate if (remote == 0) { 552*7c478bd9Sstevel@tonic-gate sigset(SIGTSTP, SIG_IGN); 553*7c478bd9Sstevel@tonic-gate sigset(SIGTTIN, SIG_IGN); 554*7c478bd9Sstevel@tonic-gate sigset(SIGTTOU, SIG_IGN); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate #endif 557*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, SIG_IGN); 558*7c478bd9Sstevel@tonic-gate sigset(SIGINT, SIG_IGN); 559*7c478bd9Sstevel@tonic-gate sigset(SIGQUIT, SIG_IGN); 560*7c478bd9Sstevel@tonic-gate s = fileno(mtf); 561*7c478bd9Sstevel@tonic-gate (void) fdwalk(closefd_walk, &s); 562*7c478bd9Sstevel@tonic-gate close(0); 563*7c478bd9Sstevel@tonic-gate dup(s); 564*7c478bd9Sstevel@tonic-gate close(s); 565*7c478bd9Sstevel@tonic-gate #ifdef CC 566*7c478bd9Sstevel@tonic-gate submit(getpid()); 567*7c478bd9Sstevel@tonic-gate #endif /* CC */ 568*7c478bd9Sstevel@tonic-gate if ((deliver = value("sendmail")) == NOSTR) 569*7c478bd9Sstevel@tonic-gate #ifdef SENDMAIL 570*7c478bd9Sstevel@tonic-gate deliver = SENDMAIL; 571*7c478bd9Sstevel@tonic-gate #else 572*7c478bd9Sstevel@tonic-gate deliver = MAIL; 573*7c478bd9Sstevel@tonic-gate #endif 574*7c478bd9Sstevel@tonic-gate execvp(safeexpand(deliver), namelist); 575*7c478bd9Sstevel@tonic-gate perror(deliver); 576*7c478bd9Sstevel@tonic-gate exit(1); 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (value("sendwait")!=NOSTR) 580*7c478bd9Sstevel@tonic-gate remote++; 581*7c478bd9Sstevel@tonic-gate out: 582*7c478bd9Sstevel@tonic-gate if (remote) { 583*7c478bd9Sstevel@tonic-gate while ((p = wait(&s)) != pid && p != (pid_t)-1) 584*7c478bd9Sstevel@tonic-gate ; 585*7c478bd9Sstevel@tonic-gate if (s != 0) 586*7c478bd9Sstevel@tonic-gate senderr++; 587*7c478bd9Sstevel@tonic-gate pid = 0; 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate fclose(mtf); 590*7c478bd9Sstevel@tonic-gate return; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * Prepend a header in front of the collected stuff 595*7c478bd9Sstevel@tonic-gate * and return the new file. 596*7c478bd9Sstevel@tonic-gate */ 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate static FILE * 599*7c478bd9Sstevel@tonic-gate infix(struct header *hp, FILE *fi) 600*7c478bd9Sstevel@tonic-gate { 601*7c478bd9Sstevel@tonic-gate register FILE *nfo, *nfi; 602*7c478bd9Sstevel@tonic-gate register int c; 603*7c478bd9Sstevel@tonic-gate char *postmark, *returnaddr; 604*7c478bd9Sstevel@tonic-gate int fd = -1; 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate rewind(fi); 607*7c478bd9Sstevel@tonic-gate if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 608*7c478bd9Sstevel@tonic-gate (nfo = fdopen(fd, "w")) == NULL) { 609*7c478bd9Sstevel@tonic-gate perror(tempMail); 610*7c478bd9Sstevel@tonic-gate return(fi); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate if ((nfi = fopen(tempMail, "r")) == NULL) { 613*7c478bd9Sstevel@tonic-gate perror(tempMail); 614*7c478bd9Sstevel@tonic-gate fclose(nfo); 615*7c478bd9Sstevel@tonic-gate return(fi); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate removefile(tempMail); 618*7c478bd9Sstevel@tonic-gate postmark = value("postmark"); 619*7c478bd9Sstevel@tonic-gate returnaddr = value("returnaddr"); 620*7c478bd9Sstevel@tonic-gate if ((postmark != NOSTR) || (returnaddr != NOSTR)) { 621*7c478bd9Sstevel@tonic-gate if (returnaddr && *returnaddr) 622*7c478bd9Sstevel@tonic-gate fprintf(nfo, "From: %s", returnaddr); 623*7c478bd9Sstevel@tonic-gate else 624*7c478bd9Sstevel@tonic-gate fprintf(nfo, "From: %s@%s", myname, host); 625*7c478bd9Sstevel@tonic-gate if (postmark && *postmark) 626*7c478bd9Sstevel@tonic-gate fprintf(nfo, " (%s)", postmark); 627*7c478bd9Sstevel@tonic-gate putc('\n', nfo); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate puthead(hp, nfo, (GMASK & ~GBCC) | GCLEN, fsize(fi)); 630*7c478bd9Sstevel@tonic-gate textpos = ftell(nfo); 631*7c478bd9Sstevel@tonic-gate while ((c = getc(fi)) != EOF) 632*7c478bd9Sstevel@tonic-gate putc(c, nfo); 633*7c478bd9Sstevel@tonic-gate if (ferror(fi)) { 634*7c478bd9Sstevel@tonic-gate perror("read"); 635*7c478bd9Sstevel@tonic-gate return(fi); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate fflush(nfo); 638*7c478bd9Sstevel@tonic-gate if (fferror(nfo)) { 639*7c478bd9Sstevel@tonic-gate perror(tempMail); 640*7c478bd9Sstevel@tonic-gate fclose(nfo); 641*7c478bd9Sstevel@tonic-gate fclose(nfi); 642*7c478bd9Sstevel@tonic-gate return(fi); 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate fclose(nfo); 645*7c478bd9Sstevel@tonic-gate fclose(fi); 646*7c478bd9Sstevel@tonic-gate rewind(nfi); 647*7c478bd9Sstevel@tonic-gate return(nfi); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* 651*7c478bd9Sstevel@tonic-gate * Dump the message header on the 652*7c478bd9Sstevel@tonic-gate * passed file buffer. 653*7c478bd9Sstevel@tonic-gate */ 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate puthead(struct header *hp, FILE *fo, int w, long clen) 656*7c478bd9Sstevel@tonic-gate { 657*7c478bd9Sstevel@tonic-gate register int gotcha; 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate gotcha = 0; 660*7c478bd9Sstevel@tonic-gate if (hp->h_to != NOSTR && (w & GTO)) 661*7c478bd9Sstevel@tonic-gate fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++; 662*7c478bd9Sstevel@tonic-gate if ((w & GSUBJECT) && (int)value("bsdcompat")) 663*7c478bd9Sstevel@tonic-gate if (hp->h_subject != NOSTR && *hp->h_subject) 664*7c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 665*7c478bd9Sstevel@tonic-gate else 666*7c478bd9Sstevel@tonic-gate if (sflag && *sflag) 667*7c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", sflag), gotcha++; 668*7c478bd9Sstevel@tonic-gate if (hp->h_cc != NOSTR && (w & GCC)) 669*7c478bd9Sstevel@tonic-gate fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++; 670*7c478bd9Sstevel@tonic-gate if (hp->h_bcc != NOSTR && (w & GBCC)) 671*7c478bd9Sstevel@tonic-gate fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++; 672*7c478bd9Sstevel@tonic-gate if (hp->h_defopt != NOSTR && (w & GDEFOPT)) 673*7c478bd9Sstevel@tonic-gate if (receipt_flg) 674*7c478bd9Sstevel@tonic-gate fprintf(fo, "Return-Receipt-To: %s\n", 675*7c478bd9Sstevel@tonic-gate hp->h_defopt), gotcha++; 676*7c478bd9Sstevel@tonic-gate else 677*7c478bd9Sstevel@tonic-gate fprintf(fo, "Default-Options: %s\n", hp->h_defopt), gotcha++; 678*7c478bd9Sstevel@tonic-gate if ((w & GSUBJECT) && !(int)value("bsdcompat")) 679*7c478bd9Sstevel@tonic-gate if (hp->h_subject != NOSTR && *hp->h_subject) 680*7c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; 681*7c478bd9Sstevel@tonic-gate else 682*7c478bd9Sstevel@tonic-gate if (sflag && *sflag) 683*7c478bd9Sstevel@tonic-gate fprintf(fo, "Subject: %s\n", sflag), gotcha++; 684*7c478bd9Sstevel@tonic-gate if (hp->h_others != NOSTRPTR && (w & GOTHER)) { 685*7c478bd9Sstevel@tonic-gate char **p; 686*7c478bd9Sstevel@tonic-gate for (p = hp->h_others; *p; p++) 687*7c478bd9Sstevel@tonic-gate fprintf(fo, "%s\n", *p); 688*7c478bd9Sstevel@tonic-gate gotcha++; 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate #ifndef preSVr4 691*7c478bd9Sstevel@tonic-gate if (w & GCLEN) 692*7c478bd9Sstevel@tonic-gate fprintf(fo, "Content-Length: %ld\n", clen), gotcha++; 693*7c478bd9Sstevel@tonic-gate #endif 694*7c478bd9Sstevel@tonic-gate if (gotcha && (w & GNL)) 695*7c478bd9Sstevel@tonic-gate putc('\n', fo); 696*7c478bd9Sstevel@tonic-gate return(0); 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * Format the given text to not exceed 78 characters. 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate static void 703*7c478bd9Sstevel@tonic-gate fmt(register char *str, register FILE *fo) 704*7c478bd9Sstevel@tonic-gate { 705*7c478bd9Sstevel@tonic-gate register int col = 4; 706*7c478bd9Sstevel@tonic-gate char name[256]; 707*7c478bd9Sstevel@tonic-gate int len; 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate str = strcpy((char *)salloc(strlen(str)+1), str); 710*7c478bd9Sstevel@tonic-gate while (str = yankword(str, name, sizeof (name), 1)) { 711*7c478bd9Sstevel@tonic-gate len = strlen(name); 712*7c478bd9Sstevel@tonic-gate if (col > 4) { 713*7c478bd9Sstevel@tonic-gate if (col + len > 76) { 714*7c478bd9Sstevel@tonic-gate fputs(",\n ", fo); 715*7c478bd9Sstevel@tonic-gate col = 4; 716*7c478bd9Sstevel@tonic-gate } else { 717*7c478bd9Sstevel@tonic-gate fputs(", ", fo); 718*7c478bd9Sstevel@tonic-gate col += 2; 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate fputs(name, fo); 722*7c478bd9Sstevel@tonic-gate col += len; 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate putc('\n', fo); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate /* 728*7c478bd9Sstevel@tonic-gate * Save the outgoing mail on the passed file. 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate static int 731*7c478bd9Sstevel@tonic-gate savemail(char name[], struct header *hp, FILE *fi) 732*7c478bd9Sstevel@tonic-gate { 733*7c478bd9Sstevel@tonic-gate register FILE *fo; 734*7c478bd9Sstevel@tonic-gate time_t now; 735*7c478bd9Sstevel@tonic-gate char *n; 736*7c478bd9Sstevel@tonic-gate #ifdef preSVr4 737*7c478bd9Sstevel@tonic-gate char line[BUFSIZ]; 738*7c478bd9Sstevel@tonic-gate #else 739*7c478bd9Sstevel@tonic-gate int c; 740*7c478bd9Sstevel@tonic-gate #endif 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (debug) 743*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("save in '%s'\n"), name); 744*7c478bd9Sstevel@tonic-gate if ((fo = fopen(name, "a")) == NULL) { 745*7c478bd9Sstevel@tonic-gate perror(name); 746*7c478bd9Sstevel@tonic-gate return(-1); 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate time(&now); 749*7c478bd9Sstevel@tonic-gate n = rflag; 750*7c478bd9Sstevel@tonic-gate if (n == NOSTR) 751*7c478bd9Sstevel@tonic-gate n = myname; 752*7c478bd9Sstevel@tonic-gate fprintf(fo, "From %s %s", n, ctime(&now)); 753*7c478bd9Sstevel@tonic-gate puthead(hp, fo, GMASK|GCLEN, fsize(fi) - textpos); 754*7c478bd9Sstevel@tonic-gate fseek(fi, textpos, 0); 755*7c478bd9Sstevel@tonic-gate #ifdef preSVr4 756*7c478bd9Sstevel@tonic-gate while (fgets(line, sizeof line, fi)) { 757*7c478bd9Sstevel@tonic-gate if (!strncmp(line, "From ", 5)) 758*7c478bd9Sstevel@tonic-gate putc('>', fo); 759*7c478bd9Sstevel@tonic-gate fputs(line, fo); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate #else 762*7c478bd9Sstevel@tonic-gate while ((c = getc(fi)) != EOF) 763*7c478bd9Sstevel@tonic-gate putc(c, fo); 764*7c478bd9Sstevel@tonic-gate #endif 765*7c478bd9Sstevel@tonic-gate putc('\n', fo); 766*7c478bd9Sstevel@tonic-gate fflush(fo); 767*7c478bd9Sstevel@tonic-gate if (fferror(fo)) 768*7c478bd9Sstevel@tonic-gate perror(name); 769*7c478bd9Sstevel@tonic-gate fclose(fo); 770*7c478bd9Sstevel@tonic-gate return(0); 771*7c478bd9Sstevel@tonic-gate } 772