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
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]
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"
36 copylet - copy a given letter to a file pointer
39 int copylet(int letnum, FILE *f, int type)
42 Copylet() will copy the letter "letnum" to the
45 letnum -> index into: letter table
46 f -> file pointer to copy file to
49 Returns TRUE on a completely successful copy.
53 copylet(int letnum
, FILE *f
, int type
)
56 int rc
= xxxcopylet(letnum
, f
, type
);
62 * On error, truncate the file to its original position so that a
63 * partial message is not left in the mailbox.
66 ftruncate(fileno(f
), pos
);
72 xxxcopylet(int letnum
, FILE *f
, int type
)
74 static char pn
[] = "copylet";
75 char buf
[LSIZE
], lastc
;
80 int rtrncont
= 1; /* True: nondelivery&content included, or regular mail */
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 */
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? */
92 int htype
; /* header type */
93 int sav_htype
; /* Header type of last non-H_CONT header line */
97 /* Clear out any saved header info from previous message */
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
) {
110 if ((n
= strlen (buf
)) == 0) {
117 pushrest
= (lastc
!= '\n');
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
) {
126 if ((hptr
= hdrlines
[H_CLEN
].head
) != NULL
) {
127 clen
= atol (hptr
->value
);
131 if (htype
!= FALSE
) {
132 pushrest
= (lastc
!= '\n');
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
) {
147 /* Copy From line appropriately */
148 if (fwrite(buf
,1,n
-1,f
) != n
-1) {
153 if (fwrite(&lastc
,1,1,f
) != 1) {
161 if (fprintf(f
, rmtmsg
, thissys
) < 0)
172 if (fprintf(f
, "\n") < 0)
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
)) {
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)
194 /* Compute Content-Length of what's being */
197 /* Account for H_AFWDFROM, H_AFWDCNT, */
198 /* H_TCOPY, or H_RECEIVED lines which may */
201 sprintf(wbuf
, "%d", affcnt
);
203 + strlen(header
[H_AFWDCNT
].tag
)
207 if ((hptr
= hdrlines
[H_TCOPY
].head
) !=
210 strlen(hdrlines
[H_TCOPY
].head
->value
);
213 if ((hptr
= hdrlines
[H_RECEIVED
].head
) !=
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
) !=
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)
236 if (fprintf(f
, "\n") < 0)
250 /* if not ZAP, copy balance of header */
252 if ((type
!= ZAP
) && rtrncont
)
254 if ((n
> 0) && !suppress
) {
255 if (print_from_struct
== TRUE
) {
256 if (printhdr (type
, htype
, hptr
, f
) < 0) {
260 if (sel_disp(type
, htype
, buf
) >= 0) {
261 if (fwrite(buf
,1,n
,f
) != n
) {
267 if (htype
== H_DATE
) {
268 dumprcv(type
, htype
,&didrcvlines
,&suppress
,f
);
269 dumpaff(type
, htype
,&didafflines
,&suppress
,f
);
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
);
281 num
= ((k
< sizeof(buf
)) ? k
+1 : sizeof(buf
));
282 if (fgets (buf
, num
, tmpf
) == NULL
) {
290 pushrest
= (lastc
!= '\n');
293 sav_suppress
= suppress
;
295 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. */
303 suppress
= sav_suppress
;
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
;
327 dumprcv(type
, htype
,&didrcvlines
,&suppress
,f
);
328 dumpaff(type
, htype
,&didafflines
,&suppress
,f
);
329 continue; /* next header line */
331 pushrest
= (lastc
!= '\n');
332 continue; /* next header line */
333 case FALSE
: /* end of header */
337 /* Found the blank line after the headers. */
339 if (fwrite(buf
,1,n
,f
) != n
) {
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)
357 if (n
== 1 && buf
[0] == '\n') {
363 Dout(pn
, 1, "header processed, clen/k/n = %ld/%ld/%d\n", clen
, k
, n
);
366 if (((clen
- n
) == k
) || ((clen
- n
) == (k
- 1))) {
369 /* probable content-length mismatch. show it ALL! */
370 Dout(pn
, 1, "clen conflict. using k = %ld\n", k
);
374 /* copy balance of message */
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");
383 if (fwrite(buf
,1,n
,f
) != n
) {
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) {