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
) !=
127 (struct hdrs
*)NULL
) {
128 clen
= atol (hptr
->value
);
132 if (htype
!= FALSE
) {
133 pushrest
= (lastc
!= '\n');
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
) {
148 /* Copy From line appropriately */
149 if (fwrite(buf
,1,n
-1,f
) != n
-1) {
154 if (fwrite(&lastc
,1,1,f
) != 1) {
162 if (fprintf(f
, rmtmsg
, thissys
) < 0)
173 if (fprintf(f
, "\n") < 0)
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
)) {
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)
195 /* Compute Content-Length of what's being */
198 /* Account for H_AFWDFROM, H_AFWDCNT, */
199 /* H_TCOPY, or H_RECEIVED lines which may */
202 sprintf(wbuf
, "%d", affcnt
);
204 + strlen(header
[H_AFWDCNT
].tag
)
208 if ((hptr
= hdrlines
[H_TCOPY
].head
) !=
209 (struct hdrs
*)NULL
) {
211 strlen(hdrlines
[H_TCOPY
].head
->value
);
214 if ((hptr
= hdrlines
[H_RECEIVED
].head
) !=
215 (struct hdrs
*)NULL
) {
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
);
225 if ((hptr
= hdrlines
[H_CTYPE
].head
) !=
226 (struct hdrs
*)NULL
) {
227 i
+= strlen(hdrlines
[H_CTYPE
].head
->value
);
229 if ((hptr
= hdrlines
[H_CLEN
].head
) !=
230 (struct hdrs
*)NULL
) {
231 i
+= strlen(hdrlines
[H_CLEN
].head
->value
);
233 if (fprintf(f
, "%s %ld\n", header
[H_CLEN
].tag
, i
) < 0)
239 if (fprintf(f
, "\n") < 0)
253 /* if not ZAP, copy balance of header */
255 if ((type
!= ZAP
) && rtrncont
)
257 if ((n
> 0) && !suppress
) {
258 if (print_from_struct
== TRUE
) {
259 if (printhdr (type
, htype
, hptr
, f
) < 0) {
263 if (sel_disp(type
, htype
, buf
) >= 0) {
264 if (fwrite(buf
,1,n
,f
) != n
) {
270 if (htype
== H_DATE
) {
271 dumprcv(type
, htype
,&didrcvlines
,&suppress
,f
);
272 dumpaff(type
, htype
,&didafflines
,&suppress
,f
);
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
);
284 num
= ((k
< sizeof(buf
)) ? k
+1 : sizeof(buf
));
285 if (fgets (buf
, num
, tmpf
) == NULL
) {
293 pushrest
= (lastc
!= '\n');
296 sav_suppress
= suppress
;
298 print_from_struct
= FALSE
;
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. */
306 suppress
= sav_suppress
;
316 hptr
= hdrlines
[htype
].head
;
317 if (htype
== H_CLEN
) {
318 clen
= atol (hptr
->value
);
321 * Use values saved in hdrlines[] structure
322 * rather than what was read from tmp file.
324 print_from_struct
= TRUE
;
330 dumprcv(type
, htype
,&didrcvlines
,&suppress
,f
);
331 dumpaff(type
, htype
,&didafflines
,&suppress
,f
);
332 continue; /* next header line */
334 pushrest
= (lastc
!= '\n');
335 continue; /* next header line */
336 case FALSE
: /* end of header */
340 /* Found the blank line after the headers. */
342 if (fwrite(buf
,1,n
,f
) != n
) {
348 Dout(pn
, 3,", let[%d].text = %s\n",
349 letnum
, (let
[letnum
].text
? "TRUE" : "FALSE"));
351 if ((type
== TTY
) && (let
[letnum
].text
== FALSE
) && !pflg
) {
352 if (fprintf (f
, "\n%s\n", binmsg
) < 0)
360 if (n
== 1 && buf
[0] == '\n') {
366 Dout(pn
, 1, "header processed, clen/k/n = %ld/%ld/%d\n", clen
, k
, n
);
369 if (((clen
- n
) == k
) || ((clen
- n
) == (k
- 1))) {
372 /* probable content-length mismatch. show it ALL! */
373 Dout(pn
, 1, "clen conflict. using k = %ld\n", k
);
377 /* copy balance of message */
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");
386 if (fwrite(buf
,1,n
,f
) != n
) {
392 Dout(pn
, 3, "body processed, k=%ld\n", k
);
394 if (rtrncont
&& type
!= ZAP
&& type
!= REMOTE
) {
395 if (fwrite("\n",1,1,f
) != 1) {