dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mail / copylet.c
blob0f51d654e7e6feb7df7da830cfc121acf32c12bd
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "mail.h"
35 NAME
36 copylet - copy a given letter to a file pointer
38 SYNOPSIS
39 int copylet(int letnum, FILE *f, int type)
41 DESCRIPTION
42 Copylet() will copy the letter "letnum" to the
43 given file pointer.
45 letnum -> index into: letter table
46 f -> file pointer to copy file to
47 type -> copy type
49 Returns TRUE on a completely successful copy.
52 int
53 copylet(int letnum, FILE *f, int type)
55 int pos = ftell(f);
56 int rc = xxxcopylet(letnum, f, type);
58 if (fflush(f) != 0)
59 rc = FALSE;
62 * On error, truncate the file to its original position so that a
63 * partial message is not left in the mailbox.
65 if (rc == FALSE)
66 ftruncate(fileno(f), pos);
68 return(rc);
71 int
72 xxxcopylet(int letnum, FILE *f, int type)
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;
96 if (!sending) {
97 /* Clear out any saved header info from previous message */
98 clr_hinfo();
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);
110 if ((n = strlen (buf)) == 0) {
111 k = 0;
112 break;
114 k -= n;
115 lastc = buf[n-1];
116 if (pushrest) {
117 pushrest = (lastc != '\n');
118 continue;
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);
126 if ((hptr = hdrlines[H_CLEN].head) != NULL) {
127 clen = atol (hptr->value);
130 if (type == ZAP) {
131 if (htype != FALSE) {
132 pushrest = (lastc != '\n');
133 continue;
135 /* end of header. Print non-blank line and bail. */
136 Dout(pn, 5, "ZAP end header; n=%d, buf[0] = %d\n", n, buf[0]);
137 if (buf[0] != '\n') {
138 if (fwrite(buf,1,n,f) != n) {
139 sav_errno = errno;
140 return(FALSE);
142 } else {
143 n = 0;
145 break;
147 /* Copy From line appropriately */
148 if (fwrite(buf,1,n-1,f) != n-1) {
149 sav_errno = errno;
150 return(FALSE);
152 if (lastc != '\n') {
153 if (fwrite(&lastc,1,1,f) != 1) {
154 sav_errno = errno;
155 return(FALSE);
157 continue;
159 switch(type) {
160 case REMOTE:
161 if (fprintf(f, rmtmsg, thissys) < 0)
163 sav_errno = errno;
164 return(FALSE);
167 break;
169 case TTY:
170 case ORDINARY:
171 default:
172 if (fprintf(f, "\n") < 0)
174 sav_errno = errno;
175 return(FALSE);
177 break;
179 if ((error > 0) && (dflag == 1)) {
180 Dout(pn, 3, "before gendeliv(), uval = '%s'\n", uval);
181 gendeliv(f, dflag, uval);
182 if (!(ckdlivopts(H_TCOPY, (int*)0) & RETURN)) {
183 rtrncont = 0;
184 } else {
185 /* Account for content-type info */
186 /* of returned msg */
187 if (fprintf(f, "%s %s\n", header[H_CTYPE].tag,
188 (let[letnum].text == TRUE ? "text/plain" : "application/octet-stream")) < 0)
190 sav_errno = errno;
191 return(FALSE);
194 /* Compute Content-Length of what's being */
195 /* returned... */
196 i = k;
197 /* Account for H_AFWDFROM, H_AFWDCNT, */
198 /* H_TCOPY, or H_RECEIVED lines which may */
199 /* be added later */
200 if (affcnt > 0) {
201 sprintf(wbuf, "%d", affcnt);
202 i += (affbytecnt
203 + strlen(header[H_AFWDCNT].tag)
204 + strlen(wbuf) + 2);
206 if (orig_tcopy) {
207 if ((hptr = hdrlines[H_TCOPY].head) !=
208 NULL) {
209 i +=
210 strlen(hdrlines[H_TCOPY].head->value);
213 if ((hptr = hdrlines[H_RECEIVED].head) !=
214 NULL) {
215 i += rcvbytecnt;
217 /* Add in strlen of MIME-Version:, */
218 /* Content-Length: and Content-Type: */
219 /* values for msg being returned... */
220 if ((hptr = hdrlines[H_MIMEVERS].head) !=
221 NULL) {
222 i += strlen(hdrlines[H_MIMEVERS].head->value);
224 if ((hptr = hdrlines[H_CTYPE].head) != NULL) {
225 i += strlen(hdrlines[H_CTYPE].head->value);
227 if ((hptr = hdrlines[H_CLEN].head) != NULL) {
228 i += strlen(hdrlines[H_CLEN].head->value);
230 if (fprintf(f, "%s %ld\n", header[H_CLEN].tag, i) < 0)
232 sav_errno = errno;
233 return(FALSE);
236 if (fprintf(f, "\n") < 0)
238 sav_errno = errno;
239 return(FALSE);
242 if (fflush(f))
244 sav_errno = errno;
245 return(FALSE);
248 break;
250 /* if not ZAP, copy balance of header */
251 n = 0;
252 if ((type != ZAP) && rtrncont)
253 while (k>0 || n>0) {
254 if ((n > 0) && !suppress) {
255 if (print_from_struct == TRUE) {
256 if (printhdr (type, htype, hptr, f) < 0) {
257 return (FALSE);
259 } else {
260 if (sel_disp(type, htype, buf) >= 0) {
261 if (fwrite(buf,1,n,f) != n) {
262 sav_errno = errno;
263 return(FALSE);
267 if (htype == H_DATE) {
268 dumprcv(type, htype,&didrcvlines,&suppress,f);
269 dumpaff(type, htype,&didafflines,&suppress,f);
272 if (k <= 0) {
273 /* Can only get here if k=0 && n>0, which occurs */
274 /* in a message with header lines but no content. */
275 /* If we haven't already done it, force out any */
276 /* H_AFWDFROM or H_RECEIVED lines */
277 dumprcv(type, -1,&didrcvlines,&suppress,f);
278 dumpaff(type, -1,&didafflines,&suppress,f);
279 break;
281 num = ((k < sizeof(buf)) ? k+1 : sizeof(buf));
282 if (fgets (buf, num, tmpf) == NULL) {
283 return (FALSE);
285 n = strlen (buf);
286 k -= n;
287 lastc = buf[n-1];
289 if (pushrest) {
290 pushrest = (lastc != '\n');
291 continue;
293 sav_suppress = suppress;
294 suppress = FALSE;
295 print_from_struct = FALSE;
296 sav_htype = htype;
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;
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);
313 hptr = hdrlines[htype].head;
314 if (htype == H_CLEN) {
315 clen = atol (hptr->value);
318 * Use values saved in hdrlines[] structure
319 * rather than what was read from tmp file.
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;
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);
345 Dout(pn, 3,", let[%d].text = %s\n",
346 letnum, (let[letnum].text ? "TRUE" : "FALSE"));
348 if ((type == TTY) && (let[letnum].text == FALSE) && !pflg) {
349 if (fprintf (f, "\n%s\n", binmsg) < 0)
351 sav_errno = errno;
352 return(FALSE);
354 return (TRUE);
357 if (n == 1 && buf[0] == '\n') {
358 n = 0;
360 break;
363 Dout(pn, 1, "header processed, clen/k/n = %ld/%ld/%d\n", clen, k, n);
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);
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);
382 k -= n;
383 if (fwrite(buf,1,n,f) != n) {
384 sav_errno = errno;
385 return(FALSE);
389 Dout(pn, 3, "body processed, k=%ld\n", k);
391 if (rtrncont && type != ZAP && type != REMOTE) {
392 if (fwrite("\n",1,1,f) != 1) {
393 sav_errno = errno;
394 return(FALSE);
398 return(TRUE);