1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2017 Gary Mills 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 #include "mail.h" 32 33 /* 34 NAME 35 copylet - copy a given letter to a file pointer 36 37 SYNOPSIS 38 int copylet(int letnum, FILE *f, int type) 39 40 DESCRIPTION 41 Copylet() will copy the letter "letnum" to the 42 given file pointer. 43 44 letnum -> index into: letter table 45 f -> file pointer to copy file to 46 type -> copy type 47 48 Returns TRUE on a completely successful copy. 49 */ 50 51 int 52 copylet(int letnum, FILE *f, int type) 53 { 54 int pos = ftell(f); 55 int rc = xxxcopylet(letnum, f, type); 56 57 if (fflush(f) != 0) 58 rc = FALSE; 59 60 /* 61 * On error, truncate the file to its original position so that a 62 * partial message is not left in the mailbox. 63 */ 64 if (rc == FALSE) 65 ftruncate(fileno(f), pos); 66 67 return(rc); 68 } 69 70 int 71 xxxcopylet(int letnum, FILE *f, int type) 72 { 73 static char pn[] = "copylet"; 74 char buf[LSIZE], lastc; 75 char wbuf[LSIZE]; 76 int n; 77 long i, k; 78 int num; 79 int rtrncont = 1; /* True: nondelivery&content included, or regular mail */ 80 int suppress = FALSE; 81 int sav_suppress = FALSE; /* Did we suppress previous hdr line? */ 82 int print_from_struct = FALSE; /* print from hdrlines struct */ 83 /* rather than fgets() buffer */ 84 int pushrest = FALSE; 85 int ctf = FALSE; 86 int didafflines = FALSE; /* Did we already put out any */ 87 /* H_AFWDFROM lines? */ 88 int didrcvlines = FALSE; /* Did we already put out any */ 89 /* H_RECEIVED lines? */ 90 long clen = -1L; 91 int htype; /* header type */ 92 struct hdrs *hptr; 93 94 if (!sending) { 95 /* Clear out any saved header info from previous message */ 96 clr_hinfo(); 97 } 98 99 fseek(tmpf, let[letnum].adr, 0); 100 /* Get size of message as stored into tempfile by copymt() */ 101 k = let[letnum+1].adr - let[letnum].adr; 102 Dout(pn, 1, "(letnum = %d, type = %d), k = %ld\n", letnum, type, k); 103 while (k>0) { /* process header */ 104 num = ((k < sizeof(buf)) ? k+1 : sizeof(buf)); 105 if (fgets (buf, num, tmpf) == NULL) { 106 return (FALSE); 107 } 108 if ((n = strlen (buf)) == 0) { 109 k = 0; 110 break; 111 } 112 k -= n; 113 lastc = buf[n-1]; 114 if (pushrest) { 115 pushrest = (lastc != '\n'); 116 continue; 117 } 118 htype = isheader (buf, &ctf); 119 Dout(pn, 5, "loop 1: buf = %s, htype= %d/%s\n", buf, htype, header[htype].tag); 120 if (htype == H_CLEN) { 121 if (!sending) { 122 savehdrs(buf,htype); 123 } 124 if ((hptr = hdrlines[H_CLEN].head) != 125 (struct hdrs *)NULL) { 126 clen = atol (hptr->value); 127 } 128 } 129 if (type == ZAP) { 130 if (htype != FALSE) { 131 pushrest = (lastc != '\n'); 132 continue; 133 } 134 /* end of header. Print non-blank line and bail. */ 135 Dout(pn, 5, "ZAP end header; n=%d, buf[0] = %d\n", n, buf[0]); 136 if (buf[0] != '\n') { 137 if (fwrite(buf,1,n,f) != n) { 138 sav_errno = errno; 139 return(FALSE); 140 } 141 } else { 142 n = 0; 143 } 144 break; 145 } 146 /* Copy From line appropriately */ 147 if (fwrite(buf,1,n-1,f) != n-1) { 148 sav_errno = errno; 149 return(FALSE); 150 } 151 if (lastc != '\n') { 152 if (fwrite(&lastc,1,1,f) != 1) { 153 sav_errno = errno; 154 return(FALSE); 155 } 156 continue; 157 } 158 switch(type) { 159 case REMOTE: 160 if (fprintf(f, rmtmsg, thissys) < 0) 161 { 162 sav_errno = errno; 163 return(FALSE); 164 } 165 166 break; 167 168 case TTY: 169 case ORDINARY: 170 default: 171 if (fprintf(f, "\n") < 0) 172 { 173 sav_errno = errno; 174 return(FALSE); 175 } 176 break; 177 } 178 if ((error > 0) && (dflag == 1)) { 179 Dout(pn, 3, "before gendeliv(), uval = '%s'\n", uval); 180 gendeliv(f, dflag, uval); 181 if (!(ckdlivopts(H_TCOPY, (int*)0) & RETURN)) { 182 rtrncont = 0; 183 } else { 184 /* Account for content-type info */ 185 /* of returned msg */ 186 if (fprintf(f, "%s %s\n", header[H_CTYPE].tag, 187 (let[letnum].text == TRUE ? "text/plain" : "application/octet-stream")) < 0) 188 { 189 sav_errno = errno; 190 return(FALSE); 191 } 192 193 /* Compute Content-Length of what's being */ 194 /* returned... */ 195 i = k; 196 /* Account for H_AFWDFROM, H_AFWDCNT, */ 197 /* H_TCOPY, or H_RECEIVED lines which may */ 198 /* be added later */ 199 if (affcnt > 0) { 200 sprintf(wbuf, "%d", affcnt); 201 i += (affbytecnt 202 + strlen(header[H_AFWDCNT].tag) 203 + strlen(wbuf) + 2); 204 } 205 if (orig_tcopy) { 206 if ((hptr = hdrlines[H_TCOPY].head) != 207 (struct hdrs *)NULL) { 208 i += 209 strlen(hdrlines[H_TCOPY].head->value); 210 } 211 } 212 if ((hptr = hdrlines[H_RECEIVED].head) != 213 (struct hdrs *)NULL) { 214 i += rcvbytecnt; 215 } 216 /* Add in strlen of MIME-Version:, */ 217 /* Content-Length: and Content-Type: */ 218 /* values for msg being returned... */ 219 if ((hptr = hdrlines[H_MIMEVERS].head) != 220 (struct hdrs *)NULL) { 221 i += strlen(hdrlines[H_MIMEVERS].head->value); 222 } 223 if ((hptr = hdrlines[H_CTYPE].head) != 224 (struct hdrs *)NULL) { 225 i += strlen(hdrlines[H_CTYPE].head->value); 226 } 227 if ((hptr = hdrlines[H_CLEN].head) != 228 (struct hdrs *)NULL) { 229 i += strlen(hdrlines[H_CLEN].head->value); 230 } 231 if (fprintf(f, "%s %ld\n", header[H_CLEN].tag, i) < 0) 232 { 233 sav_errno = errno; 234 return(FALSE); 235 } 236 } 237 if (fprintf(f, "\n") < 0) 238 { 239 sav_errno = errno; 240 return(FALSE); 241 } 242 } 243 if (fflush(f)) 244 { 245 sav_errno = errno; 246 return(FALSE); 247 } 248 249 break; 250 } 251 /* if not ZAP, copy balance of header */ 252 n = 0; 253 if ((type != ZAP) && rtrncont) 254 while (k>0 || n>0) { 255 if ((n > 0) && !suppress) { 256 if (print_from_struct == TRUE) { 257 if (printhdr (type, htype, hptr, f) < 0) { 258 return (FALSE); 259 } 260 } else { 261 if (sel_disp(type, htype, buf) >= 0) { 262 if (fwrite(buf,1,n,f) != n) { 263 sav_errno = errno; 264 return(FALSE); 265 } 266 } 267 } 268 if (htype == H_DATE) { 269 dumprcv(type, htype,&didrcvlines,&suppress,f); 270 dumpaff(type, htype,&didafflines,&suppress,f); 271 } 272 } 273 if (k <= 0) { 274 /* Can only get here if k=0 && n>0, which occurs */ 275 /* in a message with header lines but no content. */ 276 /* If we haven't already done it, force out any */ 277 /* H_AFWDFROM or H_RECEIVED lines */ 278 dumprcv(type, -1,&didrcvlines,&suppress,f); 279 dumpaff(type, -1,&didafflines,&suppress,f); 280 break; 281 } 282 num = ((k < sizeof(buf)) ? k+1 : sizeof(buf)); 283 if (fgets (buf, num, tmpf) == NULL) { 284 return (FALSE); 285 } 286 n = strlen (buf); 287 k -= n; 288 lastc = buf[n-1]; 289 290 if (pushrest) { 291 pushrest = (lastc != '\n'); 292 continue; 293 } 294 sav_suppress = suppress; 295 suppress = FALSE; 296 print_from_struct = FALSE; 297 htype = isheader (buf, &ctf); 298 Dout(pn, 5, "loop 2: buf = %s, htype= %d/%s\n", buf, htype, header[htype].tag); 299 /* The following order is defined in the MTA documents. */ 300 switch (htype) { 301 case H_CONT: 302 if (sending) { 303 suppress = sav_suppress; 304 } 305 continue; 306 case H_TCOPY: 307 case H_MIMEVERS: 308 case H_CTYPE: 309 case H_CLEN: 310 if (!sending) { 311 savehdrs(buf,htype); 312 } 313 hptr = hdrlines[htype].head; 314 if (htype == H_CLEN) { 315 clen = atol (hptr->value); 316 } 317 /* 318 * Use values saved in hdrlines[] structure 319 * rather than what was read from tmp file. 320 */ 321 print_from_struct = TRUE; 322 /* FALLTHROUGH */ 323 case H_EOH: 324 case H_AFWDFROM: 325 case H_AFWDCNT: 326 case H_RECEIVED: 327 dumprcv(type, htype,&didrcvlines,&suppress,f); 328 dumpaff(type, htype,&didafflines,&suppress,f); 329 continue; /* next header line */ 330 default: 331 pushrest = (lastc != '\n'); 332 continue; /* next header line */ 333 case FALSE: /* end of header */ 334 break; 335 } 336 337 /* Found the blank line after the headers. */ 338 if (n > 0) { 339 if (fwrite(buf,1,n,f) != n) { 340 sav_errno = errno; 341 return(FALSE); 342 } 343 } 344 345 Dout(pn, 3,", let[%d].text = %s\n", 346 letnum, (let[letnum].text ? "TRUE" : "FALSE")); 347 348 if ((type == TTY) && (let[letnum].text == FALSE) && !pflg) { 349 if (fprintf (f, "\n%s\n", binmsg) < 0) 350 { 351 sav_errno = errno; 352 return(FALSE); 353 } 354 return (TRUE); 355 } 356 357 if (n == 1 && buf[0] == '\n') { 358 n = 0; 359 } 360 break; 361 } 362 363 Dout(pn, 1, "header processed, clen/k/n = %ld/%ld/%d\n", clen, k, n); 364 365 if (clen >= 0) { 366 if (((clen - n) == k) || ((clen - n) == (k - 1))) { 367 k = clen - n; 368 } else { 369 /* probable content-length mismatch. show it ALL! */ 370 Dout(pn, 1, "clen conflict. using k = %ld\n", k); 371 } 372 } 373 374 /* copy balance of message */ 375 if (rtrncont) 376 while (k > 0) { 377 num = ((k < sizeof(buf)) ? k : sizeof(buf)); 378 if ((n = fread (buf, 1, num, tmpf)) <= 0) { 379 Dout(pn, 1, "content-length mismatch. return(FALSE)\n"); 380 return(FALSE); 381 } 382 k -= n; 383 if (fwrite(buf,1,n,f) != n) { 384 sav_errno = errno; 385 return(FALSE); 386 } 387 } 388 389 Dout(pn, 3, "body processed, k=%ld\n", k); 390 391 if (rtrncont && type != ZAP && type != REMOTE) { 392 if (fwrite("\n",1,1,f) != 1) { 393 sav_errno = errno; 394 return(FALSE); 395 } 396 } 397 398 return(TRUE); 399 } 400