1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* 27*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*0Sstevel@tonic-gate * Use is subject to license terms. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include "mail.h" 34*0Sstevel@tonic-gate /* 35*0Sstevel@tonic-gate Send mail - High level sending routine 36*0Sstevel@tonic-gate */ 37*0Sstevel@tonic-gate void sendmail(argc, argv) 38*0Sstevel@tonic-gate char **argv; 39*0Sstevel@tonic-gate { 40*0Sstevel@tonic-gate char **args; 41*0Sstevel@tonic-gate char *tp, *zp; 42*0Sstevel@tonic-gate char buf[2048],last1c; 43*0Sstevel@tonic-gate FILE *input; 44*0Sstevel@tonic-gate struct stat sbuf; 45*0Sstevel@tonic-gate int aret; 46*0Sstevel@tonic-gate int i, n; 47*0Sstevel@tonic-gate int oldn = 1; 48*0Sstevel@tonic-gate int ttyf = 0; 49*0Sstevel@tonic-gate int pushrest = 0; 50*0Sstevel@tonic-gate int hdrtyp = 0; 51*0Sstevel@tonic-gate int ctf = FALSE; 52*0Sstevel@tonic-gate int binflg = 0; 53*0Sstevel@tonic-gate long count = 0L; 54*0Sstevel@tonic-gate struct tm *bp; 55*0Sstevel@tonic-gate struct hdrs *hptr; 56*0Sstevel@tonic-gate static char pn[] = "sendmail"; 57*0Sstevel@tonic-gate reciplist list; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate Dout(pn, 0, "entered\n"); 60*0Sstevel@tonic-gate new_reciplist(&list); 61*0Sstevel@tonic-gate for (i = 1; i < argc; ++i) { 62*0Sstevel@tonic-gate if (argv[i][0] == '-') { 63*0Sstevel@tonic-gate if (argv[i][1] == '\0') { 64*0Sstevel@tonic-gate errmsg(E_SYNTAX,"Hyphens MAY NOT be followed by spaces"); 65*0Sstevel@tonic-gate } 66*0Sstevel@tonic-gate if (i > 1) { 67*0Sstevel@tonic-gate errmsg(E_SYNTAX,"Options MUST PRECEDE persons"); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate done(0); 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate /* 72*0Sstevel@tonic-gate Ensure no NULL names in list 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate if (argv[i][0] == '\0' || argv[i][strlen(argv[i])-1] == '!') { 75*0Sstevel@tonic-gate errmsg(E_SYNTAX,"Null names are not allowed"); 76*0Sstevel@tonic-gate done(0); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate add_recip(&list, argv[i], FALSE); /* Don't check for duplication */ 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate mktmp(); 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate Format time 84*0Sstevel@tonic-gate */ 85*0Sstevel@tonic-gate time(&iop); 86*0Sstevel@tonic-gate bp = localtime(&iop); 87*0Sstevel@tonic-gate tp = asctime(bp); 88*0Sstevel@tonic-gate zp = tzname[bp->tm_isdst]; 89*0Sstevel@tonic-gate sprintf(datestring, "%.16s %.3s %.5s", tp, zp, tp+20); 90*0Sstevel@tonic-gate trimnl (datestring); 91*0Sstevel@tonic-gate /* asctime: Fri Sep 30 00:00:00 1986\n */ 92*0Sstevel@tonic-gate /* 0123456789012345678901234 */ 93*0Sstevel@tonic-gate /* RFCtime: Fri, 28 Jul 89 10:30 EDT */ 94*0Sstevel@tonic-gate sprintf(RFC822datestring, "%.3s, %.2s %.3s %.4s %.5s %.3s", 95*0Sstevel@tonic-gate tp, tp+8, tp+4, tp+20, tp+11, zp); 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate Write out the from line header for the letter 99*0Sstevel@tonic-gate */ 100*0Sstevel@tonic-gate if (fromflag && deliverflag && from_user[0] != '\0') { 101*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s %s\n", 102*0Sstevel@tonic-gate header[H_FROM].tag, from_user, datestring); 103*0Sstevel@tonic-gate } else { 104*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s %s\n", 105*0Sstevel@tonic-gate header[H_FROM].tag, my_name, datestring); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate if (!wtmpf(buf, strlen(buf))) { 108*0Sstevel@tonic-gate done(0); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate savehdrs(buf, H_FROM); 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate Copy to list in mail entry? 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate if (flgt == 1 && argc > 1) { 116*0Sstevel@tonic-gate aret = argc; 117*0Sstevel@tonic-gate args = argv; 118*0Sstevel@tonic-gate while (--aret > 0) { 119*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s %s\n", header[H_TO].tag, *++args); 120*0Sstevel@tonic-gate if (!wtmpf(buf, strlen(buf))) { 121*0Sstevel@tonic-gate done(0); 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate savehdrs(buf, H_TO); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate flgf = 1; /* reset when first read of message body succeeds */ 128*0Sstevel@tonic-gate /* 129*0Sstevel@tonic-gate Read mail message, allowing for lines of infinite 130*0Sstevel@tonic-gate length. This is tricky, have to watch for newlines. 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate saveint = setsig(SIGINT, savdead); 133*0Sstevel@tonic-gate last1c = ' '; /* anything other than newline */ 134*0Sstevel@tonic-gate ttyf = isatty (fileno(stdin)); 135*0Sstevel@tonic-gate pushrest = 0; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* 138*0Sstevel@tonic-gate * scan header & save relevant info. 139*0Sstevel@tonic-gate */ 140*0Sstevel@tonic-gate (void) strlcpy(fromU, my_name, sizeof (fromU)); 141*0Sstevel@tonic-gate fromS[0] = 0; /* set up for >From scan */ 142*0Sstevel@tonic-gate input = stdin; 143*0Sstevel@tonic-gate if (fstat(fileno(input), &sbuf) < 0) { 144*0Sstevel@tonic-gate if (errno == EOVERFLOW) { 145*0Sstevel@tonic-gate perror("stdin"); 146*0Sstevel@tonic-gate exit(1); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate while ((n = getline (line, sizeof line, stdin)) > 0) { 151*0Sstevel@tonic-gate last1c = line[n-1]; 152*0Sstevel@tonic-gate if (pushrest) { 153*0Sstevel@tonic-gate if (!wtmpf(line,n)) { 154*0Sstevel@tonic-gate done(0); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate pushrest = (last1c != '\n'); 157*0Sstevel@tonic-gate continue; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate pushrest = (last1c != '\n'); 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate if ((hdrtyp = isheader (line, &ctf)) == FALSE) { 162*0Sstevel@tonic-gate break; 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate flgf = 0; 165*0Sstevel@tonic-gate switch (hdrtyp) { 166*0Sstevel@tonic-gate case H_RVERS: 167*0Sstevel@tonic-gate /* Are we dealing with a delivery report? */ 168*0Sstevel@tonic-gate /* dflag = 9 ==> do not return on failure */ 169*0Sstevel@tonic-gate dflag = 9; 170*0Sstevel@tonic-gate Dout(pn, 0, "dflag = 9\n"); 171*0Sstevel@tonic-gate break; 172*0Sstevel@tonic-gate case H_FROM: 173*0Sstevel@tonic-gate if (!wtmpf(">", 1)) { 174*0Sstevel@tonic-gate done(0); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate /* note dropthru */ 177*0Sstevel@tonic-gate hdrtyp = H_FROM1; 178*0Sstevel@tonic-gate case H_FROM1: 179*0Sstevel@tonic-gate if (substr(line, "forwarded by") > -1) { 180*0Sstevel@tonic-gate break; 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate pickFrom (line); 183*0Sstevel@tonic-gate if (Rpath[0] != '\0') { 184*0Sstevel@tonic-gate strcat(Rpath, "!"); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate (void) strlcat(Rpath, fromS, sizeof (Rpath)); 187*0Sstevel@tonic-gate n = 0; /* don't copy remote from's into mesg. */ 188*0Sstevel@tonic-gate break; 189*0Sstevel@tonic-gate case H_MIMEVERS: 190*0Sstevel@tonic-gate case H_CLEN: 191*0Sstevel@tonic-gate case H_CTYPE: 192*0Sstevel@tonic-gate /* suppress it: only generated if needed */ 193*0Sstevel@tonic-gate n = 0; /* suppress */ 194*0Sstevel@tonic-gate break; 195*0Sstevel@tonic-gate case H_TCOPY: 196*0Sstevel@tonic-gate /* Write out placeholder for later */ 197*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s \n", header[H_TCOPY].tag); 198*0Sstevel@tonic-gate if (!wtmpf(buf, strlen(buf))) { 199*0Sstevel@tonic-gate done(0); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate n = 0; /* suppress */ 202*0Sstevel@tonic-gate break; 203*0Sstevel@tonic-gate case H_MTYPE: 204*0Sstevel@tonic-gate if (flgm) { 205*0Sstevel@tonic-gate /* suppress if message-type argument */ 206*0Sstevel@tonic-gate n = 0; 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate break; 209*0Sstevel@tonic-gate case H_CONT: 210*0Sstevel@tonic-gate if (oldn == 0) { 211*0Sstevel@tonic-gate /* suppress continuation line also */ 212*0Sstevel@tonic-gate n = 0; 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate break; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate oldn = n; /* remember if this line was suppressed */ 217*0Sstevel@tonic-gate if (n && !wtmpf(line,n)) { 218*0Sstevel@tonic-gate done(0); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate if (!n) savehdrs(line, hdrtyp); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate if (Rpath[0] != '\0') { 223*0Sstevel@tonic-gate strcat(Rpath, "!"); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate (void) strlcat(Rpath, fromU, sizeof (Rpath)); 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* push out message type if so requested */ 228*0Sstevel@tonic-gate if (flgm) { /* message-type */ 229*0Sstevel@tonic-gate snprintf(buf, sizeof(buf), "%s%s\n", header[H_MTYPE].tag, msgtype); 230*0Sstevel@tonic-gate if (!wtmpf(buf, strlen(buf))) { 231*0Sstevel@tonic-gate done(0); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate memcpy (buf, line, n); 236*0Sstevel@tonic-gate if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { 237*0Sstevel@tonic-gate if (flgf) { 238*0Sstevel@tonic-gate /* no input */ 239*0Sstevel@tonic-gate return; 240*0Sstevel@tonic-gate } else { 241*0Sstevel@tonic-gate /* 242*0Sstevel@tonic-gate * no content: put mime-version, content-type 243*0Sstevel@tonic-gate * and -length only if explicitly present. 244*0Sstevel@tonic-gate * Write out 'place-holders' only. (see below....) 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate if ((hptr = hdrlines[H_MIMEVERS].head) != 247*0Sstevel@tonic-gate (struct hdrs *)NULL) { 248*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); 249*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 250*0Sstevel@tonic-gate done(0); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CTYPE].head) != 254*0Sstevel@tonic-gate (struct hdrs *)NULL) { 255*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); 256*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 257*0Sstevel@tonic-gate done(0); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CLEN].head) != 261*0Sstevel@tonic-gate (struct hdrs *)NULL) { 262*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); 263*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 264*0Sstevel@tonic-gate done(0); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate goto wrapsend; 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate if (n == 1 && last1c == '\n') { /* blank line -- suppress */ 272*0Sstevel@tonic-gate n = getline (buf, sizeof buf, stdin); 273*0Sstevel@tonic-gate if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { 274*0Sstevel@tonic-gate /* 275*0Sstevel@tonic-gate * no content: put mime-version, content-type 276*0Sstevel@tonic-gate * and -length only if explicitly present. 277*0Sstevel@tonic-gate * Write out 'place-holders' only. (see below....) 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate if ((hptr = hdrlines[H_MIMEVERS].head) != 280*0Sstevel@tonic-gate (struct hdrs *)NULL) { 281*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); 282*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 283*0Sstevel@tonic-gate done(0); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CTYPE].head) != 287*0Sstevel@tonic-gate (struct hdrs *)NULL) { 288*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); 289*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 290*0Sstevel@tonic-gate done(0); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CLEN].head) != 294*0Sstevel@tonic-gate (struct hdrs *)NULL) { 295*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); 296*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 297*0Sstevel@tonic-gate done(0); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate goto wrapsend; 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate if (debug > 0) { 305*0Sstevel@tonic-gate buf[n] = '\0'; 306*0Sstevel@tonic-gate Dout(pn, 0, "header scan complete, readahead %d = \"%s\"\n", n, buf); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* 310*0Sstevel@tonic-gate * Write out H_MIMEVERS, H_CTYPE & H_CLEN lines. These are used only as 311*0Sstevel@tonic-gate * placeholders in the tmp file. When the 'real' message is sent, 312*0Sstevel@tonic-gate * the proper values will be put out by copylet(). 313*0Sstevel@tonic-gate */ 314*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); 315*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 316*0Sstevel@tonic-gate done(0); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate if (hdrlines[H_MIMEVERS].head == (struct hdrs *)NULL) { 319*0Sstevel@tonic-gate savehdrs(line, H_MIMEVERS); 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); 322*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 323*0Sstevel@tonic-gate done(0); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate if (hdrlines[H_CTYPE].head == (struct hdrs *)NULL) { 326*0Sstevel@tonic-gate savehdrs(line,H_CTYPE); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); 329*0Sstevel@tonic-gate if (!wtmpf(line, strlen(line))) { 330*0Sstevel@tonic-gate done(0); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate if (hdrlines[H_CLEN].head == (struct hdrs *)NULL) { 333*0Sstevel@tonic-gate savehdrs(line,H_CLEN); 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate /* and a blank line */ 336*0Sstevel@tonic-gate if (!wtmpf("\n", 1)) { 337*0Sstevel@tonic-gate done(0); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate Dout(pn, 0, "header out completed\n"); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate pushrest = 0; 342*0Sstevel@tonic-gate count = 0L; 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * Are we returning mail from a delivery failure of an old-style 345*0Sstevel@tonic-gate * (SVR3.1 or SVR3.0) rmail? If so, we won't return THIS on failure 346*0Sstevel@tonic-gate * [This line should occur as the FIRST non-blank non-header line] 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate if (!strncmp("***** UNDELIVERABLE MAIL sent to",buf,32)) { 349*0Sstevel@tonic-gate dflag = 9; /* 9 says do not return on failure */ 350*0Sstevel@tonic-gate Dout(pn, 0, "found old-style UNDELIVERABLE line. dflag = 9\n"); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate /* scan body of message */ 354*0Sstevel@tonic-gate while (n > 0) { 355*0Sstevel@tonic-gate if (ttyf && !strcmp (buf, ".\n")) 356*0Sstevel@tonic-gate break; 357*0Sstevel@tonic-gate if (!binflg) { 358*0Sstevel@tonic-gate binflg = !istext ((unsigned char *)buf, n); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if (!wtmpf(buf, n)) { 362*0Sstevel@tonic-gate done(0); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate count += n; 365*0Sstevel@tonic-gate n = ttyf 366*0Sstevel@tonic-gate ? getline (buf, sizeof buf, stdin) 367*0Sstevel@tonic-gate : fread (buf, 1, sizeof buf, stdin); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate setsig(SIGINT, saveint); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate wrapsend: 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * In order to use some of the subroutines that are used to 374*0Sstevel@tonic-gate * read mail, the let array must be set up 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate nlet = 1; 377*0Sstevel@tonic-gate let[0].adr = 0; 378*0Sstevel@tonic-gate let[1].adr = ftell(tmpf); 379*0Sstevel@tonic-gate let[0].text = (binflg == 1 ? FALSE : TRUE); 380*0Sstevel@tonic-gate Dout(pn, 0, "body copy complete, count %ld\n", count); 381*0Sstevel@tonic-gate /* 382*0Sstevel@tonic-gate * Modify value of H_MIMEVERS if necessary. 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate if ((hptr = hdrlines[H_MIMEVERS].head) != (struct hdrs *)NULL) { 385*0Sstevel@tonic-gate if (strlen(hptr->value) == 0) { 386*0Sstevel@tonic-gate (void) strlcpy(hptr->value, "1.0", 387*0Sstevel@tonic-gate sizeof (hptr->value)); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate /* 391*0Sstevel@tonic-gate * Modify value of H_CTYPE if necessary. 392*0Sstevel@tonic-gate */ 393*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { 394*0Sstevel@tonic-gate if (strlen(hptr->value) == 0) { 395*0Sstevel@tonic-gate (void) strlcpy(hptr->value, "text/plain", 396*0Sstevel@tonic-gate sizeof (hptr->value)); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate /* 400*0Sstevel@tonic-gate * Set 'place-holder' value of content length to true value 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { 403*0Sstevel@tonic-gate (void) snprintf(hptr->value, sizeof (hptr->value), 404*0Sstevel@tonic-gate "%ld", count); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate if (fclose(tmpf) == EOF) { 408*0Sstevel@tonic-gate tmperr(); 409*0Sstevel@tonic-gate done(0); 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate tmpf = doopen(lettmp,"r+",E_TMP); 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* Do not send mail on SIGINT */ 415*0Sstevel@tonic-gate if (dflag == 2) { 416*0Sstevel@tonic-gate done(0); 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate sendlist(&list, 0, 0); 420*0Sstevel@tonic-gate done(0); 421*0Sstevel@tonic-gate } 422