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