0
|
1 #ifndef lint
|
|
2 static char sccsid[] = "@(#)spost.c 1.6 (Berkeley) 11/2/85";
|
|
3 #endif
|
|
4 #ifndef lint
|
12
|
5 static char ident[] = "@(#)$Id: spost.c,v 1.1.1.1 2005/04/18 14:46:07 kono Exp $";
|
0
|
6 #endif /* lint */
|
|
7
|
|
8 /* spost.c - feed messages to sendmail */
|
|
9 /*
|
|
10 * (This is a simpler, faster, replacement for "post" for use when "sendmail"
|
|
11 * is the transport system)
|
|
12 */
|
|
13
|
|
14 #include <ctype.h>
|
|
15 #include <stdio.h>
|
|
16 #include <signal.h>
|
|
17 #include "../h/mh.h"
|
|
18 #include "../h/addrsbr.h"
|
|
19 #include "../h/aliasbr.h"
|
|
20 #include "../h/dropsbr.h"
|
|
21 #include "../zotnet/tws.h"
|
|
22 #ifdef LOCALE
|
|
23 #include <locale.h>
|
|
24 #endif
|
|
25 #ifdef UNISTD
|
|
26 #include <unistd.h>
|
|
27 #endif
|
|
28
|
|
29 extern char *getfullname (), *getusr ();
|
|
30 extern char *sendmail;
|
|
31
|
|
32
|
|
33 #define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : c)
|
|
34
|
|
35 #define MAX_SM_FIELD 1476 /* < largest hdr field sendmail will accept */
|
|
36 #define FCCS 10 /* max number of fccs allowed */
|
|
37
|
|
38 /* */
|
|
39
|
|
40 struct swit switches[] = {
|
|
41 #define FILTSW 0
|
|
42 "filter filterfile", 0,
|
|
43 #define NFILTSW 1
|
|
44 "nofilter", 0,
|
|
45
|
|
46 #define FRMTSW 2
|
|
47 "format", 0,
|
|
48 #define NFRMTSW 3
|
|
49 "noformat", 0,
|
|
50
|
|
51 #define REMVSW 4
|
|
52 "remove", 0,
|
|
53 #define NREMVSW 5
|
|
54 "noremove", 0,
|
|
55
|
|
56 #define VERBSW 6
|
|
57 "verbose", 0,
|
|
58 #define NVERBSW 7
|
|
59 "noverbose", 0,
|
|
60
|
|
61 #define WATCSW 8
|
|
62 "watch", 0,
|
|
63 #define NWATCSW 9
|
|
64 "nowatch", 0,
|
|
65
|
|
66 #define HELPSW 10
|
|
67 "help", 4,
|
|
68
|
|
69 #define DEBUGSW 11
|
|
70 "debug", -5,
|
|
71
|
|
72 #define DISTSW 12
|
|
73 "dist", -4, /* interface from dist */
|
|
74
|
|
75 #define BACKSW 13
|
|
76 "backup", 0,
|
|
77 #define NBACKSW 14
|
|
78 "nobackup", 0,
|
|
79
|
|
80 #define CHKSW 15
|
|
81 "check", -5, /* interface from whom */
|
|
82 #define NCHKSW 16
|
|
83 "nocheck", -7, /* interface from whom */
|
|
84 #define WHOMSW 17
|
|
85 "whom", -4, /* interface from whom */
|
|
86
|
|
87 #define PUSHSW 18 /* fork to sendmail then exit */
|
|
88 "push", -4,
|
|
89 #define NPUSHSW 19 /* exec sendmail */
|
|
90 "nopush", -6,
|
|
91
|
|
92 #define ALIASW 20
|
|
93 "alias aliasfile", 0,
|
|
94 #define NALIASW 21
|
|
95 "noalias", 0,
|
|
96
|
|
97 #define WIDTHSW 22
|
|
98 "width columns", 0,
|
|
99
|
|
100 #define LIBSW 23
|
|
101 "library directory", -7,
|
|
102
|
|
103 #define ANNOSW 24
|
|
104 "idanno number", -6,
|
|
105
|
|
106 #ifdef MIME_HEADERS
|
|
107 #define HENCDSW 25
|
|
108 "hencode", 0,
|
|
109 #define NHENCDSW 26
|
|
110 "nohencode", 0,
|
|
111 #endif /* MIME_HEADERS */
|
|
112
|
|
113 NULL, 0
|
|
114 };
|
|
115
|
|
116 /* */
|
|
117
|
|
118 struct headers {
|
|
119 char *value;
|
|
120
|
|
121 unsigned int flags;
|
|
122 #define HNOP 0x0000 /* just used to keep .set around */
|
|
123 #define HBAD 0x0001 /* bad header - don't let it through */
|
|
124 #define HADR 0x0002 /* header has an address field */
|
|
125 #define HSUB 0x0004 /* Subject: header */
|
|
126 #define HTRY 0x0008 /* try to send to addrs on header */
|
|
127 #define HBCC 0x0010 /* don't output this header */
|
|
128 #define HMNG 0x0020 /* mung this header */
|
|
129 #define HNGR 0x0040 /* no groups allowed in this header */
|
|
130 #define HFCC 0x0080 /* FCC: type header */
|
|
131 #define HNIL 0x0100 /* okay for this header not to have addrs */
|
|
132 #define HIGN 0x0200 /* ignore this header */
|
|
133
|
|
134 unsigned int set;
|
|
135 #define MFRM 0x0001 /* we've seen a From: */
|
|
136 #define MDAT 0x0002 /* we've seen a Date: */
|
|
137 #define MRFM 0x0004 /* we've seen a Resent-From: */
|
|
138 #define MVIS 0x0008 /* we've seen sighted addrs */
|
|
139 #define MINV 0x0010 /* we've seen blind addrs */
|
|
140 #define MRDT 0x0020 /* we've seen a Resent-Date: */
|
|
141 };
|
|
142
|
|
143 /* */
|
|
144
|
|
145 static struct headers NHeaders[] = {
|
|
146 "Return-Path", HBAD, 0,
|
|
147 "Received", HBAD, 0,
|
|
148 "Reply-To", HADR | HNGR, 0,
|
|
149 "From", HADR | HNGR, MFRM,
|
|
150 "Sender", HADR | HBAD, 0,
|
|
151 "Date", HNOP, MDAT,
|
|
152 "Subject", HSUB, 0,
|
|
153 "To", HADR | HTRY, MVIS,
|
|
154 "cc", HADR | HTRY, MVIS,
|
|
155 "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
|
|
156 "Message-Id", HBAD, 0,
|
|
157 "Fcc", HFCC, 0,
|
|
158
|
|
159 NULL
|
|
160 };
|
|
161
|
|
162 static struct headers RHeaders[] = {
|
|
163 "Resent-Reply-To", HADR | HNGR, 0,
|
|
164 "Resent-From", HADR | HNGR, MRFM,
|
|
165 "Resent-Sender", HADR | HBAD, 0,
|
|
166 "Resent-Date", HNOP, MRDT,
|
|
167 "Resent-Subject", HSUB, 0,
|
|
168 "Resent-To", HADR | HTRY, MVIS,
|
|
169 "Resent-cc", HADR | HTRY, MVIS,
|
|
170 "Resent-Bcc", HADR | HTRY | HBCC, MINV,
|
|
171 "Resent-Message-Id", HBAD, 0,
|
|
172 "Resent-Fcc", HFCC, 0,
|
|
173 "Reply-To", HADR, 0,
|
|
174 "Fcc", HIGN, 0,
|
|
175
|
|
176 NULL
|
|
177 };
|
|
178
|
|
179 /* */
|
|
180
|
|
181
|
|
182 static short fccind = 0; /* index into fccfold[] */
|
|
183
|
|
184 static int badmsg = 0; /* message has bad semantics */
|
|
185 static int verbose = 0; /* spell it out */
|
|
186 static int debug = 0; /* debugging post */
|
|
187 static int rmflg = 1; /* remove temporary file when done */
|
|
188 static int watch = 0; /* watch the delivery process */
|
|
189 static int backflg = 0; /* rename input file as *.bak when done */
|
|
190 static int whomflg = 0; /* if just checking addresses */
|
|
191 static int pushflg = 0; /* if going to fork to sendmail */
|
|
192 static int aliasflg = -1; /* if going to process aliases */
|
|
193 static int outputlinelen=72;
|
|
194 #ifdef MIME_HEADERS
|
|
195 static int hencode = -1; /* encode header in RFC-2047 style */
|
|
196 #endif /* MIME_HEADERS */
|
|
197
|
|
198 static unsigned msgflags = 0; /* what we've seen */
|
|
199
|
|
200 static enum {
|
|
201 normal, resent
|
|
202 } msgstate = normal;
|
|
203
|
|
204 static char tmpfil[] = "/tmp/pstXXXXXX";
|
|
205
|
|
206 static char from[BUFSIZ]; /* my network address */
|
|
207 static char signature[BUFSIZ]; /* my signature */
|
|
208 static char *filter = NULL; /* the filter for BCC'ing */
|
|
209 static char *subject = NULL; /* the subject field for BCC'ing */
|
|
210 static char *fccfold[FCCS]; /* foldernames for FCC'ing */
|
|
211
|
|
212 static struct headers *hdrtab; /* table for the message we're doing */
|
|
213 static FILE *out; /* output (temp) file */
|
|
214
|
16
|
215 static void putfmt(), start_headers(), finish_headers(), putadr(),
|
0
|
216 insert_fcc();
|
16
|
217 static void file(), fcc();
|
0
|
218 static int get_header(), putone();
|
|
219 /* MAIN */
|
|
220
|
|
221 /* ARGSUSED */
|
|
222
|
|
223 main (argc, argv)
|
|
224 int argc;
|
|
225 char *argv[];
|
|
226 {
|
|
227 int state,
|
|
228 i,
|
|
229 pid,
|
|
230 compnum;
|
|
231 char *cp,
|
|
232 *msg = NULL,
|
|
233 **argp = argv + 1,
|
|
234 *sargv[16],
|
|
235 buf[BUFSIZ],
|
|
236 name[NAMESZ],
|
|
237 *arguments[MAXARGS];
|
|
238 FILE * in;
|
|
239
|
|
240 #ifdef LOCALE
|
|
241 setlocale(LC_ALL, "");
|
|
242 #endif
|
|
243 #ifdef JAPAN
|
|
244 ml_init();
|
|
245 #endif /* JAPAN */
|
|
246 invo_name = r1bindex (argv[0], '/');
|
|
247 mts_init (invo_name);
|
|
248 if ((cp = m_find (invo_name)) != NULL) {
|
|
249 argp = copyip (brkstring (cp, " ", "\n"), arguments);
|
|
250 (void) copyip (argv+1, argp);
|
|
251 argp = arguments;
|
|
252 }
|
|
253
|
|
254 /* */
|
|
255
|
|
256 while (cp = *argp++) {
|
|
257 if (*cp == '-')
|
|
258 switch (smatch (++cp, switches)) {
|
|
259 case AMBIGSW:
|
|
260 ambigsw (cp, switches);
|
|
261 done (1);
|
|
262 case UNKWNSW:
|
|
263 adios (NULLCP, "-%s unknown", cp);
|
|
264 case HELPSW:
|
|
265 (void)sprintf (buf, "%s [switches] file", invo_name);
|
|
266 help (buf, switches);
|
|
267 done (1);
|
|
268
|
|
269 case DEBUGSW:
|
|
270 debug++;
|
|
271 continue;
|
|
272
|
|
273 case DISTSW:
|
|
274 msgstate = resent;
|
|
275 continue;
|
|
276
|
|
277 case WHOMSW:
|
|
278 whomflg++;
|
|
279 continue;
|
|
280
|
|
281 case FILTSW:
|
|
282 if (!(filter = *argp++) || *filter == '-')
|
|
283 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
284 continue;
|
|
285 case NFILTSW:
|
|
286 filter = NULL;
|
|
287 continue;
|
|
288
|
|
289 case REMVSW:
|
|
290 rmflg++;
|
|
291 continue;
|
|
292 case NREMVSW:
|
|
293 rmflg = 0;
|
|
294 continue;
|
|
295
|
|
296 case BACKSW:
|
|
297 backflg++;
|
|
298 continue;
|
|
299 case NBACKSW:
|
|
300 backflg = 0;
|
|
301 continue;
|
|
302
|
|
303 case VERBSW:
|
|
304 verbose++;
|
|
305 continue;
|
|
306 case NVERBSW:
|
|
307 verbose = 0;
|
|
308 continue;
|
|
309
|
|
310 case WATCSW:
|
|
311 watch++;
|
|
312 continue;
|
|
313 case NWATCSW:
|
|
314 watch = 0;
|
|
315 continue;
|
|
316
|
|
317 case PUSHSW:
|
|
318 pushflg++;
|
|
319 continue;
|
|
320 case NPUSHSW:
|
|
321 pushflg = 0;
|
|
322 continue;
|
|
323
|
|
324 case ALIASW:
|
|
325 if (!(cp = *argp++) || *cp == '-')
|
|
326 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
327 if (aliasflg < 0)
|
|
328 (void) alias (AliasFile);/* load default aka's */
|
|
329 aliasflg = 1;
|
|
330 if ((state = alias(cp)) != AK_OK)
|
|
331 adios (NULLCP, "aliasing error in file %s - %s",
|
|
332 cp, akerror(state) );
|
|
333 continue;
|
|
334 case NALIASW:
|
|
335 aliasflg = 0;
|
|
336 continue;
|
|
337
|
|
338 case WIDTHSW:
|
|
339 if (!(cp = *argp++) || *cp == '-')
|
|
340 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
341 outputlinelen = atoi (cp);
|
|
342 if (outputlinelen <= 10)
|
|
343 outputlinelen = 72;
|
|
344 continue;
|
|
345
|
|
346 case LIBSW:
|
|
347 case ANNOSW:
|
|
348 /* -library & -idanno switch ignored */
|
|
349 if (!(cp = *argp++) || *cp == '-')
|
|
350 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
351 continue;
|
|
352 #ifdef MIME_HEADERS
|
|
353 case HENCDSW:
|
|
354 hencode = 1;
|
|
355 continue;
|
|
356 case NHENCDSW:
|
|
357 hencode = 0;
|
|
358 continue;
|
|
359 #endif /* MIME_HEADERS */
|
|
360 }
|
|
361 if (msg)
|
|
362 adios (NULLCP, "only one message at a time!");
|
|
363 else
|
|
364 msg = cp;
|
|
365 }
|
|
366
|
|
367 /* */
|
|
368
|
|
369 if (aliasflg < 0)
|
|
370 (void) alias (AliasFile); /* load default aka's */
|
|
371
|
|
372 if (!msg)
|
|
373 adios (NULLCP, "usage: %s [switches] file", invo_name);
|
|
374
|
|
375 if ((in = fopen (msg, "r")) == NULL)
|
|
376 adios (msg, "unable to open");
|
|
377
|
|
378 #ifdef MIME_HEADERS
|
|
379 if (hencode == -1) {
|
|
380 hencode = 0;
|
|
381 for (state = FLD;;) {
|
|
382 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
|
|
383 case FLD:
|
|
384 case FLDEOF:
|
|
385 case FLDPLUS:
|
|
386 if (uleq (name, "MIME-Version")) {
|
|
387 hencode = 1;
|
|
388 break;
|
|
389 }
|
|
390 continue;
|
|
391
|
|
392 default:
|
|
393 break;
|
|
394 }
|
|
395 break;
|
|
396 }
|
|
397 (void) fseek (in, 0L, 0);
|
|
398 }
|
|
399 #endif /* MIME_HEADERS */
|
|
400
|
|
401 start_headers ();
|
|
402 if (debug) {
|
|
403 verbose++;
|
|
404 out = stdout;
|
|
405 }
|
|
406 else {
|
|
407 (void)mktemp (tmpfil);
|
|
408 if ((out = fopen (tmpfil, "w")) == NULL)
|
|
409 adios (tmpfil, "unable to create");
|
|
410 (void)chmod (tmpfil, 0600);
|
|
411 }
|
|
412
|
|
413 hdrtab = (msgstate == normal) ? NHeaders : RHeaders;
|
|
414
|
|
415 for (compnum = 1, state = FLD;;) {
|
|
416 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
|
|
417 #if defined(JAPAN) || defined(MIME_HEADERS)
|
|
418 case FLD:
|
|
419 case FLDEOF:
|
|
420 case FLDPLUS:
|
|
421 compnum++;
|
|
422 cp = add (buf, NULLCP);
|
|
423 while (state == FLDPLUS) {
|
|
424 state = m_getfld (state, name, buf, sizeof buf, in);
|
|
425 cp = add (buf, cp);
|
|
426 }
|
|
427 putfmt (name, cp, out);
|
|
428 free (cp);
|
|
429 continue;
|
|
430 #else /* JAPAN || MIME_HEADERS */
|
|
431 case FLD:
|
|
432 compnum++;
|
|
433 putfmt (name, buf, out);
|
|
434 continue;
|
|
435
|
|
436 case FLDPLUS:
|
|
437 compnum++;
|
|
438 cp = add (buf, cp);
|
|
439 while (state == FLDPLUS) {
|
|
440 state = m_getfld (state, name, buf, sizeof buf, in);
|
|
441 cp = add (buf, cp);
|
|
442 }
|
|
443 putfmt (name, cp, out);
|
|
444 free (cp);
|
|
445 continue;
|
|
446 #endif /* JAPAN || MIME_HEADERS */
|
|
447
|
|
448 case BODY:
|
|
449 finish_headers (out);
|
|
450 fprintf (out, "\n%s", buf);
|
|
451 if(whomflg == 0)
|
|
452 while (state == BODY) {
|
|
453 state = m_getfld (state, name, buf, sizeof buf, in);
|
|
454 fputs (buf, out);
|
|
455 }
|
|
456 break;
|
|
457
|
|
458 case FILEEOF:
|
|
459 finish_headers (out);
|
|
460 break;
|
|
461
|
|
462 case LENERR:
|
|
463 case FMTERR:
|
|
464 adios (NULLCP, "message format error in component #%d",
|
|
465 compnum);
|
|
466
|
|
467 default:
|
|
468 adios (NULLCP, "getfld() returned %d", state);
|
|
469 }
|
|
470 break;
|
|
471 }
|
|
472
|
|
473 /* */
|
|
474
|
|
475 (void)fclose (in);
|
|
476 if (backflg && !whomflg) {
|
|
477 (void) strcpy (buf, m_backup (msg));
|
|
478 if (rename (msg, buf) == NOTOK)
|
|
479 advise (buf, "unable to rename %s to", msg);
|
|
480 }
|
|
481
|
|
482 if (debug) {
|
|
483 done (0);
|
|
484 }
|
|
485 else
|
|
486 (void)fclose (out);
|
|
487
|
|
488 file (tmpfil);
|
|
489
|
|
490 /*
|
|
491 * re-open the temp file, unlink it and exec sendmail, giving it
|
|
492 * the msg temp file as std in.
|
|
493 */
|
|
494 if ( freopen( tmpfil, "r", stdin) == NULL)
|
|
495 adios (tmpfil, "can't reopen for sendmail");
|
|
496 if (rmflg)
|
|
497 (void)unlink (tmpfil);
|
|
498
|
|
499 argp = sargv;
|
|
500 *argp++ = "send-mail";
|
|
501 *argp++ = "-m"; /* send to me too */
|
|
502 *argp++ = "-t"; /* read msg for recipients */
|
|
503 *argp++ = "-i"; /* don't stop on "." */
|
|
504 if (whomflg)
|
|
505 *argp++ = "-bv";
|
|
506 if (watch || verbose)
|
|
507 *argp++ = "-v";
|
|
508 *argp = NULL;
|
|
509
|
|
510 if (pushflg && !(watch || verbose)) {
|
|
511 /* fork to a child to run sendmail */
|
|
512 for (i=0; (pid = vfork()) == NOTOK && i < 5; i++)
|
|
513 sleep(5);
|
|
514 switch (pid) {
|
|
515 case NOTOK:
|
|
516 fprintf (verbose ? stdout : stderr, "%s: can't fork to %s\n",
|
|
517 invo_name, sendmail);
|
|
518 exit(-1);
|
|
519 case OK:
|
|
520 /* we're the child .. */
|
|
521 break;
|
|
522 default:
|
|
523 exit(0);
|
|
524 }
|
|
525 }
|
|
526 execv ( sendmail, sargv);
|
|
527 adios ( sendmail, "can't exec");
|
|
528 }
|
|
529
|
|
530 /* DRAFT GENERATION */
|
|
531
|
16
|
532 static void putfmt (name, str, out)
|
0
|
533 char *name,
|
|
534 *str;
|
|
535 FILE * out;
|
|
536 {
|
|
537 int count,
|
|
538 grp,
|
|
539 i,
|
|
540 keep;
|
|
541 char *cp,
|
|
542 *pp,
|
|
543 *qp,
|
|
544 #ifdef MIME_HEADERS
|
|
545 *origstr,
|
|
546 #endif /* MIME_HEADERS */
|
|
547 namep[BUFSIZ];
|
|
548 struct mailname *mp,
|
|
549 *np;
|
|
550 struct headers *hdr;
|
|
551
|
|
552 while (*str == ' ' || *str == '\t')
|
|
553 str++;
|
|
554
|
|
555 #ifdef MIME_HEADERS
|
|
556 if (hencode) {
|
|
557 char *ep;
|
|
558 if ((ep = malloc((unsigned)strlen(str)*10+1)) == NULL)
|
|
559 adios(NULLCP, "out of memory");
|
|
560 #ifdef JAPAN
|
|
561 (void) ml_conv(str);
|
|
562 #endif /* JAPAN */
|
|
563 (void) exthdr_encode(str, ep, strlen(name)+2, name);
|
|
564 origstr = str;
|
|
565 str = ep;
|
|
566 }
|
|
567 #endif /* MIME_HEADERS */
|
|
568
|
|
569 if ((i = get_header (name, hdrtab)) == NOTOK) {
|
|
570 fprintf (out, "%s: %s", name, str);
|
|
571 return;
|
|
572 }
|
|
573
|
|
574 hdr = &hdrtab[i];
|
|
575 if (hdr -> flags & HIGN)
|
|
576 return;
|
|
577 if (hdr -> flags & HBAD) {
|
|
578 advise (NULLCP, "illegal header line -- %s:", name);
|
|
579 badmsg++;
|
|
580 return;
|
|
581 }
|
|
582 msgflags |= hdr -> set;
|
|
583
|
|
584 if (hdr -> flags & HSUB)
|
|
585 subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
|
|
586
|
|
587 if (hdr -> flags & HFCC) {
|
|
588 if (cp = rindex (str, '\n'))
|
|
589 *cp = 0;
|
|
590 for (cp = pp = str; cp = index (pp, ','); pp = cp) {
|
|
591 *cp++ = 0;
|
|
592 insert_fcc (hdr, pp);
|
|
593 }
|
|
594 insert_fcc (hdr, pp);
|
|
595 return;
|
|
596 }
|
|
597
|
|
598 #ifdef notdef
|
|
599 if (hdr -> flags & HBCC) {
|
|
600 insert_bcc(str);
|
|
601 return;
|
|
602 }
|
|
603 #endif /* notdef */
|
|
604
|
|
605 if (*str != '\n' && *str != '\0')
|
|
606 if (aliasflg && hdr->flags & HTRY) {
|
|
607 /* this header contains address(es) that we have to do
|
|
608 * alias expansion on. Because of the saved state in
|
|
609 * getname we have to put all the addresses into a list.
|
|
610 * We then let putadr munch on that list, possibly
|
|
611 * expanding aliases.
|
|
612 */
|
|
613 register struct mailname *f = 0;
|
|
614 register struct mailname *mp = 0;
|
|
615
|
|
616 #ifdef MIME_HEADERS
|
|
617 if (hencode)
|
|
618 /* encode again after format */
|
|
619 (void) exthdr_decode(origstr, str);
|
|
620 #endif /* MIME_HEADERS */
|
|
621
|
|
622 while (cp = getname( str ) ) {
|
|
623 mp = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
|
|
624 if (f == 0) {
|
|
625 f = mp;
|
|
626 mp->m_next = mp;
|
|
627 } else {
|
|
628 mp->m_next = f->m_next;
|
|
629 f->m_next = mp;
|
|
630 f = mp;
|
|
631 }
|
|
632 }
|
|
633 f = mp->m_next; mp->m_next = 0;
|
|
634 putadr( name, f );
|
|
635 } else {
|
|
636 fprintf (out, "%s: %s", name, str );
|
|
637 }
|
|
638 }
|
|
639
|
|
640 /* */
|
|
641
|
16
|
642 static void
|
0
|
643 start_headers ()
|
|
644 {
|
|
645 char *cp;
|
|
646 char sigbuf[BUFSIZ];
|
|
647
|
|
648 (void)strcpy( from, getusr() );
|
|
649
|
|
650 if ((cp = getfullname ()) && *cp) {
|
|
651 (void)strcpy (sigbuf, cp);
|
|
652 (void)sprintf (signature, "%s <%s>", sigbuf, from);
|
|
653 #ifdef MIME_HEADERS
|
|
654 if (hencode) {
|
|
655 char *ep;
|
|
656 #ifdef JAPAN
|
|
657 (void) ml_conv(signature);
|
|
658 #endif /* JAPAN */
|
|
659 ep = getcpy (signature);
|
|
660 (void) exthdr_encode (ep, signature, 5, "From");
|
|
661 free(ep);
|
|
662 }
|
|
663 #endif /* MIME_HEADERS */
|
|
664 }
|
|
665 else
|
|
666 (void)sprintf (signature, "%s", from);
|
|
667 }
|
|
668
|
|
669 /* */
|
|
670
|
16
|
671 static void
|
0
|
672 finish_headers (out)
|
|
673 FILE * out;
|
|
674 {
|
|
675 switch (msgstate) {
|
|
676 case normal:
|
|
677 if (!(msgflags & MDAT))
|
|
678 fprintf (out, "Date: %s\n", dtimenow ());
|
|
679 if (msgflags & MFRM)
|
|
680 fprintf (out, "Sender: %s\n", from);
|
|
681 else
|
|
682 fprintf (out, "From: %s\n", signature);
|
|
683 #ifdef notdef
|
|
684 if (!(msgflags & MVIS))
|
|
685 fprintf (out, "Bcc: Blind Distribution List: ;\n");
|
|
686 #endif /* notdef */
|
|
687 break;
|
|
688
|
|
689 case resent:
|
|
690 if (!(msgflags & MRDT))
|
|
691 fprintf (out, "Resent-Date: %s\n", dtimenow());
|
|
692 if (msgflags & MRFM)
|
|
693 fprintf (out, "Resent-Sender: %s\n", from);
|
|
694 else
|
|
695 fprintf (out, "Resent-From: %s\n", signature);
|
|
696 #ifdef notdef
|
|
697 if (!(msgflags & MVIS))
|
|
698 fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
|
|
699 #endif /* notdef */
|
|
700 break;
|
|
701 }
|
|
702
|
|
703 if (badmsg)
|
|
704 adios (NULLCP, "re-format message and try again");
|
|
705 }
|
|
706
|
|
707 /* */
|
|
708
|
|
709 static int
|
|
710 get_header (header, table)
|
|
711 char *header;
|
|
712 struct headers *table;
|
|
713 {
|
|
714 struct headers *h;
|
|
715
|
|
716 for (h = table; h -> value; h++)
|
|
717 if (uleq (header, h -> value))
|
|
718 return (h - table);
|
|
719
|
|
720 return NOTOK;
|
|
721 }
|
|
722
|
|
723 /* */
|
|
724
|
|
725 /* output the address list for header "name". The address list
|
|
726 * is a linked list of mailname structs. "nl" points to the head
|
|
727 * of the list. Alias substitution should be done on nl.
|
|
728 */
|
16
|
729 static void putadr (name, nl)
|
0
|
730 char *name;
|
|
731 struct mailname *nl;
|
|
732 {
|
|
733 register struct mailname *mp, *mp2;
|
|
734 register int linepos;
|
|
735 register char *cp;
|
|
736 int namelen;
|
|
737
|
|
738 fprintf (out, "%s: ", name);
|
|
739 namelen = strlen(name) + 2;
|
|
740 linepos = namelen;
|
|
741
|
|
742 for (mp = nl; mp; ) {
|
|
743 if (linepos > MAX_SM_FIELD) {
|
|
744 fprintf (out, "\n%s: ", name);
|
|
745 linepos = namelen;
|
|
746 }
|
|
747 if (mp->m_nohost) {
|
|
748 /* a local name - see if it's an alias */
|
|
749 cp = akvalue(mp->m_mbox);
|
|
750 if (strcmp(cp, mp->m_mbox) == 0)
|
|
751 /* wasn't an alias - use what the user typed */
|
|
752 linepos = putone( mp->m_text, linepos, namelen );
|
|
753 else {
|
|
754 /* an alias - expand it */
|
|
755 while (cp = getname(cp) ) {
|
|
756 if (linepos > MAX_SM_FIELD) {
|
|
757 fprintf (out, "\n%s: ", name);
|
|
758 linepos = namelen;
|
|
759 }
|
|
760 mp2 = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
|
|
761 if (akvisible()) {
|
|
762 mp2->m_pers = getcpy(mp->m_mbox);
|
|
763 linepos = putone( adrformat(mp2), linepos, namelen );
|
|
764 } else {
|
|
765 linepos = putone( mp2->m_text, linepos, namelen );
|
|
766 }
|
|
767 mnfree( mp2 );
|
|
768 }
|
|
769 }
|
|
770 } else {
|
|
771 /* not a local name - use what the user typed */
|
|
772 linepos = putone( mp->m_text, linepos, namelen );
|
|
773 }
|
|
774 mp2 = mp;
|
|
775 mp = mp->m_next;
|
|
776 mnfree( mp2 );
|
|
777 }
|
|
778 putc( '\n', out );
|
|
779 }
|
|
780
|
|
781 static int putone ( adr, pos, indent )
|
|
782 register char *adr;
|
|
783 register int pos;
|
|
784 int indent;
|
|
785 {
|
|
786 register int len;
|
|
787 static int linepos;
|
|
788 #ifdef MIME_HEADERS
|
|
789 char name[BUFSIZ], *ep;
|
|
790
|
|
791 if (hencode) {
|
|
792 if ((ep = malloc((unsigned)strlen(adr)*10+1)) == NULL)
|
|
793 adios(NULLCP, "out of memory");
|
|
794 sprintf(name, "%*s", indent, ""); /* dummy */
|
|
795 (void) exthdr_encode(adr, ep, pos, name);
|
|
796 len = strlen(ep);
|
|
797 } else
|
|
798 #endif /* MIME_HEADERS */
|
|
799 len = strlen( adr );
|
|
800 if (pos == indent)
|
|
801 linepos = pos;
|
|
802 else if ( linepos+len > outputlinelen ) {
|
|
803 fprintf ( out, ",\n%*s", indent, "");
|
|
804 #ifdef MIME_HEADERS
|
|
805 if (hencode) {
|
|
806 (void) exthdr_encode(adr, ep, linepos, name);
|
|
807 len = strlen(ep);
|
|
808 }
|
|
809 #endif /* MIME_HEADERS */
|
|
810 linepos = indent;
|
|
811 pos += indent + 2;
|
|
812 }
|
|
813 else {
|
|
814 fputs( ", ", out );
|
|
815 linepos += 2;
|
|
816 pos += 2;
|
|
817 }
|
|
818 #ifdef MIME_HEADERS
|
|
819 if (hencode) {
|
|
820 char *p;
|
|
821 fputs(ep, out);
|
|
822 linepos = (p = rindex(ep, '\n')) ? (ep + len) - (p+1) : linepos + len;
|
|
823 free(ep);
|
|
824 } else {
|
|
825 fputs(adr, out);
|
|
826 linepos += len;
|
|
827 }
|
|
828 #else /* MIME_HEADERS */
|
|
829 fputs( adr, out );
|
|
830
|
|
831 linepos += len;
|
|
832 #endif /* MIME_HEADERS */
|
|
833 return (pos+len);
|
|
834 }
|
|
835
|
|
836 /* */
|
|
837
|
16
|
838 static void insert_fcc (hdr, pp)
|
0
|
839 struct headers *hdr;
|
|
840 char *pp;
|
|
841 {
|
|
842 char *cp;
|
|
843
|
|
844 for (cp = pp; isspace (*cp); cp++)
|
|
845 continue;
|
|
846 for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
|
|
847 continue;
|
|
848 if (pp >= cp)
|
|
849 *++pp = 0;
|
|
850 if (*cp == 0)
|
|
851 return;
|
|
852
|
|
853 if (fccind >= FCCS)
|
|
854 adios (NULLCP, "too many %ss", hdr -> value);
|
|
855 fccfold[fccind++] = getcpy (cp);
|
|
856 }
|
|
857
|
|
858 #ifdef notdef
|
|
859 /* BCC GENERATION */
|
|
860
|
16
|
861 static void make_bcc_file () {
|
0
|
862 int fd,
|
|
863 i,
|
|
864 child_id,
|
|
865 status;
|
|
866 char *vec[6];
|
|
867 FILE * in, *out;
|
|
868
|
|
869 (void)mktemp (bccfil);
|
|
870 if ((out = fopen (bccfil, "w")) == NULL)
|
|
871 adios (bccfil, "unable to create");
|
|
872 (void)chmod (bccfil, 0600);
|
|
873
|
|
874 fprintf (out, "Date: %s\n", dtimenow ());
|
|
875 fprintf (out, "From: %s\n", signature);
|
|
876 if (subject)
|
|
877 fprintf (out, "Subject: %s", subject);
|
|
878 fprintf (out, "BCC:\n\n------- Blind-Carbon-Copy\n\n");
|
|
879 (void)fflush (out);
|
|
880
|
|
881 if (filter == NULL) {
|
|
882 if ((fd = open (tmpfil, 0)) == NOTOK)
|
|
883 adios (NULLCP, "unable to re-open");
|
|
884 cpydgst (fd, fileno (out), tmpfil, bccfil);
|
|
885 close (fd);
|
|
886 }
|
|
887 else {
|
|
888 vec[0] = r1bindex (mhlproc, '/');
|
|
889
|
|
890 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
|
|
891 sleep (5);
|
|
892 switch (child_id) {
|
|
893 case NOTOK:
|
|
894 adios ("vfork", "unable to");
|
|
895
|
|
896 case OK:
|
|
897 dup2 (fileno (out), 1);
|
|
898
|
|
899 i = 1;
|
|
900 vec[i++] = "-forward";
|
|
901 vec[i++] = "-form";
|
|
902 vec[i++] = filter;
|
|
903 vec[i++] = tmpfil;
|
|
904 vec[i] = NULL;
|
|
905
|
|
906 execvp (mhlproc, vec);
|
|
907 adios (mhlproc, "unable to exec");
|
|
908
|
|
909 default:
|
|
910 if (status = pidwait (child_id, OK))
|
|
911 admonish (NULL, "%s lost (status=0%o)", vec[0], status);
|
|
912 break;
|
|
913 }
|
|
914 }
|
|
915
|
|
916 fseek (out, 0L, 2);
|
|
917 fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
|
|
918 (void)fclose (out);
|
|
919 }
|
|
920 #endif /* notdef */
|
|
921
|
|
922 /* FCC INTERACTION */
|
|
923
|
16
|
924 static void file (path)
|
0
|
925 char *path;
|
|
926 {
|
|
927 int i;
|
|
928
|
|
929 if (fccind == 0)
|
|
930 return;
|
|
931
|
|
932 for (i = 0; i < fccind; i++)
|
|
933 if (whomflg)
|
|
934 printf ("Fcc: %s\n", fccfold[i]);
|
|
935 else
|
|
936 fcc (path, fccfold[i]);
|
|
937 }
|
|
938
|
|
939
|
16
|
940 static void fcc (file, folder)
|
0
|
941 char *file,
|
|
942 *folder;
|
|
943 {
|
|
944 int i,
|
|
945 child_id,
|
|
946 status;
|
|
947 char fold[BUFSIZ];
|
|
948
|
|
949 if (verbose)
|
|
950 printf ("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", folder);
|
|
951 (void)fflush (stdout);
|
|
952
|
|
953 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
|
|
954 sleep (5);
|
|
955 switch (child_id) {
|
|
956 case NOTOK:
|
|
957 if (!verbose)
|
|
958 fprintf (stderr, " %sFcc %s: ",
|
|
959 msgstate == resent ? "Resent-" : "", folder);
|
|
960 fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
|
|
961 break;
|
|
962
|
|
963 case OK:
|
|
964 (void)sprintf (fold, "%s%s",
|
|
965 *folder == '+' || *folder == '@' ? "" : "+", folder);
|
|
966 execlp (fileproc, r1bindex (fileproc, '/'),
|
|
967 "-link", "-file", file, fold, NULL);
|
|
968 _exit (-1);
|
|
969
|
|
970 default:
|
|
971 if (status = pidwait (child_id, OK)) {
|
|
972 if (!verbose)
|
|
973 fprintf (stderr, " %sFcc %s: ",
|
|
974 msgstate == resent ? "Resent-" : "", folder);
|
|
975 fprintf (verbose ? stdout : stderr,
|
|
976 " errored (0%o)\n", status);
|
|
977 }
|
|
978 }
|
|
979
|
|
980 (void)fflush (stdout);
|
|
981 }
|
|
982
|
|
983 /* TERMINATION */
|
|
984
|
|
985 /* VARARGS2 */
|
|
986
|
|
987 static die (what, fmt, a, b, c, d)
|
|
988 char *what,
|
|
989 *fmt,
|
|
990 *a,
|
|
991 *b,
|
|
992 *c,
|
|
993 *d;
|
|
994 {
|
|
995 adios (what, fmt, a, b, c, d);
|
|
996 }
|