]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/RCS/mhn.c,v
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / RCS / mhn.c,v
1 head 2.42;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 2.42
9 date 95.12.06.22.32.29; author jromine; state Exp;
10 branches;
11 next 2.41;
12
13 2.41
14 date 95.12.06.21.05.46; author jromine; state Exp;
15 branches;
16 next 2.40;
17
18 2.40
19 date 95.12.06.21.03.37; author jromine; state Exp;
20 branches;
21 next 2.39;
22
23 2.39
24 date 95.12.06.21.02.05; author jromine; state Exp;
25 branches;
26 next 2.38;
27
28 2.38
29 date 95.12.06.20.55.31; author jromine; state Exp;
30 branches;
31 next 2.37;
32
33 2.37
34 date 95.12.06.19.20.22; author jromine; state Exp;
35 branches;
36 next 2.36;
37
38 2.36
39 date 94.04.21.19.23.38; author jromine; state Exp;
40 branches;
41 next 2.35;
42
43 2.35
44 date 93.10.26.22.17.44; author jromine; state Exp;
45 branches;
46 next 2.34;
47
48 2.34
49 date 93.10.26.20.15.00; author jromine; state Exp;
50 branches;
51 next 2.33;
52
53 2.33
54 date 93.10.26.20.11.27; author jromine; state Exp;
55 branches;
56 next 2.32;
57
58 2.32
59 date 93.10.26.15.56.01; author jromine; state Exp;
60 branches;
61 next 2.31;
62
63 2.31
64 date 93.10.26.15.51.19; author jromine; state Exp;
65 branches;
66 next 2.30;
67
68 2.30
69 date 93.10.26.15.44.42; author jromine; state Exp;
70 branches;
71 next 2.29;
72
73 2.29
74 date 93.10.26.15.41.33; author jromine; state Exp;
75 branches;
76 next 2.28;
77
78 2.28
79 date 93.10.25.19.58.19; author jromine; state Exp;
80 branches;
81 next 2.27;
82
83 2.27
84 date 93.10.25.19.32.05; author jromine; state Exp;
85 branches;
86 next 2.26;
87
88 2.26
89 date 93.09.09.22.38.43; author jromine; state Exp;
90 branches;
91 next 2.25;
92
93 2.25
94 date 93.09.01.21.46.58; author jromine; state Exp;
95 branches;
96 next 2.24;
97
98 2.24
99 date 93.09.01.20.50.03; author jromine; state Exp;
100 branches;
101 next 2.23;
102
103 2.23
104 date 93.08.25.17.26.22; author jromine; state Exp;
105 branches;
106 next 2.22;
107
108 2.22
109 date 93.08.20.15.52.01; author jromine; state Exp;
110 branches;
111 next 2.21;
112
113 2.21
114 date 92.12.15.00.20.22; author jromine; state Exp;
115 branches;
116 next 2.20;
117
118 2.20
119 date 92.12.14.17.10.25; author jromine; state Exp;
120 branches;
121 next 2.19;
122
123 2.19
124 date 92.12.10.22.27.15; author jromine; state Exp;
125 branches;
126 next 2.18;
127
128 2.18
129 date 92.12.09.19.23.22; author jromine; state Exp;
130 branches;
131 next 2.17;
132
133 2.17
134 date 92.12.03.21.58.18; author jromine; state Exp;
135 branches;
136 next 2.16;
137
138 2.16
139 date 92.12.02.18.50.39; author jromine; state Exp;
140 branches;
141 next 2.15;
142
143 2.15
144 date 92.11.24.18.21.54; author jromine; state Exp;
145 branches;
146 next 2.14;
147
148 2.14
149 date 92.11.24.17.18.52; author jromine; state Exp;
150 branches;
151 next 2.13;
152
153 2.13
154 date 92.11.24.17.18.04; author jromine; state Exp;
155 branches;
156 next 2.12;
157
158 2.12
159 date 92.11.23.19.07.08; author jromine; state Exp;
160 branches;
161 next 2.11;
162
163 2.11
164 date 92.11.23.19.05.18; author jromine; state Exp;
165 branches;
166 next 2.10;
167
168 2.10
169 date 92.11.23.19.04.27; author jromine; state Exp;
170 branches;
171 next 2.9;
172
173 2.9
174 date 92.11.11.17.57.04; author jromine; state Exp;
175 branches;
176 next 2.8;
177
178 2.8
179 date 92.11.09.17.46.01; author jromine; state Exp;
180 branches;
181 next 2.7;
182
183 2.7
184 date 92.11.09.17.45.19; author jromine; state Exp;
185 branches;
186 next 2.6;
187
188 2.6
189 date 92.11.06.03.24.40; author jromine; state Exp;
190 branches;
191 next 2.5;
192
193 2.5
194 date 92.11.04.00.47.59; author jromine; state Exp;
195 branches;
196 next 2.4;
197
198 2.4
199 date 92.11.02.17.01.08; author jromine; state Exp;
200 branches;
201 next 2.3;
202
203 2.3
204 date 92.10.26.16.58.47; author jromine; state Exp;
205 branches;
206 next 2.2;
207
208 2.2
209 date 92.10.20.20.30.08; author jromine; state Exp;
210 branches;
211 next 2.1;
212
213 2.1
214 date 92.10.20.16.26.29; author jromine; state Exp;
215 branches;
216 next 2.0;
217
218 2.0
219 date 92.10.20.16.24.21; author jromine; state Exp;
220 branches;
221 next 1.7;
222
223 1.7
224 date 92.05.19.21.01.53; author jromine; state Exp;
225 branches;
226 next 1.6;
227
228 1.6
229 date 92.03.03.17.13.54; author jromine; state Exp;
230 branches;
231 next 1.5;
232
233 1.5
234 date 92.02.18.17.36.22; author jromine; state Exp;
235 branches;
236 next 1.4;
237
238 1.4
239 date 92.02.14.16.22.17; author jromine; state Exp;
240 branches;
241 next 1.3;
242
243 1.3
244 date 92.02.07.16.07.46; author jromine; state Exp;
245 branches;
246 next 1.2;
247
248 1.2
249 date 92.02.07.03.44.12; author jromine; state Exp;
250 branches;
251 next 1.1;
252
253 1.1
254 date 92.01.31.16.28.15; author jromine; state Exp;
255 branches;
256 next ;
257
258
259 desc
260 @multimedia MH
261 @
262
263
264 2.42
265 log
266 @rename si_value for Solaris 2.x
267 @
268 text
269 @/* mhn.c - multi-media MH */
270 #ifndef lint
271 static char ident[] = "@@(#)$Id: mhn.c,v 2.41 1995/12/06 21:05:46 jromine Exp jromine $";
272 #endif /* lint */
273
274 #include "../h/mh.h"
275 #include <ctype.h>
276 #include <errno.h>
277 #include <setjmp.h>
278 #include <signal.h>
279 #include <stdio.h>
280 #include "../zotnet/mts.h"
281 #include <sys/types.h>
282 #include <sys/stat.h>
283 #ifdef BSD42
284 #include <sys/wait.h>
285 #endif
286 #ifdef LOCALE
287 #include <locale.h>
288 #endif
289
290 /* \f */
291
292 static struct swit switches[] = {
293 #define AUTOSW 0
294 "auto", 0,
295 #define NAUTOSW 1
296 "noauto", 0,
297
298 #define CACHESW 2
299 "cache", 0,
300 #define NCACHESW 3
301 "nocache", 0,
302
303 #define CHECKSW 4
304 "check", 0,
305 #define NCHECKSW 5
306 "nocheck", 0,
307
308 #define DEBUGSW 6
309 "debug", -5,
310
311 #define EBCDICSW 7
312 "ebcdicsafe", 0,
313 #define NEBCDICSW 8
314 "noebcdicsafe", 0,
315
316 #define FILESW 9 /* interface from show */
317 "file file", 0,
318
319 #define FORMSW 10
320 "form formfile", 4,
321
322 #define HEADSW 11
323 "headers", 0,
324 #define NHEADSW 12
325 "noheaders", 0,
326
327 #define LISTSW 13
328 "list", 0,
329 #define NLISTSW 14
330 "nolist", 0,
331
332 #define PARTSW 15
333 "part number", 0,
334
335 #define PAUSESW 16
336 "pause", 0,
337 #define NPAUSESW 17
338 "nopause", 0,
339
340 #define RCACHESW 18
341 "rcache policy", 0,
342
343 #define SIZESW 19
344 "realsize", 0,
345 #define NSIZESW 20
346 "norealsize", 0,
347
348 #define RFC934SW 21
349 "rfc934mode", 0,
350 #define NRFC934SW 22
351 "norfc934mode", 0,
352
353 #define SERIALSW 23
354 "serialonly", 0,
355 #define NSERIALSW 24
356 "noserialonly", 0,
357
358 #define SHOWSW 25
359 "show", 0,
360 #define NSHOWSW 26
361 "noshow", 0,
362
363 #define STORESW 27
364 "store", 0,
365 #define NSTORESW 28
366 "nostore", 0,
367
368 #define TYPESW 29
369 "type content", 0,
370
371 #define VERBSW 30
372 "verbose", 0,
373 #define NVERBSW 31
374 "noverbose", 0,
375
376 #define WCACHESW 32
377 "wcache policy", 0,
378
379 #define HELPSW 33
380 "help", 4,
381
382 #define PROGSW 34
383 "moreproc program", -4,
384 #define NPROGSW 35
385 "nomoreproc", -3,
386
387 #define LENSW 36
388 "length lines", -4,
389 #define WIDSW 37
390 "width columns", -4,
391
392 #define VIAMSW 38
393 "viamail mailpath", -7,
394 #define VIASSW 39
395 "viasubj subject", -7,
396 #define VIAPSW 40
397 "viaparm arguments", -7,
398 #define VIADSW 41
399 "viadesc text", -7,
400 #define VIACSW 42
401 "viacmnt text", -7,
402 #define VIAZSW 43
403 "viadelay seconds", -8,
404 #define VIAFSW 44
405 "viafrom mailpath", -7,
406
407 NULL, 0
408 };
409
410 /* \f */
411
412 #define NPARTS 50
413 #define NTYPES 20
414
415 static struct swit caches[] = {
416 #define CACHE_NEVER 0
417 "never", 0,
418 #define CACHE_PRIVATE 1
419 "private", 0,
420 #define CACHE_PUBLIC 2
421 "public", 0,
422 #define CACHE_ASK 3
423 "ask", 0,
424
425 NULL, 0
426 };
427
428 static int autosw = 0;
429 static int cachesw = 0;
430 static int checksw = 0;
431 int debugsw = 0;
432 static int ebcdicsw = 0;
433 static char *formsw = NULLCP;
434 static int headsw = 1;
435 static int listsw = 0;
436 static int nolist = 0;
437 static int nomore = 0;
438 static int npart = 0;
439 static char *parts[NPARTS + 1];
440 static int pausesw = 1;
441 static char *progsw = NULLCP;
442 static int rcachesw = CACHE_ASK;
443 static int rfc934sw = 1;
444 static int serialsw = 0;
445 static int showsw = 0;
446 static int sizesw = 1;
447 static int storesw = 0;
448 static int ntype = 0;
449 static char *types[NTYPES + 1];
450 int verbosw = 0;
451 static int wcachesw = CACHE_ASK;
452
453 static int endian = 0;
454 static char *mm_charset = NULL;
455
456 static int xpid = 0;
457 static int userrs = 0;
458
459 static char *cache_public;
460 static char *cache_private;
461 static int cwdlen;
462 static char *cwd;
463 static char *dir;
464 static char *errs = NULL;
465 static char *tmp;
466
467
468 extern int errno;
469 #ifndef BSD44
470 extern int sys_nerr;
471 extern char *sys_errlist[];
472 #endif
473
474 off_t lseek ();
475 time_t time ();
476
477 /* \f */
478
479 #define LSTFMT1 "%4s %-5s %-24s %5s %-36s\n"
480
481 #define LSTFMT2a "%4d "
482 #define LSTFMT2b "%-5s %-24.24s "
483 #define LSTFMT2c1 "%5lu"
484 #define LSTFMT2c2 "%4lu%c"
485 #define LSTFMT2c3 "huge "
486 #define LSTFMT2c4 " "
487 #define LSTFMT2d1 " %-36.36s"
488 #define LSTFMT2d2 "\t %-65.65s\n"
489
490 static void build_comp ();
491
492 typedef struct CTinfo {
493 char *ci_type;
494 char *ci_subtype;
495
496 #define NPARMS 10
497 char *ci_attrs[NPARMS + 2];
498 char *ci_values[NPARMS];
499
500 char *ci_comment;
501
502 char *ci_magic;
503 } CTInfo, *CI;
504 #define NULLCI ((CI) 0)
505
506 static int get_ctinfo ();
507 static int get_comment ();
508
509
510 typedef struct Content {
511 char *c_partno; /* within multipart content */
512
513 char *c_vrsn; /* Body-Version: */
514
515 char *c_ctline; /* Content-Type: */
516 CTInfo c_ctinfo;
517
518 int c_type; /* internal form */
519 #define CT_UNKNOWN 0x00
520 #define CT_APPLICATION 0x01
521 #define CT_AUDIO 0x02
522 #define CT_IMAGE 0x03
523 #define CT_MESSAGE 0x04
524 #define CT_MULTIPART 0x05
525 #define CT_TEXT 0x06
526 #define CT_VIDEO 0x07
527 #define CT_EXTENSION 0x08
528
529 int c_subtype; /* filled-in by c_ctinitfnx */
530 caddr_t c_ctparams; /* .. */
531 caddr_t c_ctextern; /* .. */
532 char *c_showproc; /* default, if not in profile */
533 char *c_termproc; /* for charset madness... */
534 char *c_storeproc; /* overrides profile entry, if any */
535
536 int (*c_ctinitfnx) (); /* parse content */
537 int (*c_ctlistfnx) (); /* list content */
538 int (*c_ctshowfnx) (); /* show content */
539 int (*c_ctstorefnx) (); /* store content */
540 int (*c_ctfreefnx) (); /* free content-specific structures */
541
542
543 char *c_celine; /* Content-Transfer-Encoding: */
544
545 int c_encoding; /* internal form */
546 #define CE_UNKNOWN 0x00
547 #define CE_BASE64 0x01
548 #define CE_QUOTED 0x02
549 #define CE_8BIT 0x03
550 #define CE_7BIT 0x04
551 #define CE_BINARY 0x05
552 #define CE_EXTENSION 0x06
553 #define CE_EXTERNAL 0x07 /* for external-body */
554
555 caddr_t c_ceparams; /* filled-in by encoding initfnx */
556
557 int (*c_ceopenfnx) (); /* get a stream to decoded contents */
558 int (*c_ceclosefnx) (); /* release stream */
559 int (*c_celistfnx) (); /* list decoding info */
560 unsigned long
561 (*c_cesizefnx) (); /* size of decoded contents */
562 int (*c_cefreefnx) (); /* free encoding-specific structures */
563
564
565 char *c_id; /* Content-ID: */
566 char *c_descr; /* Content-Description: */
567
568 int c_digested; /* Content-MD5: */
569 unsigned char c_digest[16]; /* .. */
570
571 FILE *c_fp; /* read contents (stream) */
572 char *c_file; /* read contents (file) */
573 int c_unlink; /* remove file when done? */
574 int c_umask; /* associated umask */
575 long c_begin; /* where content starts in file */
576 long c_end; /* .. ends */
577
578 int c_pid; /* process doing display */
579 char *c_storage; /* write contents (file) */
580
581 int c_rfc934; /* rfc934 compatibility */
582 } Content, *CT;
583 #define NULLCT ((CT) 0)
584
585 static CT get_content ();
586 static int list_content (), show_content (), store_content ();
587 static int cache_content ();
588 static int user_content (), compose_content (), output_content ();
589 static void free_content (), flush_errors (), set_id ();
590
591 #if defined(__STDC__) && defined(VSPRINTF)
592 static void content_error (char *, register CT, char *, ...);
593 #else
594 static void content_error ();
595 #endif
596
597 static int init_encoding (), type_ok (), copy_some_headers (), set_endian ();
598 static int make_intermediates ();
599 static int find_cache (), find_cache_aux (), find_cache_aux2 ();
600 static int write7Bit (), writeQuoted (), writeBase64 (), writeBase64aux ();
601 static int writeDigest (), readDigest ();
602 static int via_mail (), via_post (), pidcheck ();
603
604 static CT *cts = NULL;
605
606
607 #define quitser pipeser
608 static TYPESIG pipeser ();
609 static char *fgetstr ();
610
611 /* \f */
612
613 /* ARGSUSED */
614
615 main (argc, argv)
616 int argc;
617 char **argv;
618 {
619 int f6 = 0,
620 msgp = 0,
621 msgnum,
622 *icachesw;
623 char *cp,
624 *f1 = NULL,
625 *f2 = NULL,
626 *f3 = NULL,
627 *f4 = NULL,
628 *f5 = NULL,
629 *f7 = NULL,
630 *file = NULL,
631 *folder = NULL,
632 *maildir,
633 buf[100],
634 **ap,
635 **argp,
636 *arguments[MAXARGS],
637 *msgs[MAXARGS];
638 struct msgs *mp;
639 register CT ct,
640 *ctp;
641 FILE *fp;
642
643 #ifdef LOCALE
644 setlocale(LC_ALL, "");
645 #endif
646 invo_name = r1bindex (argv[0], '/');
647 if (argv[1] && uprf (argv[1], "-via"))
648 m_foil (NULLCP);
649 if ((cp = m_find (invo_name)) != NULL) {
650 ap = brkstring (cp = getcpy (cp), " ", "\n");
651 ap = copyip (ap, arguments);
652 }
653 else
654 ap = arguments;
655 (void) copyip (argv + 1, ap);
656 argp = arguments;
657
658 /* \f */
659
660 while (cp = *argp++) {
661 if (*cp == '-')
662 switch (smatch (++cp, switches)) {
663 case AMBIGSW:
664 ambigsw (cp, switches);
665 done (1);
666 case UNKWNSW:
667 adios (NULLCP, "-%s unknown", cp);
668 case HELPSW:
669 (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
670 invo_name);
671 help (buf, switches);
672 done (1);
673
674 case AUTOSW:
675 autosw++;
676 continue;
677 case NAUTOSW:
678 autosw = 0;
679 continue;
680
681 case CACHESW:
682 cachesw++;
683 continue;
684 case NCACHESW:
685 cachesw = 0;
686 continue;
687
688 case RCACHESW:
689 icachesw = &rcachesw;
690 goto do_cache;
691 case WCACHESW:
692 icachesw = &wcachesw;
693 do_cache: ;
694 if (!(cp = *argp++) || *cp == '-')
695 adios (NULLCP, "missing argument to %s", argp[-2]);
696 switch (*icachesw = smatch (cp, caches)) {
697 case AMBIGSW:
698 ambigsw (cp, caches);
699 done (1);
700 case UNKWNSW:
701 adios (NULLCP, "%s unknown", cp);
702 default:
703 break;
704 }
705 continue;
706
707 case CHECKSW:
708 checksw++;
709 continue;
710 case NCHECKSW:
711 checksw = 0;
712 continue;
713
714 case DEBUGSW:
715 debugsw++;
716 continue;
717
718 case EBCDICSW:
719 ebcdicsw++;
720 continue;
721 case NEBCDICSW:
722 ebcdicsw = 0;
723 continue;
724
725 case FORMSW:
726 if (!(cp = *argp++) || *cp == '-')
727 adios (NULLCP, "missing argument to %s", argp[-2]);
728 if (formsw)
729 free (formsw);
730 formsw = getcpy (libpath (cp));
731 continue;
732
733 case HEADSW:
734 headsw++;
735 continue;
736 case NHEADSW:
737 headsw = 0;
738 continue;
739
740 case LISTSW:
741 listsw++;
742 continue;
743 case NLISTSW:
744 listsw = 0;
745 continue;
746
747 case PARTSW:
748 if (!(cp = *argp++) || *cp == '-')
749 adios (NULLCP, "missing argument to %s", argp[-2]);
750 if (npart >= NPARTS)
751 adios (NULLCP,
752 "too many parts (starting with %s), %d max",
753 cp, NPARTS);
754 parts[npart++] = cp;
755 continue;
756
757 case PAUSESW:
758 pausesw++;
759 continue;
760 case NPAUSESW:
761 pausesw = 0;
762 continue;
763
764 case RFC934SW:
765 rfc934sw++;
766 continue;
767 case NRFC934SW:
768 rfc934sw = 0;
769 continue;
770
771 case SERIALSW:
772 serialsw++;
773 continue;
774 case NSERIALSW:
775 serialsw = 0;
776 continue;
777
778 case SHOWSW:
779 showsw++;
780 continue;
781 case NSHOWSW:
782 showsw = 0;
783 continue;
784
785 case SIZESW:
786 sizesw++;
787 continue;
788 case NSIZESW:
789 sizesw = 0;
790 continue;
791
792 case STORESW:
793 storesw++;
794 continue;
795 case NSTORESW:
796 storesw = 0;
797 continue;
798
799 case TYPESW:
800 if (!(cp = *argp++) || *cp == '-')
801 adios (NULLCP, "missing argument to %s", argp[-2]);
802 if (ntype >= NTYPES)
803 adios (NULLCP,
804 "too many types (starting with %s), %d max",
805 cp, NTYPES);
806 types[ntype++] = cp;
807 continue;
808
809 case VERBSW:
810 verbosw++;
811 continue;
812 case NVERBSW:
813 verbosw = 0;
814 continue;
815
816 case PROGSW:
817 if (!(progsw = *argp++) || *progsw == '-')
818 adios (NULLCP, "missing argument to %s", argp[-2]);
819 continue;
820 case NPROGSW:
821 nomore++;
822 continue;
823
824 case LENSW:
825 case WIDSW:
826 if (!(cp = *argp++) || *cp == '-')
827 adios (NULLCP, "missing argument to %s", argp[-2]);
828 continue;
829
830 case FILESW:
831 if (!(cp = *argp++) || (*cp == '-' && cp[1]))
832 adios (NULLCP, "missing argument to %s", argp[-2]);
833 file = *cp == '-' ? cp : path (cp, TFILE);
834 continue;
835
836 case VIAMSW:
837 if (!(f1 = *argp++))
838 adios (NULLCP, "missing argument to %s", argp[-2]);
839 continue;
840 case VIASSW:
841 if (!(f2 = *argp++))
842 adios (NULLCP, "missing argument to %s", argp[-2]);
843 continue;
844 case VIAPSW:
845 if (!(f3 = *argp++))
846 adios (NULLCP, "missing argument to %s", argp[-2]);
847 continue;
848 case VIADSW:
849 if (!(f4 = *argp++))
850 adios (NULLCP, "missing argument to %s", argp[-2]);
851 continue;
852 case VIACSW:
853 if (!(f5 = *argp++))
854 adios (NULLCP, "missing argument to %s", argp[-2]);
855 continue;
856 case VIAZSW:
857 if (!(cp = *argp++) || *cp == '-')
858 adios (NULLCP, "missing argument to %s", argp[-2]);
859 if (sscanf (cp, "%d", &f6) != 1 || f6 < 0)
860 f6 = 300;
861 continue;
862 case VIAFSW:
863 if (!(f7 = *argp++))
864 adios (NULLCP, "missing argument to %s", argp[-2]);
865 continue;
866 }
867 if (*cp == '+' || *cp == '@@') {
868 if (folder)
869 adios (NULLCP, "only one folder at a time!");
870 else
871 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
872 }
873 else
874 msgs[msgp++] = cp;
875 }
876 parts[npart] = NULL, types[ntype] = NULL;
877 if (!formsw)
878 formsw = getcpy (libpath ("mhl.headers"));
879
880 set_endian ();
881
882 /* \f */
883
884 if (f1) {
885 via_mail (f1, f2, f3, f4, f5, f6, f7);
886 /* NOTREACHED */
887 }
888 else
889 if (f2 || f3 || f4 || f5 || f6 || f7)
890 adios (NULLCP, "missing -viamail \"mailpath\" switch");
891
892 if (cp = getenv ("MHN")) {
893 if (fp = fopen (cp, "r")) {
894 m_readefs ((struct node **) 0, fp, cp, 0);
895
896 (void) fclose (fp);
897 }
898 else
899 admonish ("", "unable to read $MHN profile (%s)", cp);
900 }
901 if (fp = fopen (cp = libpath ("mhn_defaults"), "r")) {
902 m_readefs ((struct node **) 0, fp, cp, 0);
903
904 (void) fclose (fp);
905 }
906
907 (void) sprintf (buf, "%s-cache", invo_name);
908 if ((cache_public = m_find (buf)) && *cache_public != '/')
909 cache_public = NULL;
910 (void) sprintf (buf, "%s-private-cache", invo_name);
911 if (!(cache_private = m_find (buf)))
912 cache_private = ".cache";
913 cache_private = getcpy (m_maildir (cache_private));
914
915 cwdlen = strlen (cwd = getcpy (pwd ()));
916 (void) sprintf (buf, "%s-storage", invo_name);
917 dir = getcpy ((cp = m_find (buf)) && *cp ? cp : cwd);
918 tmp = cp && *cp ? concat (cp, "/", invo_name, NULLCP)
919 : add (m_maildir (invo_name), NULLCP);
920
921 if (!m_find ("path"))
922 free (path ("./", TFOLDER));
923
924 if (msgp == 1
925 && !folder
926 && !npart
927 && !cachesw
928 && !showsw
929 && !storesw
930 && !ntype
931 && !file
932 && (cp = getenv ("mhdraft"))
933 && strcmp (cp, msgs[0]) == 0) {
934 build_comp (cp);
935 /* NOTREACHED */
936 }
937
938 if (file) {
939 int stdinP;
940
941 if (msgp)
942 adios (NULLCP, "only one file at a time!");
943
944 if ((cts = (CT *) calloc ((unsigned) 2, sizeof *cts)) == NULL)
945 adios (NULLCP, "out of memory");
946
947 ctp = cts;
948 if (stdinP = (strcmp (file, "-") == 0)) {
949 char buffer[BUFSIZ];
950
951 file = add (m_tmpfil (invo_name), NULLCP);
952
953 if ((fp = fopen (file, "w+")) == NULL)
954 adios (file, "unable to fopen for writing and reading");
955 (void) chmod (file, 0600);
956 while (fgets (buffer, sizeof buffer, stdin))
957 (void) fputs (buffer, fp);
958 (void) fflush (fp);
959
960 if (ferror (stdin)) {
961 (void) unlink (file);
962 adios ("stdin", "error reading");
963 }
964
965 if (ferror (fp)) {
966 (void) unlink (file);
967 adios (file, "error writing");
968 }
969
970 (void) fseek (fp, 0L, 0);
971 }
972 else
973 if ((fp = fopen (file, "r")) == NULL)
974 adios (file, "unable to read");
975
976 if (ct = get_content (fp, file, 1)) {
977 if (stdinP)
978 ct -> c_unlink = 1;
979
980 ct -> c_fp = NULL;
981 if (ct -> c_end == 0L) {
982 (void) fseek (fp, 0L, 2);
983 ct -> c_end = ftell (fp);
984 }
985 if (ct -> c_ctinitfnx && (*ct -> c_ctinitfnx) (ct) == NOTOK)
986 free_content (ct);
987 else
988 *ctp++ = ct;
989 }
990 else
991 advise (NULLCP, "unable to decode %s", file);
992
993 (void) fclose (fp);
994
995 mp = NULL;
996 goto go_to_it;
997 }
998
999 if (!msgp)
1000 msgs[msgp++] = "cur";
1001 if (!folder)
1002 folder = m_getfolder ();
1003 maildir = m_maildir (folder);
1004
1005 if (chdir (maildir) == NOTOK)
1006 adios (maildir, "unable to change directory to");
1007 if (!(mp = m_gmsg (folder)))
1008 adios (NULLCP, "unable to read folder %s", folder);
1009 if (mp -> hghmsg == 0)
1010 adios (NULLCP, "no messages in %s", folder);
1011
1012 for (msgnum = 0; msgnum < msgp; msgnum++)
1013 if (!m_convert (mp, msgs[msgnum]))
1014 done (1);
1015 m_setseq (mp);
1016
1017 if ((cts = (CT *) calloc ((unsigned) (mp -> numsel + 1), sizeof *cts))
1018 == NULL)
1019 adios (NULLCP, "out of memory");
1020
1021 ctp = cts;
1022 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1023 if (mp -> msgstats[msgnum] & SELECTED) {
1024 char *msgnam;
1025
1026 if ((fp = fopen (msgnam = m_name (msgnum), "r")) == NULL)
1027 adios (msgnam, "unable to read message");
1028
1029 if (ct = get_content (fp, msgnam, 1)) {
1030 ct -> c_fp = NULL;
1031 if (ct -> c_end == 0L) {
1032 (void) fseek (fp, 0L, 2);
1033 ct -> c_end = ftell (fp);
1034 }
1035 if (ct -> c_ctinitfnx && (*ct -> c_ctinitfnx) (ct) == NOTOK)
1036 free_content (ct);
1037 else
1038 *ctp++ = ct;
1039 }
1040 else
1041 advise (NULLCP, "unable to decode message %s", msgnam);
1042
1043 (void) fclose (fp);
1044 }
1045
1046 go_to_it: ;
1047 if (!*cts)
1048 done (1);
1049
1050 if (!listsw && !showsw && !storesw && !cachesw)
1051 showsw++;
1052
1053 /* listsw && showsw -> user wants per-message listing,
1054 so delay until showsw processing
1055
1056 && storesw && sizesw -> evaluating size will cause more work,
1057 so delay until after storesw processing
1058 */
1059 userrs = 1;
1060 (void) signal (SIGQUIT, quitser);
1061 (void) signal (SIGPIPE, pipeser);
1062
1063 for (ctp = cts; ct = *ctp; ctp++)
1064 if (type_ok (ct, 1)
1065 && (ct -> c_ctlistfnx
1066 || ct -> c_ctstorefnx
1067 || ct -> c_ctshowfnx)) {
1068 struct stat st;
1069
1070 if (!ct -> c_umask)
1071 ct -> c_umask = ~(stat (ct -> c_file, &st) != NOTOK
1072 ? (st.st_mode & 0777) : m_gmprot ());
1073 }
1074
1075 if (listsw && !showsw && (!storesw || !sizesw)) {
1076 if (headsw)
1077 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
1078 "description");
1079
1080 for (ctp = cts; ct = *ctp; ctp++)
1081 if (type_ok (ct, 1) && ct -> c_ctlistfnx) {
1082 (void) umask (ct -> c_umask);
1083 (void) (*ct -> c_ctlistfnx) (ct, 1);
1084 if (ct -> c_fp)
1085 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1086 if (ct -> c_ceclosefnx)
1087 (*ct -> c_ceclosefnx) (ct);
1088 }
1089
1090 flush_errors ();
1091 }
1092
1093 if (storesw) {
1094 for (ctp = cts; ct = *ctp; ctp++)
1095 if (type_ok (ct, 1) && ct -> c_ctstorefnx) {
1096 (void) umask (ct -> c_umask);
1097 (void) (*ct -> c_ctstorefnx) (ct, NULLCP);
1098 if (ct -> c_fp)
1099 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1100 if (ct -> c_ceclosefnx)
1101 (*ct -> c_ceclosefnx) (ct);
1102 }
1103
1104 flush_errors ();
1105 }
1106
1107 if (cachesw) {
1108 for (ctp = cts; ct = *ctp; ctp++)
1109 if (type_ok (ct, 1)) {
1110 cache_content (ct);
1111 if (ct -> c_fp)
1112 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1113 if (ct -> c_ceclosefnx)
1114 (*ct -> c_ceclosefnx) (ct);
1115 }
1116
1117 flush_errors ();
1118 }
1119
1120 if (listsw && !showsw && storesw && sizesw) {
1121 if (headsw)
1122 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
1123 "description");
1124
1125 for (ctp = cts; ct = *ctp; ctp++)
1126 if (type_ok (ct, 1) && ct -> c_ctlistfnx) {
1127 (void) umask (ct -> c_umask);
1128 (void) (*ct -> c_ctlistfnx) (ct, 1);
1129 if (ct -> c_fp)
1130 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1131 if (ct -> c_ceclosefnx)
1132 (*ct -> c_ceclosefnx) (ct);
1133 }
1134
1135 flush_errors ();
1136 listsw = 0;
1137 }
1138
1139 if (showsw)
1140 for (ctp = cts; ct = *ctp; ctp++) {
1141 #if defined(BSD42) && !defined(WAITINT)
1142 union wait status;
1143 #else
1144 int status;
1145 #endif
1146 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
1147
1148 if (!type_ok (ct, 0))
1149 continue;
1150
1151 (void) umask (ct -> c_umask);
1152
1153 if (listsw) {
1154 if (headsw)
1155 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
1156 "description");
1157
1158 if (ct -> c_ctlistfnx)
1159 (void) (*ct -> c_ctlistfnx) (ct, 1);
1160 }
1161
1162 if (!ct -> c_ctshowfnx) {
1163 if (ct -> c_fp)
1164 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1165 if (ct -> c_ceclosefnx)
1166 (*ct -> c_ceclosefnx) (ct);
1167 continue;
1168 }
1169
1170 if (strcmp (formsw, "mhl.null")) {
1171 int child_id,
1172 i,
1173 vecp;
1174 char *vec[8];
1175
1176 vecp = 0;
1177 vec[vecp++] = r1bindex (mhlproc, '/');
1178 vec[vecp++] = "-form";
1179 vec[vecp++] = formsw;
1180 vec[vecp++] = "-nobody";
1181 vec[vecp++] = ct -> c_file;
1182 if (nomore)
1183 vec[vecp++] = "-nomoreproc";
1184 else
1185 if (progsw) {
1186 vec[vecp++] = "-moreproc";
1187 vec[vecp++] = progsw;
1188 }
1189 vec[vecp] = NULL;
1190
1191 (void) fflush (stdout);
1192
1193 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
1194 sleep (5);
1195 switch (child_id) {
1196 case NOTOK:
1197 adios ("fork", "unable to");
1198 /* NOTREACHED */
1199
1200 case OK:
1201 (void) execvp (mhlproc, vec);
1202 fprintf (stderr, "unable to exec ");
1203 perror (mhlproc);
1204 _exit (-1);
1205 /* NOTREACHED */
1206
1207 default:
1208 xpid = -child_id;
1209 break;
1210 }
1211 }
1212 else
1213 xpid = 0;
1214
1215 (void) (*ct -> c_ctshowfnx) (ct, 1, 0);
1216 if (ct -> c_fp)
1217 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1218 if (ct -> c_ceclosefnx)
1219 (*ct -> c_ceclosefnx) (ct);
1220
1221 hstat = signal (SIGHUP, SIG_IGN);
1222 istat = signal (SIGINT, SIG_IGN);
1223 qstat = signal (SIGQUIT, SIG_IGN);
1224 tstat = signal (SIGTERM, SIG_IGN);
1225
1226 while (wait (&status) != NOTOK) {
1227 #if defined(BSD42) && !defined(WAITINT)
1228 (void) pidcheck (status.w_status);
1229 #else
1230 (void) pidcheck (status);
1231 #endif
1232 continue;
1233 }
1234
1235 (void) signal (SIGHUP, hstat);
1236 (void) signal (SIGINT, istat);
1237 (void) signal (SIGQUIT, qstat);
1238 (void) signal (SIGTERM, tstat);
1239
1240 xpid = 0;
1241
1242 flush_errors ();
1243 }
1244
1245 for (ctp = cts; *ctp; ctp++)
1246 free_content (*ctp);
1247 free ((char *) cts);
1248 cts = NULL;
1249
1250 if (mp) {
1251 m_replace (pfolder, folder);
1252 if (mp -> hghsel != mp -> curmsg)
1253 m_setcur (mp, mp -> hghsel);
1254 m_sync (mp);
1255 m_update ();
1256 }
1257
1258 done (0);
1259 /* NOTREACHED */
1260 }
1261
1262 /* \f */
1263
1264 static TYPESIG pipeser (i)
1265 int i;
1266 {
1267 if (i == SIGQUIT) {
1268 (void) unlink ("core");
1269
1270 (void) fflush (stdout);
1271
1272 fprintf (stderr, "\n");
1273 (void) fflush (stderr);
1274 }
1275
1276 done (1);
1277 /* NOTREACHED */
1278 }
1279
1280 /* \f */
1281
1282 #include "../h/mhn.h"
1283
1284
1285 struct str2init {
1286 char *si_key;
1287 int si_val;
1288 int (*si_init) ();
1289 };
1290
1291
1292 static int InitApplication (), InitMessage (), InitMultiPart (), InitText (),
1293 InitGeneric ();
1294
1295
1296 static struct str2init str2cts[] = {
1297 "application", CT_APPLICATION, InitApplication,
1298 "audio", CT_AUDIO, InitGeneric,
1299 "image", CT_IMAGE, InitGeneric,
1300 "message", CT_MESSAGE, InitMessage,
1301 "multipart", CT_MULTIPART, InitMultiPart,
1302 "text", CT_TEXT, InitText,
1303 "video", CT_VIDEO, InitGeneric,
1304
1305 NULL, CT_EXTENSION, NULL, /* these two must be last! */
1306 NULL, CT_UNKNOWN, NULL,
1307 };
1308
1309
1310 static int InitBase64 (), InitQuoted (), Init7Bit ();
1311
1312 static struct str2init str2ces[] = {
1313 "base64", CE_BASE64, InitBase64,
1314 "quoted-printable", CE_QUOTED, InitQuoted,
1315 "8bit", CE_8BIT, Init7Bit,
1316 "7bit", CE_7BIT, Init7Bit,
1317 "binary", CE_BINARY, NULL,
1318
1319 NULL, CE_EXTENSION, NULL, /* these two must be last! */
1320 NULL, CE_UNKNOWN, NULL,
1321 };
1322
1323 /* \f */
1324
1325 static CT get_content (in, file, toplevel)
1326 FILE *in;
1327 char *file;
1328 int toplevel;
1329 {
1330 int compnum,
1331 state;
1332 char buf[BUFSIZ],
1333 name[NAMESZ];
1334 register CT ct;
1335
1336 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
1337 adios (NULLCP, "out of memory");
1338
1339 ct -> c_begin = ftell (ct -> c_fp = in) + 1;
1340 ct -> c_file = add (file, NULLCP);
1341 for (compnum = 1, state = FLD;;) {
1342 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
1343 case FLD:
1344 case FLDPLUS:
1345 case FLDEOF:
1346 compnum++;
1347
1348 if (uleq (name, VRSN_FIELD)) {
1349 int ucmp;
1350 char c,
1351 *cp,
1352 *dp;
1353
1354 cp = add (buf, NULLCP);
1355 while (state == FLDPLUS) {
1356 state = m_getfld (state, name, buf, sizeof buf, in);
1357 cp = add (buf, cp);
1358 }
1359
1360 if (ct -> c_vrsn) {
1361 /*
1362 advise (NULLCP,
1363 "message %s has multiple %s: fields (%s)",
1364 ct -> c_file, VRSN_FIELD, dp = trimcpy (cp));
1365 free (dp);
1366 */
1367 free (cp);
1368 /*
1369 goto out;
1370 */
1371 goto got_header;
1372 }
1373
1374 ct -> c_vrsn = cp;
1375 while (isspace (*cp))
1376 cp++;
1377 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1378 *dp++ = ' ';
1379 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1380 if (!isspace (*dp))
1381 break;
1382 *++dp = '\0';
1383 if (debugsw)
1384 fprintf (stderr, "%s: %s\n", VRSN_FIELD, cp);
1385
1386 if (*cp == '(' && get_comment (ct, &cp, 0) == NOTOK)
1387 goto out;
1388
1389 for (dp = cp; istoken (*dp); dp++)
1390 continue;
1391 c = *dp, *dp = '\0';
1392 ucmp = uleq (cp, VRSN_VALUE);
1393 *dp = c;
1394 if (!ucmp)
1395 admonish (NULLCP,
1396 "message %s has unknown value for %s: field (%s)",
1397 ct -> c_file, VRSN_FIELD, cp);
1398 goto got_header;
1399 }
1400
1401 if (uleq (name, TYPE_FIELD)) {
1402 register char *cp;
1403 register struct str2init *s2i;
1404 register CI ci = &ct -> c_ctinfo;
1405
1406 cp = add (buf, NULLCP);
1407 while (state == FLDPLUS) {
1408 state = m_getfld (state, name, buf, sizeof buf, in);
1409 cp = add (buf, cp);
1410 }
1411
1412 if (ct -> c_ctline) {
1413 char *dp = trimcpy (cp);
1414
1415 advise (NULLCP,
1416 "message %s has multiple %s: fields (%s)",
1417 ct -> c_file, TYPE_FIELD, dp);
1418 free (dp);
1419 free (cp);
1420 goto out;
1421 }
1422
1423 if (get_ctinfo (cp, ct, 0) == NOTOK)
1424 goto out;
1425 for (s2i = str2cts; s2i -> si_key; s2i++)
1426 if (uleq (ci -> ci_type, s2i -> si_key))
1427 break;
1428 if (!s2i -> si_key && !uprf (ci -> ci_type, "X-"))
1429 s2i++;
1430 ct -> c_type = s2i -> si_val;
1431 ct -> c_ctinitfnx = s2i -> si_init;
1432 goto got_header;
1433 }
1434
1435 if (uleq (name, ENCODING_FIELD)) {
1436 register char *cp,
1437 *dp;
1438 char c;
1439 register struct str2init *s2i;
1440
1441 cp = add (buf, NULLCP);
1442 while (state == FLDPLUS) {
1443 state = m_getfld (state, name, buf, sizeof buf, in);
1444 cp = add (buf, cp);
1445 }
1446
1447 if (ct -> c_celine) {
1448 advise (NULLCP,
1449 "message %s has multiple %s: fields (%s)",
1450 ct -> c_file, ENCODING_FIELD,
1451 dp = trimcpy (cp));
1452 free (dp);
1453 free (cp);
1454 goto out;
1455 }
1456
1457 ct -> c_celine = cp;
1458 while (isspace (*cp))
1459 cp++;
1460 for (dp = cp; istoken (*dp); dp++)
1461 continue;
1462 c = *dp, *dp = '\0';
1463 for (s2i = str2ces; s2i -> si_key; s2i++)
1464 if (uleq (cp, s2i -> si_key))
1465 break;
1466 if (!s2i -> si_key && !uprf (cp, "X-"))
1467 s2i++;
1468 *dp = c;
1469 ct -> c_encoding = s2i -> si_val;
1470 if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
1471 goto out;
1472 goto got_header;
1473 }
1474
1475 if (uleq (name, ID_FIELD)) {
1476 ct -> c_id = add (buf, ct -> c_id);
1477 while (state == FLDPLUS) {
1478 state = m_getfld (state, name, buf, sizeof buf, in);
1479 ct -> c_id = add (buf, ct -> c_id);
1480 }
1481 goto got_header;
1482 }
1483
1484 if (uleq (name, DESCR_FIELD)) {
1485 ct -> c_descr = add (buf, ct -> c_descr);
1486 while (state == FLDPLUS) {
1487 state = m_getfld (state, name, buf, sizeof buf, in);
1488 ct -> c_descr = add (buf, ct -> c_descr);
1489 }
1490 goto got_header;
1491 }
1492
1493 if (uleq (name, MD5_FIELD)) {
1494 char *cp,
1495 *dp,
1496 *ep;
1497
1498 cp = add (buf, NULLCP);
1499 while (state == FLDPLUS) {
1500 state = m_getfld (state, name, buf, sizeof buf, in);
1501 cp = add (buf, cp);
1502 }
1503
1504 if (!checksw) {
1505 free (cp);
1506 goto got_header;
1507 }
1508
1509 if (ct -> c_digested) {
1510 advise (NULLCP,
1511 "message %s has multiple %s: fields (%s)",
1512 ct -> c_file, MD5_FIELD,
1513 dp = trimcpy (cp));
1514 free (dp);
1515 free (cp);
1516 goto out;
1517 }
1518
1519 ep = cp;
1520 while (isspace (*cp))
1521 cp++;
1522 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1523 *dp++ = ' ';
1524 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1525 if (!isspace (*dp))
1526 break;
1527 *++dp = '\0';
1528 if (debugsw)
1529 fprintf (stderr, "%s: %s\n", MD5_FIELD, cp);
1530
1531 if (*cp == '(' && get_comment (ct, &cp, 0) == NOTOK) {
1532 free (ep);
1533 goto out;
1534 }
1535
1536 for (dp = cp; *dp && !isspace (*dp); dp++)
1537 continue;
1538 *dp = '\0';
1539
1540 (void) readDigest (ct, cp);
1541 free (ep);
1542 ct -> c_digested++;
1543 goto got_header;
1544 }
1545
1546 #ifdef notdef
1547 if (uprf (name, XXX_FIELD_PRF))
1548 advise (NULLCP, "unknown field (%s) in message %s",
1549 name, ct -> c_file);
1550 /* and fall... */
1551 #endif
1552
1553 while (state == FLDPLUS)
1554 state = m_getfld (state, name, buf, sizeof buf, in);
1555 got_header: ;
1556 if (state != FLDEOF) {
1557 ct -> c_begin = ftell (in) + 1;
1558 continue;
1559 }
1560 /* else fall... */
1561
1562 case BODY:
1563 case BODYEOF:
1564 ct -> c_begin = ftell (in) - strlen (buf);
1565 break;
1566
1567 case FILEEOF:
1568 ct -> c_begin = ftell (in);
1569 break;
1570
1571 case LENERR:
1572 case FMTERR:
1573 adios (NULLCP, "message format error in component #%d",
1574 compnum);
1575
1576 default:
1577 adios (NULLCP, "getfld() returned %d", state);
1578 }
1579 break;
1580 }
1581
1582 if (!ct -> c_ctline) {
1583 if (toplevel < 0) {
1584 if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK)
1585 goto out;
1586 ct -> c_type = CT_MESSAGE;
1587 ct -> c_ctinitfnx = InitMessage;
1588 }
1589 else {
1590 if (get_ctinfo ("text/plain", ct, 0) == NOTOK)
1591 goto out;
1592 ct -> c_type = CT_TEXT;
1593 ct -> c_ctinitfnx = InitText;
1594 }
1595 }
1596 if (!ct -> c_ctlistfnx)
1597 ct -> c_ctlistfnx = list_content;
1598 if (!ct -> c_ctshowfnx)
1599 ct -> c_ctshowfnx = show_content;
1600 if (!ct -> c_ctstorefnx)
1601 ct -> c_ctstorefnx = store_content;
1602
1603 if (!ct -> c_celine) {
1604 ct -> c_encoding = CE_7BIT;
1605 (void) Init7Bit (ct);
1606 }
1607
1608 return ct;
1609
1610 out:
1611 free_content (ct);
1612 return NULLCT;
1613 }
1614
1615 /* \f */
1616
1617 static int get_ctinfo (cp, ct, magic)
1618 char *cp;
1619 register CT ct;
1620 int magic;
1621 {
1622 int i = strlen (invo_name) + 2;
1623 register char *dp,
1624 **ap,
1625 **ep;
1626 char c;
1627 register CI ci = &ct -> c_ctinfo;
1628
1629 cp = ct -> c_ctline = add (cp, NULLCP);
1630 while (isspace (*cp))
1631 cp++;
1632 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1633 *dp++ = ' ';
1634 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1635 if (!isspace (*dp))
1636 break;
1637 *++dp = '\0';
1638 if (debugsw)
1639 fprintf (stderr, "%s: %s\n", TYPE_FIELD, cp);
1640
1641 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1642 return NOTOK;
1643
1644 for (dp = cp; istoken (*dp); dp++)
1645 continue;
1646 c = *dp, *dp = '\0';
1647 ci -> ci_type = add (cp, NULLCP);
1648 *dp = c, cp = dp;
1649
1650 if (!*ci -> ci_type) {
1651 advise (NULLCP, "invalid %s: field in message %s (empty type)",
1652 TYPE_FIELD, ct -> c_file);
1653 return NOTOK;
1654 }
1655
1656 for (dp = ci -> ci_type; *dp; dp++)
1657 if (isalpha(*dp) && isupper (*dp))
1658 *dp = tolower (*dp);
1659
1660 while (isspace (*cp))
1661 cp++;
1662
1663 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1664 return NOTOK;
1665
1666 if (*cp != '/') {
1667 if (!magic)
1668 ci -> ci_subtype = add ("", NULLCP);
1669 goto magic_skip;
1670 }
1671
1672 cp++;
1673 while (isspace (*cp))
1674 cp++;
1675
1676 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1677 return NOTOK;
1678
1679 for (dp = cp; istoken (*dp); dp++)
1680 continue;
1681 c = *dp, *dp = '\0';
1682 ci -> ci_subtype = add (cp, NULLCP);
1683 *dp = c, cp = dp;
1684
1685 if (!*ci -> ci_subtype) {
1686 advise (NULLCP,
1687 "invalid %s: field in message %s (empty subtype for \"%s\")",
1688 TYPE_FIELD, ct -> c_file, ci -> ci_type);
1689 return NOTOK;
1690 }
1691
1692 for (dp = ci -> ci_subtype; *dp; dp++)
1693 if (isalpha(*dp) && isupper (*dp))
1694 *dp = tolower (*dp);
1695
1696 magic_skip: ;
1697 while (isspace (*cp))
1698 cp++;
1699
1700 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1701 return NOTOK;
1702
1703 ep = (ap = ci -> ci_attrs) + NPARMS;
1704 while (*cp == ';') {
1705 char *vp,
1706 *up;
1707
1708 if (ap >= ep) {
1709 advise (NULLCP,
1710 "too many parameters in message %s's %s: field (%d max)",
1711 ct -> c_file, TYPE_FIELD, NPARMS);
1712 return NOTOK;
1713 }
1714
1715 cp++;
1716 while (isspace (*cp))
1717 cp++;
1718
1719 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1720 return NOTOK;
1721
1722 if (*cp == 0) {
1723 advise (NULLCP,
1724 "extraneous trailing ';' in message %s's %s: parameter list",
1725 ct -> c_file, TYPE_FIELD);
1726 return OK;
1727 }
1728
1729 for (dp = cp; istoken (*dp); dp++)
1730 if (isalpha(*dp) && isupper (*dp))
1731 *dp = tolower (*dp);
1732 for (up = dp; isspace (*dp); )
1733 dp++;
1734 if (dp == cp || *dp != '=') {
1735 advise (NULLCP,
1736 "invalid parameter in message %s's %s: field\n%*.*sparameter %s (error detected at offset %d)",
1737 ct -> c_file, TYPE_FIELD, i, i, "", cp, dp - cp);
1738 return NOTOK;
1739 }
1740
1741 vp = (*ap = add (cp, NULLCP)) + (up - cp);
1742 *vp = '\0';
1743 for (dp++; isspace (*dp); )
1744 dp++;
1745 ci -> ci_values[ap - ci -> ci_attrs] = vp = *ap + (dp - cp);
1746 if (*dp == '"') {
1747 for (cp = ++dp, dp = vp;;) {
1748 switch (c = *cp++) {
1749 case '\0':
1750 bad_quote: ;
1751 advise (NULLCP,
1752 "invalid quoted-string in message %s's %s: field\n%*.*s(parameter %s)",
1753 ct -> c_file, TYPE_FIELD, i, i, "", *ap);
1754 return NOTOK;
1755
1756 case '\\':
1757 *dp++ = c;
1758 if ((c = *cp++) == '\0')
1759 goto bad_quote;
1760 /* else fall... */
1761
1762 default:
1763 *dp++ = c;
1764 continue;
1765
1766 case '"':
1767 *dp = '\0';
1768 break;
1769 }
1770 break;
1771 }
1772 }
1773 else {
1774 for (cp = dp, dp = vp; istoken (*cp); cp++, dp++)
1775 continue;
1776 *dp = '\0';
1777 }
1778 if (!*vp) {
1779 advise (NULLCP,
1780 "invalid parameter in message %s's %s: field\n%*.*s(parameter %s)",
1781 ct -> c_file, TYPE_FIELD, i, i, "", *ap);
1782 return NOTOK;
1783 }
1784 ap++;
1785
1786 while (isspace (*cp))
1787 cp++;
1788
1789 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1790 return NOTOK;
1791 }
1792
1793 if (magic && *cp == '<') {
1794 if (ct -> c_id)
1795 free (ct -> c_id), ct -> c_id = NULL;
1796
1797 if (!(dp = index (ct -> c_id = ++cp, '>'))) {
1798 advise (NULLCP, "invalid ID in message %s", ct -> c_file);
1799 return NOTOK;
1800 }
1801
1802 c = *dp, *dp = '\0';
1803 if (*ct -> c_id)
1804 ct -> c_id = concat ("<", ct -> c_id, ">\n", NULLCP);
1805 else
1806 ct -> c_id = NULL;
1807 *dp++ = c, cp = dp;
1808
1809 while (isspace (*cp))
1810 cp++;
1811 }
1812
1813 if (magic && *cp == '[') {
1814 ct -> c_descr = ++cp;
1815 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1816 if (*dp == ']')
1817 break;
1818 if (dp < cp) {
1819 advise (NULLCP, "invalid description in message %s", ct -> c_file);
1820 ct -> c_descr = NULL;
1821 return NOTOK;
1822 }
1823
1824 c = *dp, *dp = '\0';
1825 if (*ct -> c_descr)
1826 ct -> c_descr = concat (ct -> c_descr, "\n", NULLCP);
1827 else
1828 ct -> c_descr = NULL;
1829 *dp++ = c, cp = dp;
1830
1831 while (isspace (*cp))
1832 cp++;
1833 }
1834
1835 if (*cp) {
1836 if (magic)
1837 ci -> ci_magic = add (cp, NULLCP);
1838 else
1839 advise (NULLCP,
1840 "extraneous information in message %s's %s: field\n%*.*s(%s)",
1841 ct -> c_file, TYPE_FIELD, i, i, "", cp);
1842 }
1843
1844 return OK;
1845 }
1846
1847 /* \f */
1848
1849 static int get_comment (ct, ap, istype)
1850 CT ct;
1851 char **ap;
1852 int istype;
1853 {
1854 register int i;
1855 register char *bp,
1856 *cp;
1857 char c,
1858 buffer[BUFSIZ],
1859 *dp;
1860 register CI ci = &ct -> c_ctinfo;
1861
1862 cp = *ap;
1863
1864 bp = buffer;
1865 cp++;
1866 for (i = 0;;) {
1867 switch (c = *cp++) {
1868 case '\0':
1869 invalid: ;
1870 advise (NULLCP, "invalid comment in message %s's %s: field",
1871 ct -> c_file, istype ? TYPE_FIELD : VRSN_FIELD);
1872 return NOTOK;
1873
1874 case '\\':
1875 *bp++ = c;
1876 if ((c = *cp++) == '\0')
1877 goto invalid;
1878 *bp++ = c;
1879 continue;
1880
1881 case '(':
1882 i++;
1883 /* and fall... */
1884 default:
1885 *bp++ = c;
1886 continue;
1887
1888 case ')':
1889 if (--i < 0)
1890 break;
1891 *bp++ = c;
1892 continue;
1893 }
1894 break;
1895 }
1896 *bp = '\0';
1897
1898 if (istype) {
1899 if (dp = ci -> ci_comment) {
1900 ci -> ci_comment = concat (dp, " ", buffer, NULLCP);
1901 free (dp);
1902 }
1903 else
1904 ci -> ci_comment = add (buffer, NULLCP);
1905 }
1906
1907 while (isspace (*cp))
1908 cp++;
1909
1910 *ap = cp;
1911
1912 return OK;
1913 }
1914
1915 /* \f */
1916
1917 #define empty(s) ((s) ? (s) : "")
1918
1919
1920 static int list_content (ct, toplevel)
1921 register CT ct;
1922 int toplevel;
1923 {
1924 unsigned long size;
1925 register char **ap,
1926 **ep;
1927 char *cp,
1928 buffer[BUFSIZ];
1929 register CI ci = &ct -> c_ctinfo;
1930
1931 printf (toplevel > 0 ? LSTFMT2a : toplevel < 0 ? "part " : " ",
1932 atoi (r1bindex (empty (ct -> c_file), '/')));
1933 (void) sprintf (buffer, "%s/%s", empty (ci -> ci_type),
1934 empty (ci -> ci_subtype));
1935 printf (LSTFMT2b, empty (ct -> c_partno), buffer);
1936
1937 size = ct -> c_cesizefnx && sizesw ? (*ct -> c_cesizefnx) (ct)
1938 : ct -> c_end - ct -> c_begin;
1939
1940 for (cp = " KMGT"; size > 9999; size >>= 10)
1941 if (!*++cp)
1942 break;
1943 switch (*cp) {
1944 case ' ':
1945 if (size > 0 || ct -> c_encoding != CE_EXTERNAL)
1946 printf (LSTFMT2c1, size);
1947 else
1948 printf (LSTFMT2c4);
1949 break;
1950
1951 default:
1952 printf (LSTFMT2c2, size, *cp);
1953 break;
1954
1955 case '\0':
1956 printf (LSTFMT2c3);
1957 }
1958
1959 if (ct -> c_descr) {
1960 char *dp;
1961
1962 dp = trimcpy (cp = add (ct -> c_descr, NULLCP));
1963 free (cp);
1964 printf (LSTFMT2d1, dp);
1965 free (dp);
1966 }
1967
1968 printf ("\n");
1969
1970 if (verbosw && ci -> ci_comment) {
1971 char *dp;
1972
1973 dp = trimcpy (cp = add (ci -> ci_comment, NULLCP));
1974 free (cp);
1975 (void) sprintf (buffer, "(%s)", dp);
1976 free (dp);
1977 printf (LSTFMT2d2, buffer);
1978 }
1979
1980 if (!debugsw)
1981 return OK;
1982
1983 (void) fflush (stdout);
1984
1985 fprintf (stderr, " partno \"%s\"\n", empty (ct -> c_partno));
1986
1987 if (ct -> c_vrsn)
1988 fprintf (stderr, " %s:%s\n", VRSN_FIELD, ct -> c_vrsn);
1989
1990 if (ct -> c_ctline)
1991 fprintf (stderr, " %s:%s", TYPE_FIELD, ct -> c_ctline);
1992 fprintf (stderr,
1993 " type \"%s\" subtype \"%s\" comment \"%s\" magic \"%s\"\n",
1994 empty (ci -> ci_type), empty (ci -> ci_subtype),
1995 empty (ci -> ci_comment), empty (ci -> ci_magic));
1996 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
1997 fprintf (stderr, " parameter %s=\"%s\"\n", *ap, *ep);
1998 fprintf (stderr,
1999 " type 0x%x subtype 0x%x params 0x%x\n",
2000 ct -> c_type, ct -> c_subtype, ct -> c_ctparams);
2001
2002 fprintf (stderr, " showproc \"%s\"\n", empty (ct -> c_showproc));
2003 fprintf (stderr, " termproc \"%s\"\n", empty (ct -> c_termproc));
2004 fprintf (stderr, " storeproc \"%s\"\n", empty (ct -> c_storeproc));
2005
2006 if (ct -> c_celine)
2007 fprintf (stderr, " %s:%s", ENCODING_FIELD, ct -> c_celine);
2008 fprintf (stderr, " encoding 0x%x params 0x%x\n",
2009 ct -> c_encoding, ct -> c_ceparams);
2010
2011 if (ct -> c_id)
2012 fprintf (stderr, " %s:%s", ID_FIELD, ct -> c_id);
2013 if (ct -> c_descr)
2014 fprintf (stderr, " %s:%s", DESCR_FIELD, ct -> c_descr);
2015
2016 fprintf (stderr, " fp 0x%x file \"%s\" begin %d end %d\n",
2017 ct -> c_fp, empty (ct -> c_file), ct -> c_begin, ct -> c_end);
2018
2019 if (ct -> c_celistfnx)
2020 (void) (*ct -> c_celistfnx) (ct);
2021
2022 return OK;
2023 }
2024 #undef empty
2025
2026 /* \f */
2027
2028 #ifdef VSPRINTF
2029 #ifdef __STDC__
2030 #include <stdarg.h>
2031 #else
2032 #include <varargs.h>
2033 #endif
2034 #endif
2035
2036 #ifdef VSPRINTF
2037 #ifdef __STDC__
2038 static void content_error (char *what, register CT ct, char *fmt, ...)
2039 #else
2040 static void content_error (va_alist)
2041 va_dcl
2042 #endif
2043 #else /* !VSPRINTF */
2044 /* VARARGS3 */
2045 static void content_error (what, ct, fmt, a, b, c, d, e, f)
2046 char *what,
2047 *fmt,
2048 *a,
2049 *b,
2050 *c,
2051 *d,
2052 *e,
2053 *f;
2054 register CT ct;
2055 #endif
2056 {
2057 #ifdef VSPRINTF
2058 va_list arglist;
2059 #endif
2060 #if defined(VSPRINTF) && !defined(__STDC__)
2061 char *what, *fmt;
2062 register CT ct;
2063 #endif
2064 int i;
2065 register char *bp;
2066 char buffer[BUFSIZ];
2067 register CI ci;
2068
2069 bp = buffer;
2070
2071 if (userrs && invo_name && *invo_name) {
2072 (void) sprintf (bp, "%s: ", invo_name);
2073 bp += strlen (bp);
2074 }
2075
2076 #ifdef VSPRINTF
2077 #ifdef __STDC__
2078 va_start (arglist, fmt);
2079 #else
2080 va_start (arglist);
2081 what = va_arg(arglist, char *);
2082 ct = va_arg(arglist, CT);
2083 fmt = va_arg(arglist, char *);
2084 #endif
2085 (void) vsprintf (bp, fmt, arglist);
2086 bp += strlen (bp);
2087 #else
2088 (void) sprintf (bp, fmt, a, b, c, d, e, f);
2089 bp += strlen (bp);
2090 #endif
2091 ci = &ct -> c_ctinfo;
2092
2093 if (what) {
2094 if (*what) {
2095 (void) sprintf (bp, " %s: ", what);
2096 bp += strlen (bp);
2097 }
2098
2099 if (errno > 0 && errno < sys_nerr)
2100 (void) sprintf (bp, "%s", sys_errlist[errno]);
2101 else
2102 (void) sprintf (bp, "Error %d", errno);
2103 bp += strlen (bp);
2104 }
2105
2106 i = strlen (invo_name) + 2;
2107 (void) sprintf (bp, "\n%*.*s(content %s/%s", i, i, "", ci -> ci_type,
2108 ci -> ci_subtype);
2109 bp += strlen (bp);
2110 if (ct -> c_file) {
2111 (void) sprintf (bp, " in message %s", ct -> c_file);
2112 bp += strlen (bp);
2113 if (ct -> c_partno) {
2114 (void) sprintf (bp, ", part %s", ct -> c_partno);
2115 bp += strlen (bp);
2116 }
2117 }
2118 (void) sprintf (bp, ")");
2119 bp += strlen (bp);
2120
2121 if (userrs) {
2122 *bp++ = '\n';
2123 *bp = '\0';
2124
2125 errs = add (buffer, errs);
2126 }
2127 else
2128 advise (NULLCP, "%s", buffer);
2129 }
2130
2131
2132 static void flush_errors ()
2133 {
2134 if (errs) {
2135 (void) fflush (stdout);
2136 fprintf (stderr, "%s", errs);
2137 free (errs);
2138 errs = NULL;
2139 }
2140 }
2141
2142 /* \f */
2143
2144 static jmp_buf intrenv;
2145
2146
2147 /* ARGSUSED */
2148
2149 static TYPESIG intrser (i)
2150 int i;
2151 {
2152 #ifdef BSD42
2153 (void) signal (SIGINT, intrser);
2154 #endif
2155
2156 (void) putchar ('\n');
2157
2158 longjmp (intrenv, DONE);
2159 }
2160
2161 /* \f */
2162
2163 static int show_content_aux (), show_content_aux2 ();
2164
2165
2166 static int show_content (ct, serial, alternate)
2167 register CT ct;
2168 int serial,
2169 alternate;
2170 {
2171 register char *cp;
2172 char buffer[BUFSIZ];
2173 register CI ci = &ct -> c_ctinfo;
2174
2175 (void) sprintf (buffer, "%s-show-%s/%s", invo_name, ci -> ci_type,
2176 ci -> ci_subtype);
2177 if ((cp = m_find (buffer)) == NULL || *cp == 0) {
2178 (void) sprintf (buffer, "%s-show-%s", invo_name, ci -> ci_type);
2179 if (((cp = m_find (buffer)) == NULL || *cp == 0)
2180 && (cp = ct -> c_showproc) == NULL) {
2181 if (!alternate)
2182 content_error (NULLCP, ct,
2183 "don't know how to display content");
2184
2185 return NOTOK;
2186 }
2187 }
2188
2189 return show_content_aux (ct, serial, alternate, cp, NULLCP);
2190 }
2191
2192
2193 static int show_content_aux (ct, serial, alternate, cp, cracked)
2194 register CT ct;
2195 int serial,
2196 alternate;
2197 register char *cp;
2198 char *cracked;
2199 {
2200 int fd,
2201 xlist,
2202 xpause,
2203 xstdin,
2204 xtty;
2205 register char *bp;
2206 char *file,
2207 buffer[BUFSIZ];
2208 register CI ci = &ct -> c_ctinfo;
2209
2210 if (!ct -> c_ceopenfnx) {
2211 if (!alternate)
2212 content_error (NULLCP, ct, "don't know how to decode content");
2213
2214 return NOTOK;
2215 }
2216
2217 file = NULL;
2218 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
2219 return NOTOK;
2220 if (ct -> c_showproc && strcmp (ct -> c_showproc, "true") == 0)
2221 return (alternate ? DONE : OK);
2222
2223 xlist = xpause = xstdin = xtty = 0;
2224 if (cracked) {
2225 (void) strcpy (buffer, cp);
2226 goto got_command;
2227 }
2228 buffer[0] = '\0';
2229 for (bp = buffer; *cp; cp++)
2230 if (*cp == '%') {
2231 switch (*++cp) {
2232 case 'a': /* additional arguments */
2233 {
2234 register char **ap,
2235 **ep;
2236 char *s = "";
2237
2238 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
2239 *ap;
2240 ap++, ep++) {
2241 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
2242 bp += strlen (bp);
2243 s = " ";
2244 }
2245 }
2246 break;
2247
2248 case 'd': /* content description */
2249 if (ct -> c_descr) {
2250 char *s;
2251
2252 (void) strcpy (bp, s = trimcpy (ct -> c_descr));
2253 free (s);
2254 }
2255 break;
2256
2257 case 'e': /* exclusive execution */
2258 xtty = 1;
2259 break;
2260
2261 case 'F': /* %e, %f, and stdin is terminal not content */
2262 xstdin = xtty = 1;
2263 /* and fall... */
2264 case 'f': /* filename */
2265 (void) sprintf (bp, "%s", file);
2266 break;
2267
2268 case 'p': /* pause prior to displaying content */
2269 xpause = pausesw;
2270 /* and fall... */
2271 case 'l': /* display listing prior to displaying
2272 content */
2273 xlist = !nolist;
2274 break;
2275
2276 case 's': /* subtype */
2277 (void) strcpy (bp, ci -> ci_subtype);
2278 break;
2279
2280 case '%':
2281 goto raw;
2282
2283 default:
2284 *bp++ = *--cp;
2285 *bp = '\0';
2286 continue;
2287 }
2288 bp += strlen (bp);
2289 }
2290 else {
2291 raw: ;
2292 *bp++ = *cp;
2293 *bp = '\0';
2294 }
2295 if (ct -> c_termproc) {
2296 char term[BUFSIZ];
2297
2298 (void) strcpy (term, buffer);
2299 (void) sprintf (buffer, ct -> c_termproc, term);
2300 }
2301
2302 got_command: ;
2303 return show_content_aux2 (ct, serial, alternate, cracked, buffer,
2304 fd, xlist, xpause, xstdin, xtty);
2305 }
2306
2307
2308 static int show_content_aux2 (ct, serial, alternate, cracked, buffer,
2309 fd, xlist, xpause, xstdin, xtty)
2310 register CT ct;
2311 int serial,
2312 alternate;
2313 char *cracked,
2314 *buffer;
2315 int fd,
2316 xlist,
2317 xpause,
2318 xstdin,
2319 xtty;
2320 {
2321 int child_id,
2322 i;
2323 char *vec[4],
2324 exec[BUFSIZ + sizeof "exec "];
2325 register CI ci = &ct -> c_ctinfo;
2326
2327 if (debugsw || cracked) {
2328 (void) fflush (stdout);
2329
2330 fprintf (stderr, "%s msg %s", cracked ? "storing" : "show",
2331 ct -> c_file);
2332 if (ct -> c_partno)
2333 fprintf (stderr, " part %s", ct -> c_partno);
2334 if (cracked)
2335 fprintf (stderr, " using command (cd %s; %s)\n", cracked, buffer);
2336 else
2337 fprintf (stderr, " using command %s\n", buffer);
2338 }
2339
2340 if (xpid < 0 || (xtty && xpid)) {
2341 if (xpid < 0)
2342 xpid = -xpid;
2343 (void) pidcheck (pidwait (xpid, NOTOK));
2344 xpid = 0;
2345 }
2346
2347 if (xlist) {
2348 char prompt[BUFSIZ];
2349
2350 if (ct -> c_ctlistfnx) {
2351 if (ct -> c_type == CT_MULTIPART)
2352 (void) list_content (ct, -1);
2353 else
2354 (*ct -> c_ctlistfnx) (ct, -1);
2355
2356 if (xpause && SOprintf ("Press <return> to show content..."))
2357 printf ("Press <return> to show content...");
2358 }
2359 else {
2360 register char *pp;
2361
2362 pp = prompt;
2363 if (ct -> c_descr) {
2364 (void) sprintf (pp, "%s (", ct -> c_descr);
2365 pp += strlen (pp);
2366 }
2367
2368 (void) sprintf (pp, "content %s/%s", ci -> ci_type,
2369 ci -> ci_subtype);
2370 pp += strlen (pp);
2371 if (ct -> c_file) {
2372 (void) sprintf (pp, " in message %s", ct -> c_file);
2373 pp += strlen (pp);
2374 if (ct -> c_partno) {
2375 (void) sprintf (pp, ", part %s", ct -> c_partno);
2376 pp += strlen (pp);
2377 }
2378 }
2379
2380 if (ct -> c_descr) {
2381 (void) sprintf (pp, ")");
2382 pp += strlen (pp);
2383 }
2384
2385 if (!xpause)
2386 printf ("%s\n", prompt);
2387 else
2388 if (SOprintf ("Press <return> to show %s...", prompt))
2389 printf ("Press <return> to show %s...", prompt);
2390 }
2391
2392 if (xpause) {
2393 int intr;
2394 TYPESIG (*istat) ();
2395
2396 istat = signal (SIGINT, intrser);
2397 if ((intr = setjmp (intrenv)) == OK) {
2398 (void) fflush (stdout);
2399 prompt[0] = 0;
2400 (void) read (fileno (stdout), prompt, sizeof prompt);
2401 }
2402 (void) signal (SIGINT, istat);
2403 if (intr != OK || prompt[0] == 'q') {
2404 (void) (*ct -> c_ceclosefnx) (ct);
2405 return (alternate ? DONE : NOTOK);
2406 }
2407 }
2408 }
2409
2410 (void) sprintf (exec, "exec %s", buffer);
2411
2412 vec[0] = "/bin/sh";
2413 vec[1] = "-c";
2414 vec[2] = exec;
2415 vec[3] = NULL;
2416
2417 (void) fflush (stdout);
2418
2419 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
2420 sleep (5);
2421 switch (child_id) {
2422 case NOTOK:
2423 advise ("fork", "unable to");
2424 (void) (*ct -> c_ceclosefnx) (ct);
2425 return NOTOK;
2426
2427 case OK:
2428 if (cracked)
2429 (void) chdir (cracked);
2430 if (!xstdin)
2431 (void) dup2 (fd, 0);
2432 (void) close (fd);
2433 (void) execvp ("/bin/sh", vec);
2434 fprintf (stderr, "unable to exec ");
2435 perror ("/bin/sh");
2436 _exit (-1);
2437 /* NOTREACHED */
2438
2439 default:
2440 if (!serial) {
2441 ct -> c_pid = child_id;
2442 if (xtty)
2443 xpid = child_id;
2444 }
2445 else
2446 (void) pidcheck (pidXwait (child_id, NULLCP));
2447
2448 if (fd != NOTOK)
2449 (void) (*ct -> c_ceclosefnx) (ct);
2450 return (alternate ? DONE : OK);
2451 }
2452 }
2453
2454 /* \f */
2455
2456 static int store_content (ct, append)
2457 register CT ct;
2458 char *append;
2459 {
2460 int appending = append && *append;
2461 long last,
2462 pos;
2463 register char *bp,
2464 *cp;
2465 char *file,
2466 buffer[BUFSIZ];
2467 register CI ci = &ct -> c_ctinfo;
2468 FILE *fp;
2469
2470 if (appending) {
2471 (void) strcpy (buffer, append);
2472 goto got_filename;
2473 }
2474
2475 if ((cp = ct -> c_storeproc) == NULL || *cp == 0) {
2476 (void) sprintf (buffer, "%s-store-%s/%s", invo_name, ci -> ci_type,
2477 ci -> ci_subtype);
2478 if ((cp = m_find (buffer)) == NULL || *cp == 0) {
2479 (void) sprintf (buffer, "%s-store-%s", invo_name, ci -> ci_type);
2480 if ((cp = m_find (buffer)) == NULL || *cp == 0)
2481 cp = ct -> c_type == CT_MESSAGE ? "+" : "%m%P.%s";
2482 }
2483 }
2484
2485 switch (*cp) {
2486 case '+':
2487 case '@@':
2488 {
2489 char *folder = cp[1] ? path (cp + 1, *cp == '+' ? TFOLDER
2490 : TSUBCWF)
2491 : m_getfolder ();
2492 struct msgs *mp = NULL;
2493 struct stat st;
2494
2495 if (stat (bp = m_mailpath (folder), &st) == NOTOK) {
2496 int answer;
2497 char *ep;
2498
2499 if (errno != ENOENT) {
2500 advise (bp, "error on folder");
2501 goto losing_folder;
2502 }
2503
2504 ep = concat ("Create folder \"", bp, "\"? ", NULLCP);
2505 answer = getanswer (ep);
2506 free (ep);
2507
2508 if (!answer)
2509 goto losing_folder;
2510 if (!makedir (bp)) {
2511 advise (NULLCP, "unable to create folder %s", bp);
2512 goto losing_folder;
2513 }
2514 }
2515
2516 if (mp = m_gmsg (folder))
2517 (void) sprintf (buffer, "%s/%d", mp -> foldpath,
2518 mp -> hghmsg + 1);
2519 else
2520 advise (NULLCP, "unable to read folder %s", folder);
2521 losing_folder: ;
2522 if (cp[1])
2523 free (folder);
2524 if (mp)
2525 m_fmsg (mp);
2526 else
2527 return NOTOK;
2528 }
2529 goto got_filename;
2530
2531 case '/':
2532 case '|':
2533 case '!':
2534 bp = buffer;
2535 buffer[0] = '\0';
2536 break;
2537
2538 default:
2539 bp = autosw ? cwd : dir;
2540 (void) sprintf (buffer, "%s/", bp[1] ? bp : "");
2541 bp = buffer + strlen (buffer);
2542 break;
2543 }
2544 for (; *cp; cp++)
2545 if (*cp == '%') {
2546 switch (*++cp) {
2547 case 'a': /* additional arguments */
2548 if (buffer[0] != '|' && buffer[0] != '!') {
2549 *bp++ = *--cp;
2550 *bp = '\0';
2551 continue;
2552 }
2553 else {
2554 register char **ap,
2555 **ep;
2556 char *s = "";
2557
2558 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
2559 *ap;
2560 ap++, ep++) {
2561 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
2562 bp += strlen (bp);
2563 s = " ";
2564 }
2565 }
2566 break;
2567
2568 case 'm': /* message */
2569 (void) sprintf (bp, "%s", r1bindex (ct -> c_file, '/'));
2570 break;
2571
2572 case 'P': /* .part */
2573 if (ct -> c_partno)
2574 (void) sprintf (bp, ".%s", ct -> c_partno);
2575 break;
2576
2577 case 'p': /* part */
2578 if (ct -> c_partno)
2579 (void) strcpy (bp, ct -> c_partno);
2580 break;
2581
2582 case 't': /* type */
2583 (void) strcpy (bp, ci -> ci_type);
2584 break;
2585
2586 case 's': /* subtype */
2587 (void) strcpy (bp, ci -> ci_subtype);
2588 break;
2589
2590 case '%':
2591 goto raw;
2592
2593 default:
2594 *bp++ = *--cp;
2595 *bp = '\0';
2596 continue;
2597 }
2598 bp += strlen (bp);
2599 }
2600 else {
2601 raw: ;
2602 *bp++ = *cp;
2603 *bp = '\0';
2604 }
2605 if (buffer[0] == '|' || buffer[0] == '!')
2606 return show_content_aux (ct, 1, 0, buffer + 1, autosw ? cwd : dir);
2607 got_filename: ;
2608
2609 ct -> c_storage = add (buffer, NULLCP);
2610 (void) fflush (stdout);
2611 fprintf (stderr, "storing message %s", ct -> c_file);
2612 if (ct -> c_partno)
2613 fprintf (stderr, " part %s", ct -> c_partno);
2614 fprintf (stderr, " as file %s\n",
2615 strncmp (ct -> c_storage, cwd, cwdlen)
2616 || ct -> c_storage[cwdlen] != '/'
2617 ? ct -> c_storage : ct -> c_storage + cwdlen + 1);
2618 if (index (ct -> c_storage, '/')
2619 && make_intermediates (ct -> c_storage) == NOTOK)
2620 return NOTOK;
2621
2622 if (ct -> c_encoding != CE_7BIT) {
2623 int cc,
2624 fd;
2625
2626 if (!ct -> c_ceopenfnx) {
2627 advise (NULLCP, "don't know how to decode part %s of message %s",
2628 ct -> c_partno, ct -> c_file);
2629 return NOTOK;
2630 }
2631
2632 file = appending || !strcmp (ct -> c_storage, "-") ? NULLCP
2633 : ct -> c_storage;
2634 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
2635 return NOTOK;
2636 if (strcmp (file, ct -> c_storage) == 0) {
2637 (void) (*ct -> c_ceclosefnx) (ct);
2638 return OK;
2639 }
2640
2641 if (!strcmp (ct -> c_storage, "-")) {
2642 int gd;
2643
2644 if ((gd = dup (fileno (stdout))) == NOTOK) {
2645 advise ("stdout", "unable to dup");
2646 losing: ;
2647 (void) (*ct -> c_ceclosefnx) (ct);
2648 return NOTOK;
2649 }
2650 if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) {
2651 advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd,
2652 appending ? "a" : "w");
2653 (void) close (gd);
2654 goto losing;
2655 }
2656 }
2657 else
2658 if ((fp = fopen (ct -> c_storage, appending ? "a" : "w"))
2659 == NULL) {
2660 advise (ct -> c_storage, "unable to fopen for %s",
2661 appending ? "appending" : "writing");
2662 goto losing;
2663 }
2664
2665 if (append && !*append)
2666 (void) copy_some_headers (fp, ct);
2667
2668 for (;;) {
2669 switch (cc = read (fd, buffer, sizeof buffer)) {
2670 case NOTOK:
2671 advise (file, "error reading content from");
2672 break;
2673
2674 case OK:
2675 break;
2676
2677 default:
2678 (void) fwrite (buffer, sizeof *buffer, cc, fp);
2679 continue;
2680 }
2681 break;
2682 }
2683
2684 (void) (*ct -> c_ceclosefnx) (ct);
2685
2686 if (cc != NOTOK && fflush (fp))
2687 advise (ct -> c_storage, "error writing to");
2688
2689 (void) fclose (fp);
2690
2691 return (cc != NOTOK ? OK : NOTOK);
2692 }
2693
2694 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
2695 advise (ct -> c_file, "unable to open for reading");
2696 return NOTOK;
2697 }
2698
2699 (void) fseek (ct -> c_fp, pos = ct -> c_begin, 0);
2700 last = ct -> c_end;
2701
2702 if (!strcmp (ct -> c_storage, "-")) {
2703 int gd;
2704
2705 if ((gd = dup (fileno (stdout))) == NOTOK) {
2706 advise ("stdout", "unable to dup");
2707 return NOTOK;
2708 }
2709 if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) {
2710 advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd,
2711 appending ? "a" : "w");
2712 (void) close (gd);
2713 return NOTOK;
2714 }
2715 }
2716 else
2717 if ((fp = fopen (ct -> c_storage, appending ? "a" : "w")) == NULL) {
2718 advise (ct -> c_storage, "unable to fopen for %s",
2719 appending ? "appending" : "writing");
2720 return NOTOK;
2721 }
2722
2723 if (append && !*append) {
2724 (void) copy_some_headers (fp, ct);
2725 appending = 1;
2726 }
2727 else
2728 appending = 0;
2729
2730 while (fgets (buffer, sizeof buffer - 1, ct -> c_fp)) {
2731 if ((pos += strlen (buffer)) > last) {
2732 int diff = strlen (buffer) - (pos - last);
2733
2734 if (diff >= 0)
2735 buffer[diff] = '\0';
2736 }
2737
2738 if (appending)
2739 switch (buffer[0]) {
2740 case ' ':
2741 case '\t':
2742 if (appending < 0)
2743 buffer[0] = 0;
2744 break;
2745
2746 case '\n':
2747 appending = 0;
2748 break;
2749
2750 default:
2751 if (!uprf (buffer, XXX_FIELD_PRF)
2752 && !uprf (buffer, "Encrypted:")
2753 && !uprf (buffer, "Message-ID:")) {
2754 appending = -1;
2755 buffer[0] = 0;
2756 break;
2757 }
2758 appending = 1;
2759 break;
2760 }
2761
2762 (void) fputs (buffer, fp);
2763 if (pos >= last)
2764 break;
2765 }
2766
2767 if (fflush (fp))
2768 advise (ct -> c_storage, "error writing to");
2769
2770 (void) fclose (fp);
2771
2772 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
2773
2774 return OK;
2775 }
2776
2777
2778 static int copy_some_headers (out, ct)
2779 FILE *out;
2780 register CT ct;
2781 {
2782 int state;
2783 char buf[BUFSIZ],
2784 name[NAMESZ];
2785 FILE *in;
2786
2787 if ((in = fopen (ct -> c_file, "r")) == NULL) {
2788 advise (ct -> c_file, "unable to open for reading");
2789 return NOTOK;
2790 }
2791
2792 for (state = FLD;;) {
2793 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
2794 case FLD:
2795 case FLDPLUS:
2796 case FLDEOF:
2797 if (uprf (name, XXX_FIELD_PRF)
2798 || uleq (name, "Encrypted")
2799 || uleq (name, "Message-ID")) {
2800 while (state == FLDPLUS)
2801 state = m_getfld (state, name, buf, sizeof buf, in);
2802 continue;
2803 }
2804
2805 fprintf (out, "%s:%s", name, buf);
2806 while (state == FLDPLUS) {
2807 state = m_getfld (state, name, buf, sizeof buf, in);
2808 (void) fputs (buf, out);
2809 }
2810 if (state != FLDEOF)
2811 continue;
2812 /* else fall... */
2813 case BODY:
2814 case BODYEOF:
2815 case FILEEOF:
2816 break;
2817
2818 case LENERR:
2819 case FMTERR:
2820 default:
2821 break;
2822 }
2823
2824 break;
2825 }
2826
2827 (void) fclose (in);
2828
2829 return OK;
2830 }
2831
2832
2833 static int make_intermediates (file)
2834 char *file;
2835 {
2836 register char *cp;
2837
2838 for (cp = file + 1; cp = index (cp, '/'); cp++) {
2839 struct stat st;
2840
2841 *cp = NULL;
2842
2843 if (stat (file, &st) == NOTOK) {
2844 int answer;
2845 char *ep;
2846
2847 if (errno != ENOENT) {
2848 advise (file, "error on directory");
2849 losing_directory: ;
2850 *cp = '/';
2851 return NOTOK;
2852 }
2853
2854 ep = concat ("Create directory \"", file, "\"? ", NULLCP);
2855 answer = getanswer (ep);
2856 free (ep);
2857
2858 if (!answer)
2859 goto losing_directory;
2860 if (!makedir (file)) {
2861 advise (NULLCP, "unable to create directory %s", file);
2862 goto losing_directory;
2863 }
2864 }
2865
2866 *cp = '/';
2867 }
2868
2869 return OK;
2870 }
2871
2872 /* \f */
2873
2874 static void free_ctinfo (ct)
2875 register CT ct;
2876 {
2877 register char **ap;
2878 register CI ci = &ct -> c_ctinfo;
2879
2880 if (ci -> ci_type)
2881 free (ci -> ci_type);
2882 ci -> ci_type = NULL;
2883 if (ci -> ci_subtype)
2884 free (ci -> ci_subtype);
2885 ci -> ci_subtype = NULL;
2886 for (ap = ci -> ci_attrs; *ap; ap++)
2887 free (*ap), *ap = NULL;
2888 if (ci -> ci_comment)
2889 free (ci -> ci_comment);
2890 ci -> ci_comment = NULL;
2891 if (ci -> ci_magic)
2892 free (ci -> ci_magic);
2893 ci -> ci_magic = NULL;
2894 }
2895
2896
2897 static void free_content (ct)
2898 register CT ct;
2899 {
2900 if (!ct)
2901 return;
2902
2903 if (ct -> c_partno)
2904 free (ct -> c_partno);
2905 ct -> c_partno = NULL;
2906
2907 if (ct -> c_vrsn)
2908 free (ct -> c_vrsn);
2909 ct -> c_vrsn = NULL;
2910
2911 if (ct -> c_ctline)
2912 free (ct -> c_ctline);
2913 ct -> c_ctline = NULL;
2914
2915 free_ctinfo (ct);
2916
2917 if (ct -> c_ctfreefnx)
2918 (void) (*ct -> c_ctfreefnx) (ct);
2919 ct -> c_ctfreefnx = NULL;
2920
2921 if (ct -> c_showproc)
2922 free (ct -> c_showproc);
2923 ct -> c_showproc = NULL;
2924 if (ct -> c_termproc)
2925 free (ct -> c_termproc);
2926 ct -> c_termproc = NULL;
2927 if (ct -> c_storeproc)
2928 free (ct -> c_storeproc);
2929 ct -> c_storeproc = NULL;
2930
2931 if (ct -> c_celine)
2932 free (ct -> c_celine);
2933 ct -> c_celine = NULL;
2934 if (ct -> c_cefreefnx)
2935 (void) (*ct -> c_cefreefnx) (ct, 1);
2936 ct -> c_cefreefnx = NULL;
2937
2938 if (ct -> c_id)
2939 free (ct -> c_id);
2940 ct -> c_id = NULL;
2941 if (ct -> c_descr)
2942 free (ct -> c_descr);
2943 ct -> c_descr = NULL;
2944
2945 if (ct -> c_file) {
2946 if (ct -> c_unlink)
2947 (void) unlink (ct -> c_file);
2948 free (ct -> c_file);
2949 ct -> c_file = NULL;
2950 }
2951 if (ct -> c_fp)
2952 (void) fclose (ct -> c_fp);
2953 ct -> c_fp = NULL;
2954
2955 if (ct -> c_storage)
2956 (void) free (ct -> c_storage);
2957 ct -> c_storage = NULL;
2958
2959 free ((char *) ct);
2960 }
2961
2962 /* \f */
2963
2964 static int part_ok (ct, sP)
2965 register CT ct;
2966 int sP;
2967 {
2968 register char **ap;
2969
2970 if ((ct -> c_type == CT_MULTIPART && (sP || ct -> c_subtype))
2971 || npart == 0)
2972 return 1;
2973
2974 for (ap = parts; *ap; ap++)
2975 if (strcmp (*ap, ct -> c_partno) == 0)
2976 return 1;
2977
2978 return 0;
2979 }
2980
2981
2982
2983 static int type_ok (ct, sP)
2984 register CT ct;
2985 int sP;
2986 {
2987 register char **ap;
2988 char buffer[BUFSIZ];
2989 register CI ci = &ct -> c_ctinfo;
2990
2991 if ((ct -> c_type == CT_MULTIPART && (sP || ct -> c_subtype))
2992 || ntype == 0)
2993 return 1;
2994
2995 (void) sprintf (buffer, "%s/%s", ci -> ci_type, ci -> ci_subtype);
2996 for (ap = types; *ap; ap++)
2997 if (uleq (*ap, ci -> ci_type) || uleq (*ap, buffer))
2998 return 1;
2999
3000 return 0;
3001 }
3002
3003 /* \f CONTENTS */
3004
3005 struct k2v {
3006 char *kv_key;
3007 int kv_value;
3008 };
3009
3010
3011 static int InitGeneric (ct)
3012 register CT ct;
3013 {
3014 register char **ap,
3015 **ep;
3016 register CI ci = &ct -> c_ctinfo;
3017
3018 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3019 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
3020 register char *cp;
3021
3022 if (*(cp = *ep) != '/'
3023 && *cp != '.'
3024 && *cp != '|'
3025 && *cp != '!'
3026 && !index (cp, '%'))
3027 ct -> c_storeproc = add (cp, NULLCP);
3028 }
3029
3030 return OK;
3031 }
3032
3033 /* \f TEXT */
3034
3035 #define TEXT_UNKNOWN 0x00
3036 #define TEXT_PLAIN 0x01
3037 #define TEXT_RICHTEXT 0x02
3038
3039 struct text {
3040 int tx_charset;
3041 #define CHARSET_UNKNOWN 0x00
3042 #define CHARSET_USASCII 0x01
3043 #define CHARSET_LATIN 0x02
3044 };
3045
3046 static struct k2v Charset[] = {
3047 "us-ascii", CHARSET_USASCII,
3048 "iso-8859-1", CHARSET_LATIN,
3049
3050 NULL, CHARSET_UNKNOWN /* this one must be last! */
3051 };
3052
3053 static int free_text (ct)
3054 register CT ct;
3055 {
3056 register struct text *t = (struct text *) ct -> c_ctparams;
3057
3058 if (!t)
3059 return;
3060
3061 free ((char *) t);
3062 ct -> c_ctparams = NULL;
3063 }
3064
3065
3066 static struct k2v SubText[] = {
3067 "plain", TEXT_PLAIN,
3068 "richtext", TEXT_RICHTEXT,
3069
3070 NULL, TEXT_UNKNOWN /* this one must be last! */
3071 };
3072
3073 static int InitText (ct)
3074 register CT ct;
3075 {
3076 char buffer[BUFSIZ];
3077 register char **ap,
3078 **ep;
3079 register struct k2v *kv;
3080 register CI ci = &ct -> c_ctinfo;
3081
3082 if (!*ci -> ci_subtype) /* XXX: attmail bogosity! */
3083 ci -> ci_subtype = add ("plain", ci -> ci_subtype);
3084 for (kv = SubText; kv -> kv_key; kv++)
3085 if (uleq (ci -> ci_subtype, kv -> kv_key))
3086 break;
3087 if ((ct -> c_subtype = kv -> kv_value) == TEXT_PLAIN) {
3088 (void) sprintf (buffer, "%%p%s '%%F'",
3089 progsw ? progsw
3090 : moreproc && *moreproc ? moreproc : "more");
3091 ct -> c_showproc = add (buffer, NULLCP);
3092 }
3093
3094 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3095 if (!ct -> c_ctparams && uleq (*ap, "charset")) {
3096 char *cp;
3097 register struct text *t;
3098
3099 if ((t = (struct text *) calloc (1, sizeof *t)) == NULL)
3100 adios (NULLCP, "out of memory");
3101 ct -> c_ctparams = (caddr_t) t;
3102 ct -> c_ctfreefnx = free_text;
3103
3104 for (kv = Charset; kv -> kv_key; kv++)
3105 if (uleq (*ep, kv -> kv_key)) {
3106 (void) sprintf (buffer, "%s-charset-%s", invo_name,
3107 kv -> kv_key);
3108 break;
3109 }
3110 t -> tx_charset = kv -> kv_value;
3111 if (!kv -> kv_key)
3112 (void) sprintf (buffer, "%s-charset-%s", invo_name, *ep);
3113 if ((!mm_charset || !uleq (mm_charset, *ep))
3114 && (cp = m_find (buffer)))
3115 ct -> c_termproc = getcpy (cp);
3116 }
3117 else
3118 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
3119 register char *cp;
3120
3121 if (*(cp = *ep) != '/'
3122 && *cp != '.'
3123 && *cp != '|'
3124 && *cp != '!'
3125 && !index (cp, '%'))
3126 ct -> c_storeproc = add (cp, NULLCP);
3127 }
3128
3129 return OK;
3130 }
3131
3132 /* \f MULTIPART */
3133
3134 #define MULTI_UNKNOWN 0x00
3135 #define MULTI_MIXED 0x01
3136 #define MULTI_ALTERNATE 0x02
3137 #define MULTI_DIGEST 0x03
3138 #define MULTI_PARALLEL 0x04
3139
3140
3141 struct multipart {
3142 char *mp_start;
3143 char *mp_stop;
3144
3145 struct part {
3146 CT mp_part;
3147
3148 struct part *mp_next;
3149 } *mp_parts;
3150 };
3151
3152
3153 static int list_multi (ct, toplevel)
3154 register CT ct;
3155 int toplevel;
3156 {
3157 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3158 register struct part *part;
3159
3160 (void) list_content (ct, toplevel);
3161
3162 for (part = m -> mp_parts; part; part = part -> mp_next) {
3163 register CT p = part -> mp_part;
3164
3165 if (part_ok (p, 1) && type_ok (p, 1) && p -> c_ctlistfnx)
3166 (void) (*p -> c_ctlistfnx) (p, 0);
3167 }
3168
3169 return OK;
3170 }
3171
3172
3173 static int show_multi (ct, serial, alternate)
3174 register CT ct;
3175 int serial,
3176 alternate;
3177 {
3178 int alternating,
3179 nowalternate,
3180 nowserial,
3181 result;
3182 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3183 register struct part *part;
3184 register CT p;
3185 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
3186
3187 alternating = 0;
3188 nowalternate = alternate;
3189 switch (ct -> c_subtype) {
3190 case MULTI_PARALLEL:
3191 if (!(nowserial = serialsw)) {
3192 set_signals: ;
3193 hstat = signal (SIGHUP, SIG_IGN);
3194 istat = signal (SIGINT, SIG_IGN);
3195 qstat = signal (SIGQUIT, SIG_IGN);
3196 tstat = signal (SIGTERM, SIG_IGN);
3197 }
3198 break;
3199
3200 case MULTI_ALTERNATE:
3201 nowalternate = alternating = 1;
3202 /* and fall... */
3203 default:
3204 if (!(nowserial = serial))
3205 goto set_signals;
3206 break;
3207 }
3208
3209 /* alternate -> we're inside an alternative
3210 alternating -> we are an alternative
3211 */
3212
3213 result = alternate ? NOTOK : OK;
3214 for (part = m -> mp_parts; part; part = part -> mp_next) {
3215 p = part -> mp_part;
3216
3217 if (part_ok (p, 0) && type_ok (p, 0) && p -> c_ctshowfnx) {
3218 int inneresult;
3219
3220 switch (inneresult = (*p -> c_ctshowfnx) (p, nowserial,
3221 nowalternate)) {
3222 case NOTOK:
3223 if (alternate && !alternating) {
3224 result = NOTOK;
3225 goto out;
3226 }
3227 continue;
3228
3229 case OK:
3230 case DONE:
3231 if (alternating) {
3232 result = DONE;
3233 break;
3234 }
3235 if (alternate) {
3236 alternate = nowalternate = 0;
3237 if (result == NOTOK)
3238 result = inneresult;
3239 }
3240 continue;
3241 }
3242 break;
3243 }
3244 }
3245 if (alternating && !part) {
3246 if (!alternate)
3247 content_error (NULLCP, ct,
3248 "don't know how to display any of the contents");
3249
3250 result = NOTOK;
3251 goto out;
3252 }
3253
3254 if (serial && !nowserial) {
3255 int pid,
3256 kids;
3257 #if defined(BSD42) && !defined(WAITINT)
3258 union wait status;
3259 #else
3260 int status;
3261 #endif
3262
3263 kids = 0;
3264 for (part = m -> mp_parts; part; part = part -> mp_next) {
3265 p = part -> mp_part;
3266
3267 if (p -> c_pid > OK)
3268 if (kill (p -> c_pid, 0) == NOTOK)
3269 p -> c_pid = 0;
3270 else
3271 kids++;
3272 }
3273
3274 while (kids > 0 && (pid = wait (&status)) != NOTOK) {
3275 #if defined(BSD42) && !defined(WAITINT)
3276 (void) pidcheck (status.w_status);
3277 #else
3278 (void) pidcheck (status);
3279 #endif
3280
3281 for (part = m -> mp_parts; part; part = part -> mp_next) {
3282 p = part -> mp_part;
3283
3284 if (xpid == pid)
3285 xpid = 0;
3286 if (p -> c_pid == pid) {
3287 p -> c_pid = 0;
3288 kids--;
3289 break;
3290 }
3291 }
3292 }
3293 }
3294
3295 out: ;
3296 if (!nowserial) {
3297 (void) signal (SIGHUP, hstat);
3298 (void) signal (SIGINT, istat);
3299 (void) signal (SIGQUIT, qstat);
3300 (void) signal (SIGTERM, tstat);
3301 }
3302
3303 return result;
3304 }
3305
3306
3307 static int show_unknown_multi (ct, serial, alternate)
3308 register CT ct;
3309 int serial,
3310 alternate;
3311 {
3312 int xlist,
3313 xpause,
3314 xtty;
3315 register char *bp,
3316 *cp;
3317 char buffer[BUFSIZ];
3318 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3319 register struct part *part;
3320 register CI ci = &ct -> c_ctinfo;
3321 register CT p;
3322
3323 (void) sprintf (buffer, "%s-show-%s/%s", invo_name, ci -> ci_type,
3324 ci -> ci_subtype);
3325 if ((cp = m_find (buffer)) == NULL || *cp == 0) {
3326 (void) sprintf (buffer, "%s-show-%s", invo_name, ci -> ci_type);
3327 if (((cp = m_find (buffer)) == NULL || *cp == 0)
3328 && (cp = ct -> c_showproc) == NULL) {
3329 if (!alternate)
3330 content_error (NULLCP, ct,
3331 "don't know how to display content");
3332
3333 return NOTOK;
3334 }
3335 }
3336
3337 for (part = m -> mp_parts; part; part = part -> mp_next) {
3338 p = part -> mp_part;
3339
3340 if (!p -> c_ceopenfnx) {
3341 if (!alternate)
3342 content_error (NULLCP, p, "don't know how to decode content");
3343
3344 return NOTOK;
3345 }
3346
3347 if (p -> c_storage == NULL) {
3348 if ((*p -> c_ceopenfnx) (p, &p -> c_storage) == NOTOK)
3349 return NOTOK;
3350
3351 if (p -> c_showproc && strcmp (p -> c_showproc, "true") == 0)
3352 return (alternate ? DONE : OK);
3353 (*p -> c_ceclosefnx) (p);
3354 }
3355 }
3356
3357 xlist = xpause = xtty = 0;
3358 buffer[0] = '\0';
3359 for (bp = buffer; *cp; cp++)
3360 if (*cp == '%') {
3361 switch (*++cp) {
3362 case 'a': /* additional arguments */
3363 {
3364 register char **ap,
3365 **ep;
3366 char *s = "";
3367
3368 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
3369 *ap;
3370 ap++, ep++) {
3371 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
3372 bp += strlen (bp);
3373 s = " ";
3374 }
3375 }
3376 break;
3377
3378 case 'd': /* content description */
3379 if (ct -> c_descr) {
3380 char *s;
3381
3382 (void) strcpy (bp, s = trimcpy (ct -> c_descr));
3383 free (s);
3384 }
3385 break;
3386
3387 case 'e': /* exclusive execution */
3388 xtty = 1;
3389 break;
3390
3391 case 'F': /* %e and %f */
3392 xtty = 1;
3393 /* and fall... */
3394 case 'f': /* filename(s) */
3395 {
3396 char *s = "";
3397
3398 for (part = m -> mp_parts;
3399 part;
3400 part = part -> mp_next) {
3401 p = part -> mp_part;
3402
3403 (void) sprintf (bp, "%s'%s'", s, p -> c_storage);
3404 bp += strlen (bp);
3405 s = " ";
3406 }
3407 }
3408 break;
3409
3410 case 'p': /* pause prior to displaying content */
3411 xpause = pausesw;
3412 /* and fall... */
3413 case 'l': /* display listing prior to displaying
3414 content */
3415 xlist = !nolist;
3416 break;
3417
3418 case 's': /* subtype */
3419 (void) strcpy (bp, ci -> ci_subtype);
3420 break;
3421
3422 case '%':
3423 goto raw;
3424
3425 default:
3426 *bp++ = *--cp;
3427 *bp = '\0';
3428 continue;
3429 }
3430 bp += strlen (bp);
3431 }
3432 else {
3433 raw: ;
3434 *bp++ = *cp;
3435 *bp = '\0';
3436 }
3437 if (ct -> c_termproc) {
3438 char term[BUFSIZ];
3439
3440 (void) strcpy (term, buffer);
3441 (void) sprintf (buffer, ct -> c_termproc, term);
3442 }
3443
3444 return show_content_aux2 (ct, serial, alternate, NULLCP, buffer,
3445 NOTOK, xlist, xpause, 0, xtty);
3446 }
3447
3448
3449 /* ARGSUSED */
3450
3451 static int store_multi (ct, unused)
3452 register CT ct;
3453 char *unused;
3454 {
3455 int result;
3456 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3457 register struct part *part;
3458
3459 result = NOTOK;
3460 for (part = m -> mp_parts; part; part = part -> mp_next) {
3461 register CT p = part -> mp_part;
3462
3463 if (part_ok (p, 1)
3464 && type_ok (p, 1)
3465 && p -> c_ctstorefnx
3466 && (result = (*p -> c_ctstorefnx) (p, NULLCP)) == OK
3467 && ct -> c_subtype == MULTI_ALTERNATE)
3468 break;
3469 }
3470
3471 return result;
3472 }
3473
3474
3475 static int free_multi (ct)
3476 register CT ct;
3477 {
3478 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3479 register struct part *part,
3480 *next;
3481
3482 if (!m)
3483 return;
3484
3485 if (m -> mp_start)
3486 free (m -> mp_start);
3487 if (m -> mp_stop)
3488 free (m -> mp_stop);
3489
3490 for (part = m -> mp_parts; part; part = next) {
3491 next = part -> mp_next;
3492
3493 free_content (part -> mp_part);
3494
3495 free ((char *) part);
3496 }
3497 m -> mp_parts = NULL;
3498
3499 free ((char *) m);
3500 ct -> c_ctparams = NULL;
3501 }
3502
3503
3504 static struct k2v SubMultiPart[] = {
3505 "mixed", MULTI_MIXED,
3506 "alternative", MULTI_ALTERNATE,
3507 "digest", MULTI_DIGEST,
3508 "parallel", MULTI_PARALLEL,
3509
3510 NULL, MULTI_UNKNOWN /* this one must be last! */
3511 };
3512
3513 static int InitMultiPart (ct)
3514 register CT ct;
3515 {
3516 int inout;
3517 long last,
3518 pos;
3519 register char *cp,
3520 *dp,
3521 **ap,
3522 **ep;
3523 char *bp,
3524 buffer[BUFSIZ];
3525 register struct multipart *m;
3526 register struct k2v *kv;
3527 register struct part *part,
3528 **next;
3529 register CI ci = &ct -> c_ctinfo;
3530 register CT p;
3531 FILE *fp;
3532
3533 ct -> c_ctshowfnx = NULL;
3534 ct -> c_ctstorefnx = NULL;
3535
3536 if (ct -> c_encoding != CE_7BIT) {
3537 admonish (NULLCP,
3538 "\"%s/%s\" type in message %s should be encoded in 7bit",
3539 ci -> ci_type, ci -> ci_subtype, ct -> c_file);
3540 return NOTOK;
3541 }
3542
3543 for (kv = SubMultiPart; kv -> kv_key; kv++)
3544 if (uleq (ci -> ci_subtype, kv -> kv_key))
3545 break;
3546 ct -> c_subtype = kv -> kv_value;
3547
3548 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3549 if (uleq (*ap, "boundary")) {
3550 bp = *ep;
3551 break;
3552 }
3553 if (!*ap) {
3554 advise (NULLCP,
3555 "a \"boundary\" parameter is mandatory for \"%s/%s\" type in message %s's %s: field",
3556 ci -> ci_type, ci -> ci_subtype, ct -> c_file, TYPE_FIELD);
3557 return NOTOK;
3558 }
3559
3560 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
3561 adios (NULLCP, "out of memory");
3562 ct -> c_ctparams = (caddr_t) m;
3563 ct -> c_ctlistfnx = list_multi;
3564 ct -> c_ctshowfnx = ct -> c_subtype != MULTI_UNKNOWN ? show_multi
3565 : show_unknown_multi;
3566 ct -> c_ctstorefnx = store_multi;
3567 ct -> c_ctfreefnx = free_multi;
3568
3569 for (cp = bp; isspace (*cp); cp++)
3570 continue;
3571 if (!*cp) {
3572 advise (NULLCP, "invalid \"boundary\" parameter for \"%s/%s\" type in message %s's %s: field",
3573 ci -> ci_type, ci -> ci_subtype, ct -> c_file, TYPE_FIELD);
3574 return NOTOK;
3575 }
3576 for (cp = bp, dp = cp + strlen (cp) - 1; dp > cp; dp--)
3577 if (!isspace (*dp))
3578 break;
3579 *++dp = '\0';
3580 m -> mp_start = concat (bp, "\n", NULLCP);
3581 m -> mp_stop = concat (bp, "--\n", NULLCP);
3582
3583 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
3584 advise (ct -> c_file, "unable to open for reading");
3585 return NOTOK;
3586 }
3587
3588 (void) fseek (fp = ct -> c_fp, pos = ct -> c_begin, 0);
3589 last = ct -> c_end;
3590
3591 next = &m -> mp_parts, part = NULL, inout = 1;
3592 while (fgets (buffer, sizeof buffer - 1, fp)) {
3593 if (pos > last)
3594 break;
3595
3596 pos += strlen (buffer);
3597
3598 if (buffer[0] != '-' || buffer[1] != '-')
3599 continue;
3600
3601 if (inout) {
3602 if (strcmp (buffer + 2, m -> mp_start))
3603 continue;
3604
3605 next_part: ;
3606 if ((part = (struct part *) calloc (1, sizeof *part)) == NULL)
3607 adios (NULLCP, "out of memory");
3608 *next = part, next = &part -> mp_next;
3609
3610 if ((p = get_content (fp, ct -> c_file,
3611 rfc934sw && ct -> c_subtype == MULTI_DIGEST
3612 ? -1 : 0)) == NULLCT) {
3613 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
3614 return NOTOK;
3615 }
3616 p -> c_fp = NULL;
3617
3618 part -> mp_part = p;
3619 (void) fseek (fp, pos = p -> c_begin, 0);
3620 inout = 0;
3621 }
3622 else
3623 if (strcmp (buffer + 2, m -> mp_start) == 0) {
3624 inout = 1;
3625
3626 end_part: ;
3627 p = part -> mp_part;
3628 p -> c_end = ftell (fp) - (strlen (buffer) + 1);
3629 if (p -> c_end < p -> c_begin)
3630 p -> c_begin = p -> c_end;
3631 if (inout)
3632 goto next_part;
3633 goto last_part;
3634 }
3635 else
3636 if (strcmp (buffer + 2, m -> mp_stop) == 0)
3637 goto end_part;
3638 }
3639 advise (NULLCP, "bogus multipart content in message %s", ct -> c_file);
3640 if (!inout && part) {
3641 p = part -> mp_part;
3642 p -> c_end = ct -> c_end;
3643
3644 if (p -> c_begin >= p -> c_end) {
3645 for (next = &m -> mp_parts;
3646 *next != part;
3647 next = &((*next) -> mp_next))
3648 continue;
3649 *next = NULL;
3650 free_content (p);
3651 free ((char *) part);
3652 }
3653 }
3654
3655 last_part: ;
3656 if (ct -> c_subtype == MULTI_ALTERNATE
3657 && m -> mp_parts
3658 && m -> mp_parts -> mp_next) {
3659 register int i;
3660 register struct part **base,
3661 **bmp;
3662
3663 i = 0;
3664 for (part = m -> mp_parts; part; part = part -> mp_next)
3665 i++;
3666 if ((base = (struct part **) calloc ((unsigned) (i + 1), sizeof *base))
3667 == NULL)
3668 adios (NULLCP, "out of memory");
3669 bmp = base;
3670 for (part = m -> mp_parts; part; part = part -> mp_next)
3671 *bmp++ = part;
3672 *bmp = NULL;
3673
3674 next = &m -> mp_parts;
3675 for (bmp--; bmp >= base; bmp--) {
3676 part = *bmp;
3677 *next = part, next = &part -> mp_next;
3678 }
3679 *next = NULL;
3680
3681 free ((char *) base);
3682 }
3683
3684 {
3685 int partnum;
3686 register char *pp;
3687 char partnam[BUFSIZ];
3688
3689 if (ct -> c_partno) {
3690 (void) sprintf (partnam, "%s.", ct -> c_partno);
3691 pp = partnam + strlen (partnam);
3692 }
3693 else
3694 pp = partnam;
3695
3696 for (part = m -> mp_parts, partnum = 1;
3697 part;
3698 part = part -> mp_next, partnum++) {
3699 p = part -> mp_part;
3700
3701 (void) sprintf (pp, "%d", partnum);
3702 p -> c_partno = add (partnam, NULLCP);
3703
3704 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK) {
3705 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
3706 return NOTOK;
3707 }
3708 }
3709 }
3710
3711 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
3712
3713 return OK;
3714 }
3715
3716 /* \f MESSAGE */
3717
3718 #define MESSAGE_UNKNOWN 0x00
3719 #define MESSAGE_RFC822 0x01
3720 #define MESSAGE_PARTIAL 0x02
3721 #define MESSAGE_EXTERNAL 0x03
3722
3723
3724 struct partial {
3725 char *pm_partid;
3726
3727 int pm_partno;
3728 int pm_maxno;
3729
3730 int pm_marked;
3731 int pm_stored;
3732 };
3733
3734
3735 static int list_partial (ct, toplevel)
3736 register CT ct;
3737 int toplevel;
3738 {
3739 register struct partial *p = (struct partial *) ct -> c_ctparams;
3740
3741 (void) list_content (ct, toplevel);
3742 if (verbosw) {
3743 printf ("\t [message %s, part %d", p -> pm_partid, p -> pm_partno);
3744 if (p -> pm_maxno)
3745 printf (" of %d", p -> pm_maxno);
3746 printf ("]\n");
3747 }
3748
3749 return OK;
3750 }
3751
3752
3753 static int ct_compar (a, b)
3754 CT *a,
3755 *b;
3756 {
3757 register struct partial *am = (struct partial *) ((*a) -> c_ctparams);
3758 register struct partial *bm = (struct partial *) ((*b) -> c_ctparams);
3759
3760 return (am -> pm_marked - bm -> pm_marked);
3761 }
3762
3763
3764 /* ARGSUSED */
3765
3766 static int store_partial (ct, unused)
3767 register CT ct;
3768 char *unused;
3769 {
3770 int cur,
3771 hi,
3772 i;
3773 register CT p,
3774 *ctp,
3775 *ctq;
3776 CT *base;
3777 struct partial *qm = (struct partial *) ct -> c_ctparams;
3778
3779 if (qm -> pm_stored)
3780 return OK;
3781
3782 hi = i = 0;
3783 for (ctp = cts; p = *ctp; ctp++)
3784 if (p -> c_type == CT_MESSAGE && p -> c_subtype == ct -> c_subtype) {
3785 register struct partial *pm = (struct partial *) p -> c_ctparams;
3786
3787 if (!pm -> pm_stored
3788 && strcmp (qm -> pm_partid, pm -> pm_partid) == 0) {
3789 pm -> pm_marked = pm -> pm_partno;
3790 if (pm -> pm_maxno)
3791 hi = pm -> pm_maxno;
3792 pm -> pm_stored = 1;
3793 i++;
3794 }
3795 else
3796 pm -> pm_marked = 0;
3797 }
3798 if (hi == 0) {
3799 advise (NULLCP, "missing (at least) last part of multipart message");
3800 return NOTOK;
3801 }
3802
3803 if ((base = (CT *) calloc ((unsigned) (i + 1), sizeof *base)) == NULL)
3804 adios (NULLCP, "out of memory");
3805
3806 ctq = base;
3807 for (ctp = cts; p = *ctp; ctp++)
3808 if (p -> c_type == CT_MESSAGE && p -> c_subtype == ct -> c_subtype) {
3809 register struct partial *pm = (struct partial *) p -> c_ctparams;
3810
3811 if (pm -> pm_marked)
3812 *ctq++ = p;
3813 }
3814 *ctq = NULL;
3815
3816 if (i > 1)
3817 qsort ((char *) base, i, sizeof *base, ct_compar);
3818
3819 cur = 1;
3820 for (ctq = base; p = *ctq; ctq++) {
3821 register struct partial *pm = (struct partial *) p -> c_ctparams;
3822
3823 if (pm -> pm_marked != cur) {
3824 if (pm -> pm_marked == cur - 1) {
3825 admonish (NULLCP,
3826 "duplicate part %d of %d part multipart message",
3827 pm -> pm_marked, hi);
3828 continue;
3829 }
3830
3831 missing_part: ;
3832 advise (NULLCP,
3833 "missing %spart %d of %d part multipart message",
3834 cur != hi ? "(at least) " : "", cur, hi);
3835 goto losing;
3836 }
3837 else
3838 cur++;
3839 }
3840 if (hi != --cur) {
3841 cur = hi;
3842 goto missing_part;
3843 }
3844
3845 ctq = base;
3846 ct = *ctq++;
3847 if (store_content (ct, "") == NOTOK) {
3848 losing: ;
3849 free ((char *) base);
3850 return NOTOK;
3851 }
3852
3853 for (; p = *ctq; ctq++)
3854 if (store_content (p, ct -> c_storage) == NOTOK)
3855 goto losing;
3856
3857 free ((char *) base);
3858 return OK;
3859 }
3860
3861
3862 static int free_partial (ct)
3863 register CT ct;
3864 {
3865 register struct partial *p = (struct partial *) ct -> c_ctparams;
3866
3867 if (!p)
3868 return;
3869
3870 if (p -> pm_partid)
3871 free (p -> pm_partid);
3872
3873 free ((char *) p);
3874 ct -> c_ctparams = NULL;
3875 }
3876
3877
3878 struct exbody {
3879 CT eb_parent;
3880 CT eb_content;
3881 char *eb_partno;
3882
3883 char *eb_access;
3884 int eb_flags;
3885
3886 char *eb_name;
3887 char *eb_permission;
3888
3889 char *eb_site;
3890 char *eb_dir;
3891 char *eb_mode;
3892 unsigned long
3893 eb_size;
3894
3895 char *eb_server;
3896 char *eb_subject;
3897 char *eb_body;
3898 };
3899
3900
3901 static int openFile ();
3902 static int openFTP ();
3903 static int openMail ();
3904
3905 /* NOTE WELL: si_key MUST NOT have value of NOTOK */
3906
3907 static struct str2init str2methods[] = {
3908 "afs", 1, openFile,
3909 "anon-ftp", 1, openFTP,
3910 "ftp", 0, openFTP,
3911 "local-file", 0, openFile,
3912 "mail-server", 0, openMail,
3913
3914 NULL
3915 };
3916
3917
3918 static int params_external (ct, composing)
3919 register CT ct;
3920 int composing;
3921 {
3922 register char **ap,
3923 **ep;
3924 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
3925 register CI ci = &ct -> c_ctinfo;
3926
3927 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++) {
3928 if (uleq (*ap, "access-type")) {
3929 register struct str2init *s2i;
3930 register CT p = e -> eb_content;
3931
3932 for (s2i = str2methods; s2i -> si_key; s2i++)
3933 if (uleq (*ep, s2i -> si_key))
3934 break;
3935 if (!s2i -> si_key) {
3936 e -> eb_access = *ep;
3937 e -> eb_flags = NOTOK;
3938 p -> c_encoding = CE_EXTERNAL;
3939 continue;
3940 }
3941 e -> eb_access = s2i -> si_key;
3942 e -> eb_flags = s2i -> si_val;
3943 p -> c_encoding = CE_EXTERNAL;
3944 if (init_encoding (p, s2i -> si_init) == NOTOK)
3945 return NOTOK;
3946 continue;
3947 }
3948 if (uleq (*ap, "name")) {
3949 e -> eb_name = *ep;
3950 continue;
3951 }
3952 if (uleq (*ap, "permission")) {
3953 e -> eb_permission = *ep;
3954 continue;
3955 }
3956 if (uleq (*ap, "site")) {
3957 e -> eb_site = *ep;
3958 continue;
3959 }
3960 if (uleq (*ap, "directory")) {
3961 e -> eb_dir = *ep;
3962 continue;
3963 }
3964 if (uleq (*ap, "mode")) {
3965 e -> eb_mode = *ep;
3966 continue;
3967 }
3968 if (uleq (*ap, "size")) {
3969 (void) sscanf (*ep, "%lu", &e -> eb_size);
3970 continue;
3971 }
3972 if (uleq (*ap, "server")) {
3973 e -> eb_server = *ep;
3974 continue;
3975 }
3976 if (uleq (*ap, "subject")) {
3977 e -> eb_subject = *ep;
3978 continue;
3979 }
3980 if (composing && uleq (*ap, "body")) {
3981 e -> eb_body = getcpy (*ep);
3982 continue;
3983 }
3984 }
3985
3986 if (!e -> eb_access) {
3987 advise (NULLCP,
3988 "invalid parameters for \"%s/%s\" type in message %s's %s field",
3989 ci -> ci_type, ci -> ci_subtype,
3990 ct -> c_file, TYPE_FIELD);
3991 return NOTOK;
3992 }
3993
3994 return OK;
3995 }
3996
3997 static int list_external (ct, toplevel)
3998 register CT ct;
3999 int toplevel;
4000 {
4001 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4002
4003 (void) list_content (ct, toplevel);
4004 if (verbosw) {
4005 if (e -> eb_name)
4006 printf ("\t retrieve %s\n", e -> eb_name);
4007 if (e -> eb_dir)
4008 printf ("\t in directory %s\n", e -> eb_dir);
4009 if (e -> eb_site)
4010 printf ("\t from %s\n", e -> eb_site);
4011 if (e -> eb_server)
4012 printf ("\t from mailbox %s\n", e -> eb_server);
4013 if (e -> eb_subject)
4014 printf ("\t with subject %s\n", e -> eb_subject);
4015 printf ("\t using %s", e -> eb_access);
4016 if (e -> eb_mode)
4017 printf (" (in %s mode)", e -> eb_mode);
4018 if (e -> eb_permission)
4019 printf (" (permission %s)", e -> eb_permission);
4020 if (e -> eb_flags == NOTOK)
4021 printf (" [service unavailable]");
4022 printf ("\n");
4023 }
4024 (void) list_content (e -> eb_content, 0);
4025
4026 return OK;
4027 }
4028
4029
4030 static int show_external (ct, serial, alternate)
4031 register CT ct;
4032 int serial,
4033 alternate;
4034 {
4035 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4036 register CT p = e -> eb_content;
4037
4038 if (!type_ok (p, 0))
4039 return OK;
4040
4041 if (p -> c_ctshowfnx)
4042 return (*p -> c_ctshowfnx) (p, serial, alternate);
4043
4044 content_error (NULLCP, p, "don't know how to display content");
4045 return NOTOK;
4046 }
4047
4048
4049 static int store_external (ct)
4050 register CT ct;
4051 {
4052 int result = NOTOK;
4053 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4054 register CT p = e -> eb_content;
4055
4056 if (!type_ok (p, 1))
4057 return OK;
4058
4059 p -> c_partno = ct -> c_partno;
4060 if (p -> c_ctstorefnx)
4061 result = (*p -> c_ctstorefnx) (p, NULLCP);
4062 p -> c_partno = NULL;
4063
4064 return result;
4065 }
4066
4067
4068 static int free_external (ct)
4069 register CT ct;
4070 {
4071 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4072
4073 if (!e)
4074 return;
4075
4076 free_content (e -> eb_content);
4077 if (e -> eb_body)
4078 free (e -> eb_body);
4079
4080 free ((char *) e);
4081 ct -> c_ctparams = NULL;
4082 }
4083
4084
4085 static struct k2v SubMessage[] = {
4086 "rfc822", MESSAGE_RFC822,
4087 "partial", MESSAGE_PARTIAL,
4088 "external-body", MESSAGE_EXTERNAL,
4089
4090 NULL, MESSAGE_UNKNOWN /* this one must be last! */
4091 };
4092
4093 static int InitMessage (ct)
4094 register CT ct;
4095 {
4096 register struct k2v *kv;
4097 register CI ci = &ct -> c_ctinfo;
4098
4099 if (ct -> c_encoding != CE_7BIT) {
4100 admonish (NULLCP,
4101 "\"%s/%s\" type in message %s should be encoded in 7bit",
4102 ci -> ci_type, ci -> ci_subtype, ct -> c_file);
4103 return NOTOK;
4104 }
4105
4106 if (!*ci -> ci_subtype) /* XXX: attmail bogosity! */
4107 ci -> ci_subtype = add ("rfc822", ci -> ci_subtype);
4108 for (kv = SubMessage; kv -> kv_key; kv++)
4109 if (uleq (ci -> ci_subtype, kv -> kv_key))
4110 break;
4111
4112 switch (ct -> c_subtype = kv -> kv_value) {
4113 case MESSAGE_RFC822:
4114 ct -> c_showproc = add ("%pshow -file '%F'", NULLCP);
4115 break;
4116
4117 case MESSAGE_PARTIAL:
4118 {
4119 register char **ap,
4120 **ep;
4121 register struct partial *p;
4122
4123 ct -> c_ctshowfnx = NULL;
4124 ct -> c_ctstorefnx = NULL;
4125
4126 if ((p = (struct partial *) calloc (1, sizeof *p)) == NULL)
4127 adios (NULLCP, "out of memory");
4128 ct -> c_ctparams = (caddr_t) p;
4129 ct -> c_ctfreefnx = free_partial;
4130
4131 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
4132 *ap;
4133 ap++, ep++) {
4134 if (uleq (*ap, "id")) {
4135 p -> pm_partid = add (*ep, NULLCP);
4136
4137 continue;
4138 }
4139
4140 if (uleq (*ap, "number")) {
4141 if (sscanf (*ep, "%d", &p -> pm_partno) != 1
4142 || p -> pm_partno < 1) {
4143 invalid_param: ;
4144 advise (NULLCP,
4145 "invalid %s parameter for \"%s/%s\" type in message %s's %s field",
4146 *ap, ci -> ci_type, ci -> ci_subtype,
4147 ct -> c_file, TYPE_FIELD);
4148 return NOTOK;
4149 }
4150
4151 continue;
4152 }
4153
4154 if (uleq (*ap, "total")) {
4155 if (sscanf (*ep, "%d", &p -> pm_maxno) != 1
4156 || p -> pm_maxno < 1)
4157 goto invalid_param;
4158
4159 continue;
4160 }
4161 }
4162
4163 if (!p -> pm_partid
4164 || !p -> pm_partno
4165 || (p -> pm_maxno && p -> pm_partno > p -> pm_maxno)) {
4166 advise (NULLCP,
4167 "invalid parameters for \"%s/%s\" type in message %s's %s field",
4168 ci -> ci_type, ci -> ci_subtype,
4169 ct -> c_file, TYPE_FIELD);
4170 return NOTOK;
4171 }
4172
4173 ct -> c_ctlistfnx = list_partial;
4174 ct -> c_ctstorefnx = store_partial;
4175 }
4176 break;
4177
4178 case MESSAGE_EXTERNAL:
4179 {
4180 int exresult;
4181 register struct exbody *e;
4182 CT p;
4183 FILE *fp;
4184
4185 ct -> c_ctshowfnx = NULL;
4186 ct -> c_ctstorefnx = NULL;
4187
4188 if ((e = (struct exbody *) calloc (1, sizeof *e)) == NULL)
4189 adios (NULLCP, "out of memory");
4190 ct -> c_ctparams = (caddr_t) e;
4191 ct -> c_ctfreefnx = free_external;
4192
4193 if (!ct -> c_fp
4194 && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
4195 advise (ct -> c_file, "unable to open for reading");
4196 return NOTOK;
4197 }
4198
4199 (void) fseek (fp = ct -> c_fp, ct -> c_begin, 0);
4200
4201 if ((p = get_content (fp, ct -> c_file, 0)) == NULLCT) {
4202 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
4203 return NOTOK;
4204 }
4205
4206 e -> eb_parent = ct;
4207 e -> eb_content = p;
4208 p -> c_ctextern = (caddr_t) e;
4209 if ((exresult = params_external (ct, 0)) != NOTOK
4210 && p -> c_ceopenfnx == openMail) {
4211 int cc,
4212 size;
4213 char *bp;
4214
4215 if ((size = ct -> c_end - p -> c_begin) <= 0) {
4216 if (!e -> eb_subject)
4217 content_error (NULLCP, ct,
4218 "empty body for access-type=mail-server");
4219 goto no_body;
4220 }
4221
4222 if ((e -> eb_body = bp = malloc ((unsigned) size)) == NULL)
4223 adios (NULLCP, "out of memory");
4224 (void) fseek (p -> c_fp, p -> c_begin, 0);
4225 while (size > 0)
4226 switch (cc = fread (bp, sizeof *bp, size, p -> c_fp)) {
4227 case NOTOK:
4228 adios ("failed", "fread");
4229
4230 case OK:
4231 adios (NULLCP, "unexpected EOF from fread");
4232
4233 default:
4234 bp += cc, size -= cc;
4235 break;
4236 }
4237 *bp = 0;
4238 no_body: ;
4239 }
4240 p -> c_fp = NULL;
4241 p -> c_end = p -> c_begin;
4242
4243 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
4244
4245 ct -> c_ctlistfnx = list_external;
4246
4247 if (exresult == NOTOK)
4248 return NOTOK;
4249 if (e -> eb_flags == NOTOK)
4250 return OK;
4251
4252 if (e -> eb_name && autosw) {
4253 char *cp = e -> eb_name;
4254
4255 if (*cp != '/'
4256 && *cp != '.'
4257 && *cp != '|'
4258 && *cp != '!'
4259 && !index (cp, '%')) {
4260 if (!ct -> c_storeproc)
4261 ct -> c_storeproc = add (cp, NULLCP);
4262 if (!p -> c_storeproc)
4263 p -> c_storeproc = add (cp, NULLCP);
4264 }
4265 }
4266
4267 ct -> c_ctshowfnx = show_external;
4268 ct -> c_ctstorefnx = store_external;
4269 switch (p -> c_type) {
4270 case CT_MULTIPART:
4271 break;
4272
4273 case CT_MESSAGE:
4274 if (p -> c_subtype != MESSAGE_RFC822)
4275 break;
4276 /* else fall... */
4277 default:
4278 e -> eb_partno = ct -> c_partno;
4279 if (p -> c_ctinitfnx)
4280 (void) (*p -> c_ctinitfnx) (p);
4281 break;
4282 }
4283 }
4284 break;
4285
4286 default:
4287 break;
4288 }
4289
4290 return OK;
4291 }
4292
4293 /* \f APPLICATION */
4294
4295 #define APPLICATION_UNKNOWN 0x00
4296 #define APPLICATION_OCTETS 0x01
4297 #define APPLICATION_POSTSCRIPT 0x02
4298
4299
4300 static int list_application (ct, toplevel)
4301 register CT ct;
4302 int toplevel;
4303 {
4304 (void) list_content (ct, toplevel);
4305 if (verbosw) {
4306 register char **ap,
4307 **ep;
4308 register CI ci = &ct -> c_ctinfo;
4309
4310 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
4311 printf ("\t %s=\"%s\"\n", *ap, *ep);
4312 }
4313
4314 return OK;
4315 }
4316
4317
4318 static struct k2v SubApplication[] = {
4319 "octet-stream", APPLICATION_OCTETS,
4320 "postscript", APPLICATION_POSTSCRIPT,
4321 NULL, APPLICATION_UNKNOWN /* this one must be last! */
4322 };
4323
4324 static int InitApplication (ct)
4325 register CT ct;
4326 {
4327 register char **ap,
4328 **ep;
4329 register struct k2v *kv;
4330 register CI ci = &ct -> c_ctinfo;
4331
4332 ct -> c_ctlistfnx = list_application;
4333
4334 for (kv = SubApplication; kv -> kv_key; kv++)
4335 if (uleq (ci -> ci_subtype, kv -> kv_key))
4336 break;
4337
4338 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
4339 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
4340 register char *cp;
4341
4342 if (*(cp = *ep) != '/'
4343 && *cp != '.'
4344 && *cp != '|'
4345 && *cp != '!'
4346 && !index (cp, '%'))
4347 ct -> c_storeproc = add (cp, NULLCP);
4348 }
4349
4350 if ((ct -> c_subtype = kv -> kv_value) == APPLICATION_OCTETS) {
4351 int tarP,
4352 zP;
4353
4354 tarP = zP = 0;
4355 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++) {
4356 if (uleq (*ap, "type")) {
4357 if (!uleq (*ep, "tar"))
4358 break;
4359
4360 tarP = 1;
4361 continue;
4362 }
4363
4364 if ((uleq (*ap, "conversions") || uleq (*ap, "x-conversions"))
4365 && (uleq (*ep, "compress") || uleq (*ep, "x-compress"))) {
4366 zP = 1;
4367 continue;
4368 }
4369 }
4370
4371 if (tarP) {
4372 ct -> c_showproc = add (zP ? "%euncompress | tar tvf -"
4373 : "%etar tvf -", NULLCP);
4374 if (!ct -> c_storeproc)
4375 if (autosw) {
4376 ct -> c_storeproc = add (zP ? "| uncompress | tar xvpf -"
4377 : "| tar xvpf -", NULLCP);
4378 ct -> c_umask = 0022;
4379 }
4380 else
4381 ct -> c_storeproc = add (zP ? "%m%P.tar.Z" : "%m%P.tar",
4382 NULLCP);
4383 }
4384 }
4385
4386 return OK;
4387 }
4388
4389 /* \f ENCODINGS */
4390
4391 #include "md5.c"
4392
4393
4394 struct cefile {
4395 char *ce_file;
4396 int ce_unlink;
4397
4398 FILE *ce_fp;
4399 };
4400
4401
4402 static int list_encoding (ct)
4403 register CT ct;
4404 {
4405 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4406
4407 if (ce)
4408 fprintf (stderr, " decoded fp 0x%x file \"%s\"\n", ce -> ce_fp,
4409 ce -> ce_file ? ce -> ce_file : "");
4410
4411 return OK;
4412 }
4413
4414
4415 static int close_encoding (ct)
4416 register CT ct;
4417 {
4418 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4419
4420 if (!ce)
4421 return;
4422
4423 if (ce -> ce_fp) {
4424 (void) fclose (ce -> ce_fp);
4425 ce -> ce_fp = NULL;
4426 }
4427 }
4428
4429
4430 static unsigned long size_encoding (ct)
4431 register CT ct;
4432 {
4433 int fd;
4434 unsigned long size;
4435 char *file;
4436 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4437 struct stat st;
4438
4439 if (!ce) {
4440 estimate: ;
4441
4442 return (ct -> c_end - ct -> c_begin);
4443 }
4444
4445 if (ce -> ce_fp && fstat (fileno (ce -> ce_fp), &st) != NOTOK)
4446 return (long) st.st_size;
4447
4448 if (ce -> ce_file)
4449 return stat (ce -> ce_file, &st) != NOTOK ? (long) st.st_size : 0L;
4450
4451 if (ct -> c_encoding == CE_EXTERNAL)
4452 goto estimate;
4453
4454 file = NULL;
4455 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
4456 goto estimate;
4457
4458 size = fstat (fd, &st) != NOTOK ? (long) st.st_size : 0L;
4459
4460 (*ct -> c_ceclosefnx) (ct);
4461
4462 return size;
4463 }
4464
4465
4466 static int free_encoding (ct, toplevel)
4467 register CT ct;
4468 int toplevel;
4469 {
4470 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4471
4472 if (!ce)
4473 return;
4474
4475 if (ce -> ce_fp) {
4476 (void) fclose (ce -> ce_fp);
4477 ce -> ce_fp = NULL;
4478 }
4479
4480 if (ce -> ce_file) {
4481 if (ce -> ce_unlink)
4482 (void) unlink (ce -> ce_file);
4483 free (ce -> ce_file);
4484 }
4485
4486 if (toplevel) {
4487 free ((char *) ce);
4488 ct -> c_ceparams = NULL;
4489 }
4490 else
4491 ct -> c_ceopenfnx = NULL;
4492 }
4493
4494
4495 static init_encoding (ct, openfnx)
4496 register CT ct;
4497 int (*openfnx) ();
4498 {
4499 register struct cefile *ce;
4500
4501 if ((ce = (struct cefile *) calloc (1, sizeof *ce)) == NULL)
4502 adios (NULLCP, "out of memory");
4503
4504 ct -> c_ceparams = (caddr_t) ce;
4505 ct -> c_ceopenfnx = openfnx;
4506 ct -> c_ceclosefnx = close_encoding;
4507 ct -> c_cesizefnx = size_encoding;
4508 ct -> c_celistfnx = list_encoding;
4509 ct -> c_cefreefnx = free_encoding;
4510
4511 return OK;
4512 }
4513
4514 /* \f BASE64 */
4515
4516 static unsigned char b642nib[0x80] = {
4517 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4518 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4519 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4520 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4521 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4522 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
4523 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
4524 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
4525 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
4526 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
4527 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
4528 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
4529 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
4530 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
4531 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
4532 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
4533 };
4534
4535
4536 static int openBase64 (ct, file)
4537 register CT ct;
4538 char **file;
4539 {
4540 int bitno,
4541 cc,
4542 digested,
4543 fd,
4544 len,
4545 skip;
4546 unsigned long bits;
4547 register char *cp,
4548 *ep;
4549 unsigned char value,
4550 *b = (unsigned char *) &bits,
4551 *b1 = &b[endian > 0 ? 1 : 2],
4552 *b2 = &b[endian > 0 ? 2 : 1],
4553 *b3 = &b[endian > 0 ? 3 : 0];
4554 char buffer[BUFSIZ];
4555 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4556 MD5_CTX mdContext;
4557
4558 if (ce -> ce_fp)
4559 goto ready_to_go;
4560 if (ce -> ce_file) {
4561 if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
4562 content_error (ce -> ce_file, ct, "unable to fopen for reading");
4563 return NOTOK;
4564 }
4565
4566 *file = ce -> ce_file;
4567 return fileno (ce -> ce_fp);
4568 }
4569
4570 ce -> ce_unlink = *file == NULL;
4571 if ((ce -> ce_fp = fopen (ce -> ce_file =
4572 add (*file ? *file : m_scratch ("", tmp),
4573 NULLCP),
4574 "w+")) == NULL) {
4575 content_error (ce -> ce_file, ct,
4576 "unable to fopen for writing and reading");
4577 return NOTOK;
4578 }
4579
4580 if ((len = ct -> c_end - ct -> c_begin) < 0)
4581 adios (NULLCP, "internal error(1)");
4582
4583 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
4584 content_error (ct -> c_file, ct, "unable to open for reading");
4585 return NOTOK;
4586 }
4587
4588 if (digested = ct -> c_digested)
4589 MD5Init (&mdContext);
4590
4591 (void) lseek (fd = fileno (ct -> c_fp), (off_t)ct -> c_begin, 0);
4592 bitno = 18, bits = 0L, skip = 0;
4593 while (len > 0)
4594 switch (cc = read (fd, buffer, sizeof buffer - 1)) {
4595 case NOTOK:
4596 content_error (ct -> c_file, ct, "error reading from");
4597 goto clean_up;
4598
4599 case OK:
4600 content_error (NULLCP, ct, "premature eof");
4601 goto clean_up;
4602
4603 default:
4604 if (cc > len)
4605 cc = len;
4606 len -= cc;
4607
4608 for (ep = (cp = buffer) + cc; cp < ep; cp++)
4609 switch (*cp) {
4610 default:
4611 if (isspace (*cp))
4612 break;
4613 if (skip
4614 || (*cp & 0x80)
4615 || (value = b642nib[*cp & 0x7f]) > 0x3f) {
4616 if (debugsw)
4617 fprintf (stderr,
4618 "*cp=0x%x pos=%ld skip=%d\n", *cp,
4619 (long) lseek (fd, (off_t)0, 1) - (ep - cp),
4620 skip);
4621 content_error (NULLCP, ct,
4622 "invalid BASE64 encoding -- continuing");
4623 continue;
4624 }
4625
4626 bits |= value << bitno;
4627 test_end: ;
4628 if ((bitno -= 6) < 0) {
4629 (void) putc ((char) *b1, ce -> ce_fp);
4630 if (digested)
4631 MD5Update (&mdContext, b1, 1);
4632 if (skip < 2) {
4633 (void) putc ((char) *b2, ce -> ce_fp);
4634 if (digested)
4635 MD5Update (&mdContext, b2, 1);
4636 if (skip < 1) {
4637 (void) putc ((char) *b3, ce -> ce_fp);
4638 if (digested)
4639 MD5Update (&mdContext, b3, 1);
4640 }
4641 }
4642
4643 if (ferror (ce -> ce_fp)) {
4644 content_error (ce -> ce_file, ct,
4645 "error writing to");
4646 goto clean_up;
4647 }
4648 bitno = 18, bits = 0L, skip = 0;
4649 }
4650 break;
4651
4652 case '=':
4653 if (++skip > 3)
4654 goto self_delimiting;
4655 goto test_end;
4656 }
4657 }
4658 if (bitno != 18) {
4659 if (debugsw)
4660 fprintf (stderr, "premature ending (bitno %d)\n", bitno);
4661
4662 content_error (NULLCP, ct, "invalid BASE64 encoding");
4663 goto clean_up;
4664 }
4665 self_delimiting: ;
4666 (void) fseek (ct -> c_fp, 0L, 0);
4667
4668 if (fflush (ce -> ce_fp)) {
4669 content_error (ce -> ce_file, ct, "error writing to");
4670 goto clean_up;
4671 }
4672
4673 if (digested) {
4674 unsigned char digest[16];
4675
4676 MD5Final (digest, &mdContext);
4677 if (bcmp ((char *) digest, (char *) ct -> c_digest,
4678 sizeof digest / sizeof digest[0]))
4679 content_error (NULLCP, ct,
4680 "content integrity suspect (digest mismatch) -- continuing");
4681 else
4682 if (debugsw)
4683 fprintf (stderr, "content integrity confirmed\n");
4684 }
4685
4686 ready_to_go: ;
4687 (void) fseek (ce -> ce_fp, 0L, 0);
4688 *file = ce -> ce_file;
4689 return fileno (ce -> ce_fp);
4690
4691 clean_up: ;
4692 free_encoding (ct, 0);
4693
4694 return NOTOK;
4695 }
4696
4697
4698 static int InitBase64 (ct)
4699 register CT ct;
4700 {
4701 return init_encoding (ct, openBase64);
4702 }
4703
4704
4705 static int set_endian ()
4706 {
4707 char *cp;
4708 union {
4709 long l;
4710 char c[sizeof (long)];
4711 } un;
4712
4713 un.l = 1;
4714 endian = un.c[0] ? -1 : 1;
4715 if (debugsw)
4716 fprintf (stderr, "%s endian architecture\n",
4717 endian > 0 ? "big" : "little");
4718
4719 mm_charset = getenv ("MM_CHARSET");
4720
4721 if ((cp = getenv ("MM_NOASK")) && strcmp (cp, "1") == 0) {
4722 nolist = 1, pausesw = 0;
4723 if (showsw)
4724 listsw = 0;
4725 }
4726 }
4727
4728 /* \f QUOTED */
4729
4730 static char hex2nib[0x80] = {
4731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4737 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
4738 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4739 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
4740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4743 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
4744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4747 };
4748
4749
4750 static int openQuoted (ct, file)
4751 register CT ct;
4752 char **file;
4753 {
4754 int cc,
4755 digested,
4756 len,
4757 quoted;
4758 register char *cp,
4759 *ep;
4760 char buffer[BUFSIZ];
4761 unsigned char mask;
4762 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4763 MD5_CTX mdContext;
4764
4765 if (ce -> ce_fp)
4766 goto ready_to_go;
4767 if (ce -> ce_file) {
4768 if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
4769 content_error (ce -> ce_file, ct, "unable to fopen for reading");
4770 return NOTOK;
4771 }
4772
4773 *file = ce -> ce_file;
4774 return fileno (ce -> ce_fp);
4775 }
4776
4777 ce -> ce_unlink = *file == NULL;
4778 if ((ce -> ce_fp = fopen (ce -> ce_file =
4779 add (*file ? *file : m_scratch ("", tmp),
4780 NULLCP),
4781 "w+")) == NULL) {
4782 content_error (ce -> ce_file, ct,
4783 "unable to fopen for writing and reading");
4784 return NOTOK;
4785 }
4786
4787 if ((len = ct -> c_end - ct -> c_begin) < 0)
4788 adios (NULLCP, "internal error(2)");
4789
4790 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
4791 content_error (ct -> c_file, ct, "unable to open for reading");
4792 return NOTOK;
4793 }
4794
4795 if (digested = ct -> c_digested)
4796 MD5Init (&mdContext);
4797
4798 (void) fseek (ct -> c_fp, ct -> c_begin, 0);
4799 quoted = 0;
4800 #ifdef lint
4801 mask = 0;
4802 #endif
4803 while (len > 0) {
4804 char *dp;
4805
4806 if (fgets (buffer, sizeof buffer - 1, ct -> c_fp) == NULL) {
4807 content_error (NULLCP, ct, "premature eof");
4808 goto clean_up;
4809 }
4810
4811 if ((cc = strlen (buffer)) > len)
4812 cc = len;
4813 len -= cc;
4814
4815 for (ep = (cp = buffer) + cc - 1; cp <= ep; ep--)
4816 if (!isspace (*ep))
4817 break;
4818 *++ep = '\n', ep++;
4819
4820 for (; cp < ep; cp++) {
4821 if (quoted) {
4822 if (quoted > 1) {
4823 if (!isxdigit (*cp)) {
4824 invalid_hex: ;
4825 dp = "expecting hexidecimal-digit";
4826 goto invalid_encoding;
4827 }
4828 mask <<= 4;
4829 mask |= hex2nib[*cp & 0x7f];
4830 (void) putc (mask, ce -> ce_fp);
4831 if (digested)
4832 MD5Update (&mdContext, &mask, 1);
4833 }
4834 else
4835 switch (*cp) {
4836 case ':':
4837 (void) putc (*cp, ce -> ce_fp);
4838 if (digested)
4839 MD5Update (&mdContext, (unsigned char *) ":",
4840 1);
4841 break;
4842
4843 default:
4844 if (!isxdigit (*cp))
4845 goto invalid_hex;
4846 mask = hex2nib[*cp & 0x7f];
4847 quoted = 2;
4848 continue;
4849 }
4850
4851 if (ferror (ce -> ce_fp)) {
4852 content_error (ce -> ce_file, ct, "error writing to");
4853 goto clean_up;
4854 }
4855 quoted = 0;
4856 continue;
4857 }
4858
4859 switch (*cp) {
4860 default:
4861 if (*cp < '!' || *cp > '~') {
4862 int i;
4863 dp = "expecting character in range [!..~]";
4864
4865 invalid_encoding: ;
4866 i = strlen (invo_name) + 2;
4867 content_error (NULLCP, ct,
4868 "invalid QUOTED-PRINTABLE encoding -- %s,\n%*.*sbut got char 0x%x",
4869 dp, i, i, "", *cp);
4870 goto clean_up;
4871 }
4872 /* and fall...*/
4873 case ' ':
4874 case '\t':
4875 case '\n':
4876 (void) putc (*cp, ce -> ce_fp);
4877 if (digested) {
4878 if (*cp == '\n')
4879 MD5Update (&mdContext, (unsigned char *) "\r\n",2);
4880 else
4881 MD5Update (&mdContext, (unsigned char *) cp, 1);
4882 }
4883 if (ferror (ce -> ce_fp)) {
4884 content_error (ce -> ce_file, ct, "error writing to");
4885 goto clean_up;
4886 }
4887 break;
4888
4889 case '=':
4890 if (*++cp != '\n') {
4891 quoted = 1;
4892 cp--;
4893 }
4894 break;
4895 }
4896 }
4897 }
4898 if (quoted) {
4899 content_error (NULLCP, ct,
4900 "invalid QUOTED-PRINTABLE encoding -- end-of-content while still quoting");
4901 goto clean_up;
4902 }
4903 (void) fseek (ct -> c_fp, 0L, 0);
4904
4905 if (fflush (ce -> ce_fp)) {
4906 content_error (ce -> ce_file, ct, "error writing to");
4907 goto clean_up;
4908 }
4909
4910 if (digested) {
4911 unsigned char digest[16];
4912
4913 MD5Final (digest, &mdContext);
4914 if (bcmp ((char *) digest, (char *) ct -> c_digest,
4915 sizeof digest / sizeof digest[0]))
4916 content_error (NULLCP, ct,
4917 "content integrity suspect (digest mismatch) -- continuing");
4918 else
4919 if (debugsw)
4920 fprintf (stderr, "content integrity confirmed\n");
4921 }
4922
4923 ready_to_go: ;
4924 (void) fseek (ce -> ce_fp, 0L, 0);
4925 *file = ce -> ce_file;
4926 return fileno (ce -> ce_fp);
4927
4928 clean_up: ;
4929 free_encoding (ct, 0);
4930
4931 return NOTOK;
4932 }
4933
4934
4935 static int InitQuoted (ct)
4936 register CT ct;
4937 {
4938 return init_encoding (ct, openQuoted);
4939 }
4940
4941 /* \f 7BIT */
4942
4943 static int open7Bit (ct, file)
4944 register CT ct;
4945 char **file;
4946 {
4947 int cc,
4948 fd,
4949 len;
4950 char buffer[BUFSIZ];
4951 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4952
4953 if (ce -> ce_fp)
4954 goto ready_to_go;
4955 if (ce -> ce_file) {
4956 if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
4957 content_error (ce -> ce_file, ct, "unable to fopen for reading");
4958 return NOTOK;
4959 }
4960
4961 *file = ce -> ce_file;
4962 return fileno (ce -> ce_fp);
4963 }
4964
4965 ce -> ce_unlink = *file == NULL;
4966 if ((ce -> ce_fp = fopen (ce -> ce_file =
4967 add (*file ? *file : m_scratch ("", tmp),
4968 NULLCP),
4969 "w+")) == NULL) {
4970 content_error (ce -> ce_file, ct,
4971 "unable to fopen for writing and reading");
4972 return NOTOK;
4973 }
4974
4975 if (ct -> c_type == CT_MULTIPART) {
4976 register char **ap,
4977 **ep;
4978 register CI ci = &ct -> c_ctinfo;
4979
4980 len = 0;
4981
4982 fprintf (ce -> ce_fp, "%s: %s/%s", TYPE_FIELD, ci -> ci_type,
4983 ci -> ci_subtype);
4984 len += strlen (TYPE_FIELD) + 2 + strlen (ci -> ci_type)
4985 + 1 + strlen (ci -> ci_subtype);
4986 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++) {
4987 (void) putc (';', ce -> ce_fp);
4988 len++;
4989
4990 (void) sprintf (buffer, "%s=\"%s\"", *ap, *ep);
4991
4992 if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
4993 (void) fputs ("\n\t", ce -> ce_fp);
4994 len = 8;
4995 }
4996 else {
4997 (void) putc (' ', ce -> ce_fp);
4998 len++;
4999 }
5000 fprintf (ce -> ce_fp, "%s", buffer);
5001 len += cc;
5002 }
5003 if (ci -> ci_comment) {
5004 if (len + 1 + (cc = 2 + strlen (ci -> ci_comment)) >= CPERLIN) {
5005 (void) fputs ("\n\t", ce -> ce_fp);
5006 len = 8;
5007 }
5008 else {
5009 (void) putc (' ', ce -> ce_fp);
5010 len++;
5011 }
5012 fprintf (ce -> ce_fp, "(%s)", ci -> ci_comment);
5013 len += cc;
5014 }
5015 fprintf (ce -> ce_fp, "\n");
5016 if (ct -> c_id)
5017 fprintf (ce -> ce_fp, "%s:%s", ID_FIELD, ct -> c_id);
5018 if (ct -> c_descr)
5019 fprintf (ce -> ce_fp, "%s:%s", DESCR_FIELD, ct -> c_descr);
5020 fprintf (ce -> ce_fp, "\n");
5021 }
5022
5023 if ((len = ct -> c_end - ct -> c_begin) < 0)
5024 adios (NULLCP, "internal error(3)");
5025
5026 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
5027 content_error (ct -> c_file, ct, "unable to open for reading");
5028 return NOTOK;
5029 }
5030
5031 (void) lseek (fd = fileno (ct -> c_fp), (off_t) ct -> c_begin, 0);
5032 while (len > 0)
5033 switch (cc = read (fd, buffer, sizeof buffer - 1)) {
5034 case NOTOK:
5035 content_error (ct -> c_file, ct, "error reading from");
5036 goto clean_up;
5037
5038 case OK:
5039 content_error (NULLCP, ct, "premature eof");
5040 goto clean_up;
5041
5042 default:
5043 if (cc > len)
5044 cc = len;
5045 len -= cc;
5046
5047 (void) fwrite (buffer, sizeof *buffer, cc, ce -> ce_fp);
5048 if (ferror (ce -> ce_fp)) {
5049 content_error (ce -> ce_file, ct, "error writing to");
5050 goto clean_up;
5051 }
5052 }
5053 (void) fseek (ct -> c_fp, 0L, 0);
5054
5055 if (fflush (ce -> ce_fp)) {
5056 content_error (ce -> ce_file, ct, "error writing to");
5057 goto clean_up;
5058 }
5059
5060 ready_to_go: ;
5061 (void) fseek (ce -> ce_fp, 0L, 0);
5062 *file = ce -> ce_file;
5063 return fileno (ce -> ce_fp);
5064
5065 clean_up: ;
5066 free_encoding (ct, 0);
5067
5068 return NOTOK;
5069 }
5070
5071
5072 static int Init7Bit (ct)
5073 register CT ct;
5074 {
5075 if (init_encoding (ct, open7Bit) == NOTOK)
5076 return NOTOK;
5077 ct -> c_cesizefnx = NULL;
5078
5079 return OK;
5080 }
5081
5082 /* \f External */
5083
5084 static int openExternal (ct, cb, ce, file, fd)
5085 register CT ct;
5086 CT cb;
5087 struct cefile *ce;
5088 char **file;
5089 int *fd;
5090 {
5091 char cachefile[BUFSIZ];
5092
5093 if (ce -> ce_fp) {
5094 (void) fseek (ce -> ce_fp, 0L, 0);
5095
5096 ready_already: ;
5097 *file = ce -> ce_file, *fd = fileno (ce -> ce_fp);
5098 return DONE;
5099 }
5100
5101 if (ce -> ce_file) {
5102 if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
5103 content_error (ce -> ce_file, ct, "unable to fopen for reading");
5104 return NOTOK;
5105 }
5106
5107 goto ready_already;
5108 }
5109
5110 if (find_cache (ct, rcachesw, (int *) 0, cb -> c_id, cachefile) != NOTOK) {
5111 if (ce -> ce_fp = fopen (cachefile, "r")) {
5112 ce -> ce_unlink = 0;
5113 ce -> ce_file = getcpy (cachefile);
5114 goto ready_already;
5115 }
5116 else
5117 admonish (cachefile, "unable to fopen for reading");
5118 }
5119
5120 return OK;
5121 }
5122
5123 /* \f File */
5124
5125 static int openFile (ct, file)
5126 register CT ct;
5127 char **file;
5128 {
5129 int fd,
5130 cachetype;
5131 char cachefile[BUFSIZ];
5132 register struct exbody *e = (struct exbody *) ct -> c_ctextern;
5133 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5134
5135 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5136 case NOTOK:
5137 return NOTOK;
5138
5139 case OK:
5140 break;
5141
5142 case DONE:
5143 return fd;
5144 }
5145
5146 if (!e -> eb_name) {
5147 content_error (NULLCP, ct, "missing name parameter");
5148 return NOTOK;
5149 }
5150
5151 ce -> ce_unlink = 0;
5152 if ((ce -> ce_fp = fopen (ce -> ce_file = getcpy (e -> eb_name), "r"))
5153 == NULL) {
5154 content_error (ce -> ce_file, ct, "unable to fopen for reading");
5155 return NOTOK;
5156 }
5157
5158 if ((!e -> eb_permission || !uleq (e -> eb_permission, "read-write"))
5159 && find_cache (NULLCT, wcachesw, &cachetype,
5160 e -> eb_content -> c_id, cachefile) != NOTOK) {
5161 int mask;
5162 FILE *fp;
5163
5164 mask = umask (cachetype ? ~m_gmprot () : 0222);
5165 if (fp = fopen (cachefile, "w")) {
5166 int cc;
5167 char buffer[BUFSIZ];
5168 FILE *gp = ce -> ce_fp;
5169
5170 (void) fseek (gp, 0L, 0);
5171
5172 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5173 > 0)
5174 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5175 (void) fflush (fp);
5176
5177 if (ferror (gp)) {
5178 admonish (ce -> ce_file, "error reading");
5179 (void) unlink (cachefile);
5180 }
5181 else
5182 if (ferror (fp)) {
5183 admonish (cachefile, "error writing");
5184 (void) unlink (cachefile);
5185 }
5186 (void) fclose (fp);
5187 }
5188 (void) umask (mask);
5189 }
5190
5191 (void) fseek (ce -> ce_fp, 0L, 0);
5192 *file = ce -> ce_file;
5193 return fileno (ce -> ce_fp);
5194 }
5195
5196 /* \f FTP */
5197
5198 static int openFTP (ct, file)
5199 register CT ct;
5200 char **file;
5201 {
5202 int cachetype,
5203 caching,
5204 fd;
5205 char *bp,
5206 *ftp,
5207 *user,
5208 *pass,
5209 buffer[BUFSIZ],
5210 cachefile[BUFSIZ];
5211 register struct exbody *e = (struct exbody *) ct -> c_ctextern;
5212 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5213 static char *username = NULL;
5214 static char *password = NULL;
5215
5216 (void) sprintf (buffer, "%s-access-ftp", invo_name);
5217 if ((ftp = m_find (buffer)) && !*ftp)
5218 ftp = NULLCP;
5219 #ifndef FTP
5220 if (!ftp)
5221 return NOTOK;
5222 #endif
5223 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5224 case NOTOK:
5225 return NOTOK;
5226
5227 case OK:
5228 break;
5229
5230 case DONE:
5231 return fd;
5232 }
5233
5234 if (!e -> eb_name || !e -> eb_site) {
5235 content_error (NULLCP, ct, "missing %s parameter",
5236 e -> eb_name ? "site": "name");
5237 return NOTOK;
5238 }
5239
5240 if (xpid) {
5241 if (xpid < 0)
5242 xpid = -xpid;
5243 (void) pidcheck (pidwait (xpid, NOTOK));
5244 xpid = 0;
5245 }
5246
5247 bp = buffer;
5248 (void) sprintf (bp, "Retrieve %s", e -> eb_name);
5249 bp += strlen (bp);
5250 if (e -> eb_partno) {
5251 (void) sprintf (bp, " (content %s)", e -> eb_partno);
5252 bp += strlen (bp);
5253 }
5254 (void) sprintf (bp, "\n using %sFTP from site %s",
5255 e -> eb_flags ? "anonymous " : "", e -> eb_site);
5256 bp += strlen (bp);
5257 if (e -> eb_size > 0) {
5258 (void) sprintf (bp, " (%lu octets)", e -> eb_size);
5259 bp += strlen (bp);
5260 }
5261 (void) sprintf (bp, "? ");
5262 if (!getanswer (buffer))
5263 return NOTOK;
5264
5265 if (e -> eb_flags) {
5266 user = "anonymous";
5267 (void) sprintf (pass = buffer, "%s@@%s", getusr (), LocalName ());
5268 }
5269 else {
5270 ruserpass (e -> eb_site, &username, &password);
5271 user = username, pass = password;
5272 }
5273
5274 ce -> ce_unlink = *file == NULL, caching = 0, cachefile[0] = 0;
5275 if ((!e -> eb_permission || !uleq (e -> eb_permission, "read-write"))
5276 && find_cache (NULLCT, wcachesw, &cachetype,
5277 e -> eb_content -> c_id, cachefile) != NOTOK) {
5278 if (*file == NULL) {
5279 ce -> ce_unlink = 0;
5280 caching = 1;
5281 }
5282 }
5283
5284 if ((ce -> ce_fp = fopen (ce -> ce_file =
5285 add (*file ? *file
5286 : caching ? cachefile
5287 : m_scratch ("", tmp),
5288 NULLCP),
5289 "w+")) == NULL) {
5290 content_error (ce -> ce_file, ct,
5291 "unable to fopen for writing and reading");
5292 return NOTOK;
5293 }
5294
5295 #ifdef FTP
5296 if (ftp)
5297 #endif
5298 {
5299 int child_id,
5300 i,
5301 vecp;
5302 char *vec[9];
5303
5304 vecp = 0;
5305 vec[vecp++] = r1bindex (ftp, '/');
5306 vec[vecp++] = e -> eb_site;
5307 vec[vecp++] = user;
5308 vec[vecp++] = pass;
5309 vec[vecp++] = e -> eb_dir;
5310 vec[vecp++] = e -> eb_name;
5311 vec[vecp++] = ce -> ce_file,
5312 vec[vecp++] = e -> eb_mode && uleq (e -> eb_mode, "ascii")
5313 ? "ascii" : "binary";
5314 vec[vecp] = NULL;
5315
5316 (void) fflush (stdout);
5317
5318 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
5319 sleep (5);
5320 switch (child_id) {
5321 case NOTOK:
5322 adios ("fork", "unable to");
5323 /* NOTREACHED */
5324
5325 case OK:
5326 (void) close (fileno (ce -> ce_fp));
5327 (void) execvp (ftp, vec);
5328 fprintf (stderr, "unable to exec ");
5329 perror (ftp);
5330 _exit (-1);
5331 /* NOTREACHED */
5332
5333 default:
5334 if (pidXwait (child_id, NULLCP)) {
5335 #ifdef FTP
5336 losing_ftp: ;
5337 #endif
5338 username = password = NULL;
5339 ce -> ce_unlink = 1;
5340 return NOTOK;
5341 }
5342 break;
5343 }
5344 }
5345 #ifdef FTP
5346 else
5347 if (ftp_get (e -> eb_site, user, pass, e -> eb_dir, e -> eb_name,
5348 ce -> ce_file,
5349 !e -> eb_mode || uleq (e -> eb_mode, "ascii"), 0)
5350 == NOTOK)
5351 goto losing_ftp;
5352 #endif
5353
5354 if (cachefile[0])
5355 if (caching)
5356 (void) chmod (cachefile, cachetype ? m_gmprot () : 0444);
5357 else {
5358 int mask;
5359 FILE *fp;
5360
5361 mask = umask (cachetype ? ~m_gmprot () : 0222);
5362 if (fp = fopen (cachefile, "w")) {
5363 int cc;
5364 FILE *gp = ce -> ce_fp;
5365
5366 (void) fseek (gp, 0L, 0);
5367
5368 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5369 > 0)
5370 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5371 (void) fflush (fp);
5372
5373 if (ferror (gp)) {
5374 admonish (ce -> ce_file, "error reading");
5375 (void) unlink (cachefile);
5376 }
5377 else
5378 if (ferror (fp)) {
5379 admonish (cachefile, "error writing");
5380 (void) unlink (cachefile);
5381 }
5382 (void) fclose (fp);
5383 }
5384 (void) umask (mask);
5385 }
5386
5387 (void) fseek (ce -> ce_fp, 0L, 0);
5388 *file = ce -> ce_file;
5389 return fileno (ce -> ce_fp);
5390 }
5391
5392 /* \f Mail */
5393
5394 static int openMail (ct, file)
5395 register CT ct;
5396 char **file;
5397 {
5398 int child_id,
5399 fd,
5400 i,
5401 vecp;
5402 char *bp,
5403 buffer[BUFSIZ],
5404 *vec[7];
5405 register struct exbody *e = (struct exbody *) ct -> c_ctextern;
5406 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5407
5408 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5409 case NOTOK:
5410 return NOTOK;
5411
5412 case OK:
5413 break;
5414
5415 case DONE:
5416 return fd;
5417 }
5418
5419 if (!e -> eb_server) {
5420 content_error (NULLCP, ct, "missing server parameter");
5421 return NOTOK;
5422 }
5423
5424 if (xpid) {
5425 if (xpid < 0)
5426 xpid = -xpid;
5427 (void) pidcheck (pidwait (xpid, NOTOK));
5428 xpid = 0;
5429 }
5430
5431 bp = buffer;
5432 (void) sprintf (bp, "Retrieve content");
5433 bp += strlen (bp);
5434 if (e -> eb_partno) {
5435 (void) sprintf (bp, " %s", e -> eb_partno);
5436 bp += strlen (bp);
5437 }
5438 (void) sprintf (bp, " by asking %s\n\n%s\n? ",
5439 e -> eb_server,
5440 e -> eb_subject ? e -> eb_subject : e -> eb_body);
5441 if (!getanswer (buffer))
5442 return NOTOK;
5443
5444 vecp = 0;
5445 vec[vecp++] = r1bindex (mailproc, '/');
5446 vec[vecp++] = e -> eb_server;
5447 vec[vecp++] = "-subject";
5448 vec[vecp++] = e -> eb_subject ? e -> eb_subject : "mail-server request";
5449 vec[vecp++] = "-body";
5450 vec[vecp++] = e -> eb_body;
5451 vec[vecp] = NULL;
5452
5453 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
5454 sleep (5);
5455 switch (child_id) {
5456 case NOTOK:
5457 advise ("fork", "unable to");
5458 return NOTOK;
5459
5460 case OK:
5461 (void) execvp (mailproc, vec);
5462 fprintf (stderr, "unable to exec ");
5463 perror (mailproc);
5464 _exit (-1);
5465 /* NOTREACHED */
5466
5467 default:
5468 if (pidXwait (child_id, NULLCP) == OK)
5469 advise (NULLCP, "request sent");
5470 break;
5471 }
5472
5473 ce -> ce_unlink = *file == NULL;
5474 if ((ce -> ce_fp = fopen (ce -> ce_file =
5475 add (*file ? *file : m_scratch ("", tmp),
5476 NULLCP),
5477 "w+")) == NULL) {
5478 content_error (ce -> ce_file, ct,
5479 "unable to fopen for writing and reading");
5480 return NOTOK;
5481 }
5482 if (ct -> c_showproc)
5483 free (ct -> c_showproc);
5484 ct -> c_showproc = add ("true", NULLCP);
5485
5486 (void) fseek (ce -> ce_fp, 0L, 0);
5487 *file = ce -> ce_file;
5488 return fileno (ce -> ce_fp);
5489 }
5490
5491 /* \f CACHE */
5492
5493 static int find_cache (ct, policy, writing, id, buffer)
5494 CT ct;
5495 int policy,
5496 *writing;
5497 char *id,
5498 *buffer;
5499 {
5500 int status = NOTOK;
5501
5502 if (id == NULL)
5503 return NOTOK;
5504 id = trimcpy (id);
5505
5506 if (debugsw)
5507 fprintf (stderr, "find_cache %s(%d) %s %s\n",
5508 caches[policy].sw, policy, writing ? "writing" : "reading",
5509 id);
5510
5511 switch (policy) {
5512 case CACHE_NEVER:
5513 default:
5514 break;
5515
5516 case CACHE_ASK:
5517 case CACHE_PUBLIC:
5518 if (cache_private
5519 && !writing
5520 && find_cache_aux (writing ? 2 : 0, cache_private, id,
5521 buffer) == OK) {
5522 if (access (buffer, 04) != NOTOK) {
5523 got_private: ;
5524 if (writing)
5525 *writing = 1;
5526 got_it: ;
5527 status = OK;
5528 break;
5529 }
5530 }
5531 if (cache_public
5532 && find_cache_aux (writing ? 1 : 0, cache_public, id,
5533 buffer) == OK) {
5534 if (writing || access (buffer, 04) != NOTOK) {
5535 if (writing)
5536 *writing = 0;
5537 goto got_it;
5538 }
5539 }
5540 break;
5541
5542 case CACHE_PRIVATE:
5543 if (cache_private
5544 && find_cache_aux (writing ? 2 : 0, cache_private, id,
5545 buffer) == OK) {
5546 if (writing || access (buffer, 04) != NOTOK)
5547 goto got_private;
5548 }
5549 break;
5550
5551 }
5552
5553 if (status == OK && policy == CACHE_ASK) {
5554 char *bp,
5555 query[BUFSIZ];
5556
5557 if (xpid) {
5558 if (xpid < 0)
5559 xpid = -xpid;
5560 (void) pidcheck (pidwait (xpid, NOTOK));
5561 xpid = 0;
5562 }
5563
5564 bp = query;
5565 if (writing)
5566 (void) sprintf (bp, "Make cached, publically-accessible copy");
5567 else {
5568 struct stat st;
5569
5570 (void) sprintf (bp, "Use cached copy");
5571 bp += strlen (bp);
5572 if (ct -> c_partno) {
5573 (void) sprintf (bp, " of content %s", ct -> c_partno);
5574 bp += strlen (bp);
5575 }
5576 (void) stat (buffer, &st);
5577 (void) sprintf (bp, " (size %lu octets)",
5578 (unsigned long) st.st_size);
5579 }
5580 bp += strlen (bp);
5581 (void) sprintf (bp, "\n in file %s? ", buffer);
5582 if (!getanswer (query))
5583 status = NOTOK;
5584 }
5585 if (status == OK && writing) {
5586 if (*writing && index (buffer, '/'))
5587 (void) make_intermediates (buffer);
5588 (void) unlink (buffer);
5589 }
5590
5591 free (id);
5592 return status;
5593 }
5594
5595 /* \f */
5596
5597 static int find_cache_aux (writing, directory, id, buffer)
5598 int writing;
5599 char *directory,
5600 *id,
5601 *buffer;
5602 {
5603 int mask;
5604 #ifdef BSD42
5605 int usemap = index (id, '/') ? 1 : 0;
5606 #else
5607 int usemap = 1;
5608 #endif
5609 char mapfile[BUFSIZ],
5610 mapname[BUFSIZ];
5611 FILE *fp;
5612 static int partno,
5613 pid;
5614 static long clock = 0L;
5615
5616 if (debugsw)
5617 fprintf (stderr, "find_cache_aux %s usemap=%d\n", directory, usemap);
5618
5619 (void) sprintf (mapfile, "%s/cache.map", directory);
5620 if (find_cache_aux2 (mapfile, id, mapname) == OK)
5621 goto done_map;
5622
5623 if (!writing) {
5624 if (usemap)
5625 return NOTOK;
5626
5627 use_raw: ;
5628 (void) sprintf (buffer, "%s/%s", directory, id);
5629 return OK;
5630 }
5631
5632 if (!usemap && access (mapfile, 02) == NOTOK)
5633 goto use_raw;
5634
5635 if (clock != 0L) {
5636 long now;
5637
5638 (void) time (&now);
5639 if (now > clock)
5640 clock = 0L;
5641 }
5642 else
5643 pid = getpid ();
5644 if (clock == 0L) {
5645 (void) time (&clock);
5646 partno = 0;
5647 }
5648 else
5649 if (partno > 0xff)
5650 clock++, partno = 0;
5651
5652 (void) sprintf (mapname, "%08x%04x%02x", clock & 0xffffffff,
5653 pid & 0xffff, partno++ & 0xff);
5654 if (debugsw)
5655 fprintf (stderr, "creating mapping %s -> %s\n", mapname, id);
5656
5657 (void) make_intermediates (mapfile);
5658 mask = umask (writing == 2 ? 0077 : 0);
5659 if (!(fp = lkfopen (mapfile, "a")) && errno == ENOENT) {
5660 int fd = creat (mapfile, 0666);
5661
5662 if (fd != NOTOK) {
5663 (void) close (fd);
5664 fp = lkfopen (mapfile, "a");
5665 }
5666 }
5667 (void) umask (mask);
5668 if (!fp)
5669 return NOTOK;
5670 fprintf (fp, "%s: %s\n", mapname, id);
5671 (void) lkfclose (fp, mapfile);
5672
5673 done_map: ;
5674 if (*mapname == '/')
5675 (void) strcpy (buffer, mapname);
5676 else
5677 (void) sprintf (buffer, "%s/%s", directory, mapname);
5678 if (debugsw)
5679 fprintf (stderr, "use %s\n", buffer);
5680
5681 return OK;
5682 }
5683
5684 /* \f */
5685
5686 static int find_cache_aux2 (mapfile, id, mapname)
5687 char *mapfile,
5688 *id,
5689 *mapname;
5690 {
5691 int state;
5692 char buf[BUFSIZ],
5693 name[NAMESZ];
5694 FILE *fp;
5695
5696 if (!(fp = lkfopen (mapfile, "r")))
5697 return NOTOK;
5698
5699 for (state = FLD;;) {
5700 int result;
5701 register char *cp,
5702 *dp;
5703
5704 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
5705 case FLD:
5706 case FLDPLUS:
5707 case FLDEOF:
5708 (void) strcpy (mapname, name);
5709 if (state != FLDPLUS)
5710 cp = buf;
5711 else {
5712 cp = add (buf, NULLCP);
5713 while (state == FLDPLUS) {
5714 state = m_getfld (state, name, buf, sizeof buf, fp);
5715 cp = add (buf, cp);
5716 }
5717 }
5718 dp = trimcpy (cp);
5719 if (cp != buf)
5720 free (cp);
5721 if (debugsw)
5722 fprintf (stderr, "compare %s to %s <- %s\n", id, dp,
5723 mapname);
5724 result = strcmp (id, dp);
5725 free (dp);
5726 if (result == 0) {
5727 (void) lkfclose (fp, mapfile);
5728 return OK;
5729 }
5730 if (state != FLDEOF)
5731 continue;
5732 /* else fall... */
5733
5734 case BODY:
5735 case BODYEOF:
5736 case FILEEOF:
5737 default:
5738 break;
5739 }
5740 break;
5741 }
5742
5743 (void) lkfclose (fp, mapfile);
5744 return NOTOK;
5745 }
5746
5747 /* \f */
5748
5749 static int cache_content (ct)
5750 register CT ct;
5751 {
5752 int cachetype;
5753 char *file,
5754 cachefile[BUFSIZ];
5755 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5756
5757 if (!ct -> c_id) {
5758 advise (NULLCP, "no %s: field in %s", ID_FIELD, ct -> c_file);
5759 return;
5760 }
5761
5762 if (!ce) {
5763 advise (NULLCP, "unable to decode %s", ct -> c_file);
5764 return;
5765 }
5766
5767 if (ct -> c_ceopenfnx == openMail) {
5768 advise (NULLCP, "a radish may no know Greek, but I do...");
5769 return;
5770 }
5771
5772 if (find_cache (NULLCT, wcachesw != CACHE_NEVER ? wcachesw : CACHE_ASK,
5773 &cachetype, ct -> c_id, cachefile)
5774 == NOTOK) {
5775 advise (NULLCP, "unable to cache %s's contents", ct -> c_file);
5776 return;
5777 }
5778 if (wcachesw != CACHE_NEVER && wcachesw != CACHE_ASK) {
5779 (void) fflush (stdout);
5780 fprintf (stderr, "caching message %s as file %s\n", ct -> c_file,
5781 cachefile);
5782 }
5783
5784 if (ce -> ce_file) {
5785 int mask = umask (cachetype ? ~m_gmprot () : 0222);
5786 FILE *fp;
5787
5788 if (debugsw)
5789 fprintf (stderr, "caching by copying %s...\n", ce -> ce_file);
5790
5791 file = NULL;
5792 if ((*ct -> c_ceopenfnx) (ct, &file) == NOTOK)
5793 goto reset_umask;
5794
5795 if (fp = fopen (cachefile, "w")) {
5796 int cc;
5797 char buffer[BUFSIZ];
5798 FILE *gp = ce -> ce_fp;
5799
5800 (void) fseek (gp, 0L, 0);
5801
5802 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5803 > 0)
5804 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5805 (void) fflush (fp);
5806
5807 if (ferror (gp)) {
5808 admonish (ce -> ce_file, "error reading");
5809 (void) unlink (cachefile);
5810 }
5811 else
5812 if (ferror (fp)) {
5813 admonish (cachefile, "error writing");
5814 (void) unlink (cachefile);
5815 }
5816 (void) fclose (fp);
5817 }
5818 else
5819 content_error (cachefile, ct, "unable to fopen for writing");
5820 reset_umask: ;
5821 (void) umask (mask);
5822 }
5823 else {
5824 if (debugsw)
5825 fprintf (stderr, "in place caching...\n");
5826
5827 file = cachefile;
5828 if ((*ct -> c_ceopenfnx) (ct, &file) != NOTOK)
5829 (void) chmod (cachefile, cachetype ? m_gmprot () : 0444);
5830 }
5831 }
5832
5833 /* \f COMPOSITION */
5834
5835 static char prefix[] = "----- =_aaaaaaaaaa";
5836
5837 static char *free_file = NULL;
5838 static CT free_ct = NULL;
5839
5840
5841 static void build_comp (file)
5842 char *file;
5843 {
5844 int compnum,
5845 state;
5846 char *cp,
5847 buf[BUFSIZ],
5848 name[NAMESZ],
5849 tmpfil[BUFSIZ];
5850 struct multipart *m;
5851 register struct part **pp;
5852 CT ct;
5853 FILE *in,
5854 *out;
5855
5856 if ((in = fopen (file, "r")) == NULL)
5857 adios (file, "unable to open for reading");
5858
5859 (void) umask (~m_gmprot ());
5860
5861 (void) strcpy (tmpfil, m_scratch (file, invo_name));
5862 if ((out = fopen (tmpfil, "w")) == NULL)
5863 adios (tmpfil, "unable to open for writing");
5864 free_file = tmpfil;
5865
5866 for (compnum = 1, state = FLD;;) {
5867 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
5868 case FLD:
5869 case FLDPLUS:
5870 case FLDEOF:
5871 compnum++;
5872
5873 if (uleq (name, VRSN_FIELD))
5874 adios (NULLCP, "draft shouldn't contain %s: field",
5875 VRSN_FIELD);
5876
5877 if (uleq (name, TYPE_FIELD)) {
5878 while (state == FLDPLUS)
5879 state = m_getfld (state, name, buf, sizeof buf, in);
5880 goto finish_field;
5881 }
5882
5883 if (uleq (name, ENCODING_FIELD))
5884 adios (NULLCP, "draft shouldn't contain %s: field",
5885 ENCODING_FIELD);
5886
5887 fprintf (out, "%s:%s", name, buf);
5888 while (state == FLDPLUS) {
5889 state = m_getfld (state, name, buf, sizeof buf, in);
5890 (void) fputs (buf, out);
5891 }
5892 finish_field: ;
5893 if (state != FLDEOF)
5894 continue;
5895 /* else fall... */
5896
5897 case FILEEOF:
5898 adios (NULLCP, "draft has empty body -- no directives!");
5899 /* NOTREACHED */
5900
5901 case BODY:
5902 case BODYEOF:
5903 (void) fseek (in, (long) (-strlen (buf)), 1);
5904 break;
5905
5906 case LENERR:
5907 case FMTERR:
5908 adios (NULLCP, "message format error in component #%d",
5909 compnum);
5910
5911 default:
5912 adios (NULLCP, "getfld() returned %d", state);
5913 }
5914 break;
5915 }
5916
5917 if ((free_ct = ct = (CT) calloc (1, sizeof *ct)) == NULL)
5918 adios (NULLCP, "out of memory");
5919 if (get_ctinfo ("multipart/mixed", ct, 0) == NOTOK)
5920 done (1);
5921 ct -> c_type = CT_MULTIPART;
5922 ct -> c_subtype = MULTI_MIXED;
5923 ct -> c_ctlistfnx = list_multi;
5924 ct -> c_ctfreefnx = free_multi;
5925 ct -> c_file = add (file, NULLCP);
5926
5927 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
5928 adios (NULLCP, "out of memory");
5929 ct -> c_ctparams = (caddr_t) m;
5930
5931 pp = &m -> mp_parts;
5932 while (fgetstr (buf, sizeof buf - 1, in)) {
5933 register struct part *part;
5934 CT p;
5935
5936 if (user_content (in, file, buf, &p) == DONE) {
5937 admonish (NULLCP, "ignoring spurious #end");
5938 continue;
5939 }
5940 if (!p)
5941 continue;
5942
5943 if ((part = (struct part *) calloc (1, sizeof *part)) == NULL)
5944 adios (NULLCP, "out of memory");
5945 *pp = part, pp = &part -> mp_next;
5946 part -> mp_part = p;
5947 }
5948
5949 (void) fclose (in);
5950
5951 if (!m -> mp_parts)
5952 adios (NULLCP, "no content directives found");
5953 if (!m -> mp_parts -> mp_next) {
5954 CT p = m -> mp_parts -> mp_part;
5955
5956 m -> mp_parts -> mp_part = NULL;
5957 free_content (ct);
5958 free_ct = ct = p;
5959 }
5960 else
5961 set_id (ct, 1);
5962
5963 if ((cp = index (prefix, 'a')) == NULL)
5964 adios (NULLCP, "internal error(4)");
5965
5966 while (compose_content (ct) == NOTOK)
5967 if (*cp < 'z')
5968 (*cp)++;
5969 else
5970 if (*++cp == 0)
5971 adios (NULLCP,
5972 "giving up trying to find a unique delimiter string");
5973 else
5974 (*cp)++;
5975
5976 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
5977 (void) output_content (ct, out);
5978
5979 if (fflush (out))
5980 adios (tmpfil, "error writing to");
5981
5982 (void) fclose (out);
5983
5984 if (listsw && ct -> c_ctlistfnx) {
5985 char *savfile;
5986
5987 if (headsw)
5988 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
5989 "description");
5990
5991 /* to get msgno */
5992 savfile = ct -> c_file, ct -> c_file = file;
5993 (*ct -> c_ctlistfnx) (ct, 1);
5994 ct -> c_file = savfile;
5995 }
5996
5997 free_content (ct);
5998 free_ct = NULL;
5999
6000 (void) sprintf (buf, "%s.orig", m_backup (file));
6001 if (rename (file, buf) == NOTOK)
6002 adios (buf, "unable to rename %s to", file);
6003 if (rename (tmpfil, file) == NOTOK) {
6004 advise (file, "unable to rename %s to", tmpfil);
6005 (void) rename (buf, file);
6006 done (1);
6007 }
6008 free_file = NULL;
6009
6010 done (0);
6011 }
6012
6013 /* \f */
6014
6015 static char *fgetstr (s, n, stream)
6016 char *s;
6017 int n;
6018 FILE *stream;
6019 {
6020 register char *cp,
6021 *ep;
6022
6023 for (ep = (cp = s) + n; cp < ep; ) {
6024 register int i;
6025
6026 if (!fgets (cp, n, stream))
6027 return (cp != s ? s : NULL);
6028 if (cp == s && *cp != '#')
6029 return s;
6030
6031 cp += (i = strlen (cp)) - 1;
6032 if (i <= 1 || *cp-- != '\n' || *cp != '\\')
6033 break;
6034 *cp = 0, n -= (i - 2);
6035 }
6036
6037 return s;
6038 }
6039
6040 /* \f */
6041
6042 static int user_content (in, file, buf, ctp)
6043 FILE *in;
6044 char *file,
6045 *buf;
6046 CT *ctp;
6047 {
6048 int extrnal,
6049 vrsn;
6050 register char *cp,
6051 **ap;
6052 char buffer[BUFSIZ];
6053 struct multipart *m;
6054 register struct part **pp;
6055 struct stat st;
6056 register struct str2init *s2i;
6057 register CI ci;
6058 register CT ct;
6059
6060 if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) {
6061 *ctp = NULL;
6062 return OK;
6063 }
6064
6065 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
6066 adios (NULLCP, "out of memory");
6067 *ctp = ct;
6068 ci = &ct -> c_ctinfo;
6069 ct -> c_ctlistfnx = list_content;
6070 set_id (ct, 0);
6071
6072 if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
6073 int headers,
6074 inlineD;
6075 long pos;
6076 char content[BUFSIZ];
6077 FILE *out;
6078
6079 ct -> c_file = add (m_tmpfil (invo_name), NULLCP);
6080 ct -> c_unlink = 1;
6081
6082 if ((out = fopen (ct -> c_file, "w")) == NULL)
6083 adios (ct -> c_file, "unable to open for writing");
6084
6085 if (buf[0] == '#' && buf[1] == '<') {
6086 (void) strcpy (content, buf + 2);
6087 inlineD = 1;
6088 goto rock_and_roll;
6089 }
6090 else
6091 inlineD = 0;
6092
6093 (void) strcpy (content, "text/plain");
6094 headers = 0;
6095 (void) strcpy (buffer, buf[0] != '#' ? buf : buf + 1);
6096 for (;;) {
6097 int i;
6098
6099 if (headers >= 0
6100 && uprf (buffer, DESCR_FIELD)
6101 && buffer[i = strlen (DESCR_FIELD)] == ':') {
6102 headers = 1;
6103
6104 again_descr: ;
6105 ct -> c_descr = add (buffer + i + 1, ct -> c_descr);
6106 if (!fgetstr (buffer, sizeof buffer - 1, in))
6107 adios (NULLCP,
6108 "end-of-file after %s: field in plaintext",
6109 DESCR_FIELD);
6110 switch (buffer[0]) {
6111 case ' ':
6112 case '\t':
6113 i = -1;
6114 goto again_descr;
6115
6116 case '#':
6117 adios (NULLCP,
6118 "#-directive after %s: field in plaintext",
6119 DESCR_FIELD);
6120 /* NOTREACHED */
6121
6122 default:
6123 break;
6124 }
6125 }
6126
6127 if (headers != 1 || buffer[0] != '\n')
6128 (void) fputs (buffer, out);
6129 rock_and_roll: ;
6130 headers = -1;
6131
6132 pos = ftell (in);
6133 if ((cp = fgetstr (buffer, sizeof buffer - 1, in)) == NULL)
6134 break;
6135 if (buffer[0] == '#') {
6136 register char *bp;
6137
6138 if (buffer[1] != '#')
6139 break;
6140 for (cp = (bp = buffer) + 1; *cp; cp++)
6141 *bp++ = *cp;
6142 *bp = '\0';
6143 }
6144 }
6145
6146 if (listsw)
6147 ct -> c_end = ftell (out);
6148 (void) fclose (out);
6149
6150 if (get_ctinfo (content, ct, inlineD) == NOTOK)
6151 done (1);
6152 for (s2i = str2cts; s2i -> si_key; s2i++)
6153 if (uleq (ci -> ci_type, s2i -> si_key))
6154 break;
6155 if (!s2i -> si_key && !uprf (ci -> ci_type, "X-"))
6156 s2i++;
6157 switch (ct -> c_type = s2i -> si_val) {
6158 case CT_MESSAGE:
6159 if (uleq (ci -> ci_subtype, "rfc822")) {
6160 ct -> c_encoding = CE_7BIT; /* XXX */
6161 goto call_init;
6162 }
6163 /* else fall... */
6164 case CT_MULTIPART:
6165 adios (NULLCP,
6166 "it makes sense to define a in-line %s content... NOT!",
6167 ct -> c_type == CT_MESSAGE ? "message" : "multipart");
6168 /* NOTREACHED */
6169
6170 default:
6171 call_init: ;
6172 if (ct -> c_ctinitfnx = s2i -> si_init)
6173 (void) (*ct -> c_ctinitfnx) (ct);
6174 break;
6175 }
6176
6177 if (cp)
6178 (void) fseek (in, pos, 0);
6179 return OK;
6180 }
6181
6182 extrnal = buf[1] == '@@';
6183 if (get_ctinfo (buf + (extrnal ? 2 : 1), ct, 1) == NOTOK)
6184 done (1);
6185
6186 for (s2i = str2cts; s2i -> si_key; s2i++)
6187 if (uleq (ci -> ci_type, s2i -> si_key))
6188 break;
6189 if (s2i -> si_key) { /* type/subtype [file] */
6190 if (!ci -> ci_subtype)
6191 adios (NULLCP, "missing subtype in \"#%s\"", ci -> ci_type);
6192
6193 switch (ct -> c_type = s2i -> si_val) {
6194 case CT_MULTIPART:
6195 adios (NULLCP, "use \"#begin ... #end\" instead of \"#%s/%s\"",
6196 ci -> ci_type, ci -> ci_subtype);
6197 /* NOTREACHED */
6198
6199 case CT_MESSAGE:
6200 if (uleq (ci -> ci_subtype, "partial"))
6201 adios (NULLCP, "sorry, \"#%s/%s\" isn't supported",
6202 ci -> ci_type, ci -> ci_subtype);
6203 if (uleq (ci -> ci_subtype, "external-body"))
6204 adios (NULLCP, "use \"#@@type/subtype ... [] ...\" instead of \"#%s/%s\"",
6205 ci -> ci_type, ci -> ci_subtype);
6206 use_forw: ;
6207 adios (NULLCP,
6208 "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"",
6209 ci -> ci_type, ci -> ci_subtype);
6210 /* NOTREACHED */
6211
6212 default:
6213 if (ct -> c_ctinitfnx = s2i -> si_init)
6214 (void) (*ct -> c_ctinitfnx) (ct);
6215 break;
6216 }
6217
6218 if (extrnal) {
6219 register struct exbody *e;
6220 CT p;
6221
6222 if (!ci -> ci_magic)
6223 adios (NULLCP, "need external information for \"#@@%s/%s\"",
6224 ci -> ci_type, ci -> ci_subtype);
6225 p = ct;
6226
6227 (void) sprintf (buffer, "message/external-body; %s",
6228 ci -> ci_magic);
6229 free (ci -> ci_magic), ci -> ci_magic = NULL;
6230
6231 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
6232 adios (NULLCP, "out of memory");
6233 *ctp = ct;
6234 ci = &ct -> c_ctinfo;
6235 ct -> c_ctlistfnx = list_content;
6236 if (get_ctinfo (buffer, ct, 0) == NOTOK)
6237 done (1);
6238 ct -> c_type = CT_MESSAGE;
6239 ct -> c_subtype = MESSAGE_EXTERNAL;
6240
6241 if ((e = (struct exbody *) calloc (1, sizeof *e)) == NULL)
6242 adios (NULLCP, "out of memory");
6243 ct -> c_ctparams = (caddr_t) e;
6244 ct -> c_ctfreefnx = free_external;
6245
6246 e -> eb_parent = ct;
6247 e -> eb_content = p;
6248 p -> c_ctextern = (caddr_t) e;
6249
6250 ct -> c_ctlistfnx = list_external;
6251
6252 if (params_external (ct, 1) == NOTOK)
6253 done (1);
6254
6255 return OK;
6256 }
6257
6258 if (ci -> ci_magic) {
6259 if (*ci -> ci_magic == '|' || *ci -> ci_magic == '!') {
6260 for (cp = ci -> ci_magic + 1; isspace (*cp); cp++)
6261 continue;
6262 if (!*cp)
6263 adios (NULLCP, "empty pipe command for #%s directive",
6264 ci -> ci_type);
6265 cp = add (cp, NULLCP);
6266 free (ci -> ci_magic);
6267 ci -> ci_magic = cp;
6268 }
6269 else {
6270 if (access (ct -> c_file = ci -> ci_magic, 04) == NOTOK)
6271 adios ("reading", "unable to access %s for", ct -> c_file);
6272 if (listsw && stat (ct -> c_file, &st) != NOTOK)
6273 ct -> c_end = (long) st.st_size;
6274 ci -> ci_magic = NULL;
6275 }
6276 return OK;
6277 }
6278
6279 (void) sprintf (buffer, "%s-compose-%s/%s", invo_name, ci -> ci_type,
6280 ci -> ci_subtype);
6281 if ((cp = m_find (buffer)) == NULL || *cp == 0) {
6282 (void) sprintf (buffer, "%s-compose-%s", invo_name, ci -> ci_type);
6283 if ((cp = m_find (buffer)) == NULL || *cp == 0) {
6284 content_error (NULLCP, ct,
6285 "don't know how to compose content");
6286 done (1);
6287 }
6288 }
6289 ci -> ci_magic = add (cp, NULLCP);
6290 return OK;
6291 }
6292
6293 if (extrnal)
6294 adios (NULLCP, "externally definition not allowed for \"#%s\"",
6295 ci -> ci_type);
6296
6297 if (uleq (ci -> ci_type, "forw")) { /* #forw [+folder] [msgs] */
6298 int msgnum;
6299 char *folder,
6300 *arguments[MAXARGS];
6301 struct msgs *mp;
6302
6303 if (ci -> ci_magic) {
6304 ap = brkstring (ci -> ci_magic, " ", "\n");
6305 ap = copyip (ap, arguments);
6306 }
6307 else
6308 arguments[0] = "cur", arguments[1] = NULL;
6309
6310 folder = NULL;
6311 for (ap = arguments; cp = *ap; ap++)
6312 if (*cp == '+' || *cp == '@@')
6313 if (folder)
6314 adios (NULLCP, "only one folder per #forw directive");
6315 else
6316 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
6317 if (!folder)
6318 folder = add (m_getfolder (), NULLCP);
6319
6320 if ((mp = m_gmsg (folder)) == NULL)
6321 adios (NULLCP, "unable to read folder %s", folder);
6322 for (ap = arguments; cp = *ap; ap++)
6323 if (*cp != '+' && *cp != '@@')
6324 if (!m_convert (mp, cp))
6325 done (1);
6326 free (folder);
6327
6328 free_ctinfo (ct);
6329 if (mp -> numsel > 1) {
6330 if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK)
6331 done (1);
6332 ct -> c_type = CT_MULTIPART;
6333 ct -> c_subtype = MULTI_DIGEST;
6334 ct -> c_ctlistfnx = list_multi;
6335 ct -> c_ctfreefnx = free_multi;
6336
6337 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
6338 adios (NULLCP, "out of memory");
6339 ct -> c_ctparams = (caddr_t) m;
6340
6341 pp = &m -> mp_parts;
6342 }
6343 else
6344 free_content (ct);
6345 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
6346 if (mp -> msgstats[msgnum] & SELECTED) {
6347 register struct part *part;
6348 register CT p;
6349
6350 if ((p = (CT) calloc (1, sizeof *p)) == NULL)
6351 adios (NULLCP, "out of memory");
6352 if (get_ctinfo ("message/rfc822", p, 0) == NOTOK)
6353 done (1);
6354 p -> c_type = CT_MESSAGE;
6355 p -> c_subtype = MESSAGE_RFC822;
6356 p -> c_ctlistfnx = list_content;
6357
6358 (void) sprintf (buffer, "%s/%d", mp -> foldpath, msgnum);
6359 p -> c_file = add (buffer, NULLCP);
6360 if (listsw && stat (p -> c_file, &st) != NOTOK)
6361 p -> c_end = (long) st.st_size;
6362
6363 if (mp -> numsel > 1) {
6364 if ((part = (struct part *) calloc (1, sizeof *part))
6365 == NULL)
6366 adios (NULLCP, "out of memory");
6367 *pp = part, pp = &part -> mp_next;
6368 part -> mp_part = p;
6369 }
6370 else
6371 *ctp = ct = p;
6372 }
6373
6374 m_fmsg (mp);
6375
6376 return OK;
6377 }
6378
6379 if (uleq (ci -> ci_type, "end")) {
6380 free_content (ct);
6381 *ctp = NULL;
6382 return DONE;
6383 }
6384
6385 if (!uleq (ci -> ci_type, "begin"))
6386 adios (NULLCP, "unknown directive \"#%s\"", ci -> ci_type);
6387
6388 /* #begin [ alternative | parallel ] */
6389 if (!ci -> ci_magic)
6390 cp = SubMultiPart[(vrsn = MULTI_MIXED) - 1].kv_key;
6391 else
6392 if (uleq (ci -> ci_magic, "alternative"))
6393 cp = SubMultiPart[(vrsn = MULTI_ALTERNATE) - 1].kv_key;
6394 else
6395 if (uleq (ci -> ci_magic, "parallel"))
6396 cp = SubMultiPart[(vrsn = MULTI_PARALLEL) - 1].kv_key;
6397 else
6398 if (uprf (ci -> ci_magic, "digest"))
6399 goto use_forw;
6400 else
6401 cp = ci -> ci_magic, vrsn = MULTI_UNKNOWN;
6402 free_ctinfo (ct);
6403 (void) sprintf (buffer, "multipart/%s", cp);
6404 if (get_ctinfo (buffer, ct, 0) == NOTOK)
6405 done (1);
6406 ct -> c_type = CT_MULTIPART;
6407 ct -> c_subtype = vrsn;
6408 ct -> c_ctlistfnx = list_multi;
6409 ct -> c_ctfreefnx = free_multi;
6410
6411 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
6412 adios (NULLCP, "out of memory");
6413 ct -> c_ctparams = (caddr_t) m;
6414
6415 pp = &m -> mp_parts;
6416 while (fgetstr (buffer, sizeof buffer - 1, in)) {
6417 register struct part *part;
6418 CT p;
6419
6420 if (user_content (in, file, buffer, &p) == DONE) {
6421 if (!m -> mp_parts)
6422 adios (NULLCP, "empty \"#begin ... #end\" sequence");
6423 return OK;
6424 }
6425 if (!p)
6426 continue;
6427
6428 if ((part = (struct part *) calloc (1, sizeof *part)) == NULL)
6429 adios (NULLCP, "out of memory");
6430 *pp = part, pp = &part -> mp_next;
6431 part -> mp_part = p;
6432 }
6433 admonish (NULLCP, "premature end-of-file, missing #end");
6434 return OK;
6435 }
6436
6437 /* \f */
6438
6439 static void set_id (ct, top)
6440 CT ct;
6441 int top;
6442 {
6443 char msgid[BUFSIZ];
6444 static int partno;
6445 static long clock = 0L;
6446 static char *msgfmt;
6447
6448 if (clock == 0L) {
6449 (void) time (&clock);
6450 (void) sprintf (msgid, "<%d.%ld.%%d@@%s>\n", getpid (), clock,
6451 LocalName ());
6452 partno = 0;
6453 msgfmt = getcpy (msgid);
6454 }
6455 (void) sprintf (msgid, msgfmt, top ? 0 : ++partno);
6456 ct -> c_id = getcpy (msgid);
6457 }
6458
6459 /* \f */
6460
6461 static char ebcdicsafe[0x100] = {
6462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6463 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
6464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6466 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
6467 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6468 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6469 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6470 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6471 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6472 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6473 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
6474 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6475 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6476 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
6477 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
6478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6494 };
6495
6496 static int compose_content (ct)
6497 register CT ct;
6498 {
6499 register char *cp;
6500 char buffer[BUFSIZ];
6501 register CI ci = &ct -> c_ctinfo;
6502
6503 if (ct -> c_type == CT_MESSAGE && ct -> c_subtype == MESSAGE_EXTERNAL)
6504 return OK;
6505
6506 switch (ct -> c_type) {
6507 case CT_MULTIPART:
6508 {
6509 int partnum;
6510 register char *pp;
6511 char partnam[BUFSIZ];
6512 struct multipart *m = (struct multipart *) ct -> c_ctparams;
6513 register struct part *part;
6514
6515 if (ct -> c_partno) {
6516 (void) sprintf (partnam, "%s.", ct -> c_partno);
6517 pp = partnam + strlen (partnam);
6518 }
6519 else
6520 pp = partnam;
6521
6522 for (part = m -> mp_parts, partnum = 1;
6523 part;
6524 part = part -> mp_next, partnum++) {
6525 register CT p = part -> mp_part;
6526
6527 (void) sprintf (pp, "%d", partnum);
6528 p -> c_partno = add (partnam, NULLCP);
6529
6530 if (compose_content (p) == NOTOK)
6531 return NOTOK;
6532 }
6533
6534 if (rfc934sw && ct -> c_subtype == MULTI_DIGEST) {
6535 int is934 = 1;
6536
6537 for (part = m -> mp_parts; part; part = part -> mp_next) {
6538 register CT p = part -> mp_part;
6539
6540 if (p -> c_subtype != MESSAGE_RFC822) {
6541 is934 = 0;
6542 break;
6543 }
6544 }
6545
6546 ct -> c_rfc934 = is934;
6547 for (part = m -> mp_parts; part; part = part -> mp_next) {
6548 register CT p = part -> mp_part;
6549
6550 if (p -> c_rfc934 = is934)
6551 p -> c_end++;
6552 }
6553 }
6554
6555 if (listsw) {
6556 ct -> c_end = (partnum = strlen (prefix) + 2) + 2;
6557 if (ct -> c_rfc934)
6558 ct -> c_end += 1;
6559
6560 for (part = m -> mp_parts; part; part = part -> mp_next)
6561 ct -> c_end += part -> mp_part -> c_end + partnum;
6562 }
6563 }
6564 break;
6565
6566
6567 default:
6568 if (!ct -> c_file) {
6569 int child_id,
6570 i,
6571 xstdout;
6572 register char *bp,
6573 **ap;
6574 char *vec[4];
6575 FILE *out;
6576
6577 if (!(cp = ci -> ci_magic))
6578 adios (NULLCP, "internal error(5)");
6579
6580 ct -> c_file = add (m_tmpfil (invo_name), NULLCP);
6581 ct -> c_unlink = 1;
6582
6583 xstdout = 0;
6584 buffer[0] = '\0';
6585 for (bp = buffer; *cp; cp++)
6586 if (*cp == '%') {
6587 switch (*++cp) {
6588 case 'a': /* additional arguments */
6589 {
6590 register char **ep;
6591 char *s = "";
6592
6593 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
6594 *ap;
6595 ap++, ep++) {
6596 (void) sprintf (bp, "%s%s=\"%s\"", s,
6597 *ap, *ep);
6598 bp += strlen (bp);
6599 s = " ";
6600 }
6601 }
6602 break;
6603
6604 case 'F': /* %f, and stdout is not-redirected */
6605 xstdout = 1;
6606 /* and fall... */
6607 case 'f': /* filename */
6608 (void) sprintf (bp, "%s", ct -> c_file);
6609 break;
6610
6611 case 's': /* subtype */
6612 (void) strcpy (bp, ci -> ci_subtype);
6613 break;
6614
6615 case '%':
6616 goto raw;
6617
6618 default:
6619 *bp++ = *--cp;
6620 *bp = '\0';
6621 continue;
6622 }
6623 bp += strlen (bp);
6624 }
6625 else {
6626 raw: ;
6627 *bp++ = *cp;
6628 *bp = '\0';
6629 }
6630
6631 printf ("composing content %s/%s from command\n\t%s\n",
6632 ci -> ci_type, ci -> ci_subtype, buffer);
6633 (void) fflush (stdout);
6634
6635 vec[0] = "/bin/sh";
6636 vec[1] = "-c";
6637 vec[2] = buffer;
6638 vec[3] = NULL;
6639
6640 if ((out = fopen (ct -> c_file, "w")) == NULL)
6641 adios (ct -> c_file, "unable to open for writing");
6642
6643 for (i = 0; (child_id = vfork ()) == NOTOK && i > 5; i++)
6644 sleep (5);
6645 switch (child_id) {
6646 case NOTOK:
6647 adios ("fork", "unable to fork");
6648 /* NOTREACHED */
6649
6650 case OK:
6651 if (!xstdout)
6652 (void) dup2 (fileno (out), 1);
6653 (void) close (fileno (out));
6654 (void) execvp ("/bin/sh", vec);
6655 fprintf (stderr, "unable to exec ");
6656 perror ("/bin/sh");
6657 _exit (-1);
6658 /* NOTREACHED */
6659
6660 default:
6661 (void) fclose (out);
6662 if (pidXwait (child_id, NULLCP))
6663 done (1);
6664 break;
6665 }
6666 }
6667 if (listsw && ct -> c_end == 0L) {
6668 struct stat st;
6669
6670 if (stat (ct -> c_file, &st) != NOTOK)
6671 ct -> c_end = (long) st.st_size;
6672 }
6673 if (ct -> c_type != CT_TEXT && ct -> c_type != CT_APPLICATION)
6674 break;
6675 /* else fall... */
6676
6677 case CT_MESSAGE:
6678 {
6679 int charset,
6680 len,
6681 linelen,
6682 result;
6683 FILE *in;
6684
6685 if ((in = fopen (ct -> c_file, "r")) == NULL)
6686 adios (ct -> c_file, "unable to open for reading");
6687
6688 len = strlen (prefix);
6689 result = OK;
6690 switch (ct -> c_type) {
6691 case CT_TEXT:
6692 charset = ct -> c_ctparams ? 0 : -1;
6693 linelen = ct -> c_subtype == TEXT_PLAIN ? 0 : -1;
6694 break;
6695
6696 case CT_APPLICATION:
6697 charset = linelen = ct -> c_encoding ? 0 : -1;
6698 break;
6699
6700 default:
6701 charset = linelen = 0;
6702 break;
6703 }
6704 while (fgets (buffer, sizeof buffer - 1, in)) {
6705 if (charset == -1) {
6706 for (cp = buffer; *cp; cp++) {
6707 if (!isascii (*cp)) {
6708 charset = CHARSET_UNKNOWN;
6709 break;
6710 }
6711 if (linelen == -1
6712 && ebcdicsw
6713 && !ebcdicsafe[*cp & 0xff])
6714 linelen = 1;
6715 }
6716 if ((linelen == -1) && (cp - buffer > CPERLIN + 1))
6717 linelen = 1;
6718 if (result == NOTOK)
6719 break;
6720 }
6721 else
6722 if ((linelen == -1) && (strlen (buffer) > CPERLIN + 1))
6723 linelen = 1;
6724 if (result == NOTOK)
6725 continue;
6726
6727 if (linelen == -1) {
6728 if ((cp = buffer + strlen (buffer) - 2) > buffer
6729 && isspace (*cp))
6730 linelen = 1;
6731 else
6732 if ((*(cp = buffer) == '.')
6733 || (strncmp (cp, "From ",
6734 sizeof "From " -1) == 0))
6735 linelen = 1;
6736 }
6737
6738 if (buffer[0] == '-' && buffer[1] == '-') {
6739 for (cp = buffer + strlen (buffer) - 1;
6740 cp >= buffer;
6741 cp--)
6742 if (!isspace (*cp))
6743 break;
6744 *++cp = '\0';
6745 if (strncmp (buffer + 2, prefix, len) == 0
6746 && isdigit (buffer[2 + len])) {
6747 result = NOTOK;
6748 if (charset != -1 && linelen != -1)
6749 break;
6750 }
6751 }
6752 }
6753 if (ct -> c_type == CT_APPLICATION && !ct -> c_encoding)
6754 ct -> c_encoding = linelen == -1
6755 && charset != CHARSET_UNKNOWN
6756 ? CE_7BIT
6757 : ct -> c_subtype
6758 != APPLICATION_POSTSCRIPT
6759 ? CE_BASE64 : CE_QUOTED;
6760 if (ct -> c_type == CT_TEXT && !ct -> c_ctparams) {
6761 register char **ap,
6762 **ep;
6763 register struct text *t;
6764
6765 if (charset == CHARSET_UNKNOWN && mm_charset)
6766 charset = -2;
6767 else
6768 if (charset == -1)
6769 charset = CHARSET_USASCII;
6770
6771 if ((t = (struct text *) calloc (1, sizeof *t)) == NULL)
6772 adios (NULLCP, "out of memory");
6773 ct -> c_ctparams = (caddr_t) t;
6774 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
6775 *ap;
6776 ap++, ep++)
6777 continue;
6778 switch (t -> tx_charset = charset) {
6779 case CHARSET_USASCII:
6780 *ap = add ("charset=us-ascii", NULLCP);
6781 break;
6782
6783 case CHARSET_UNKNOWN:
6784 default:
6785 *ap = add ("charset=x-unknown", NULLCP);
6786 break;
6787
6788 case -2:
6789 *ap = concat ("charset=", mm_charset, NULLCP);
6790 break;
6791 }
6792 cp = index (*ap++, '=');
6793 *ap = NULL;
6794 *cp++ = '\0';
6795 *ep = cp;
6796 }
6797 if (ct -> c_type == CT_TEXT && ct -> c_subtype != TEXT_PLAIN)
6798 ct -> c_encoding = linelen == -1 ? CE_7BIT : CE_QUOTED;
6799
6800 (void) fclose (in);
6801
6802 return result;
6803 }
6804 }
6805
6806 return OK;
6807 }
6808
6809 /* \f */
6810
6811 static int output_content (ct, out)
6812 register CT ct;
6813 FILE *out;
6814 {
6815 int cc,
6816 mailbody,
6817 len;
6818 register char **ap,
6819 **ep;
6820 char buffer[BUFSIZ];
6821 register CI ci = &ct -> c_ctinfo;
6822
6823 if (ct -> c_type == CT_MULTIPART) {
6824 register char *cp;
6825 static int encl = 0;
6826
6827 ap = ci -> ci_attrs, ep = ci -> ci_values;
6828
6829 (void) sprintf (buffer, "boundary=%s%d", prefix, encl++);
6830 cp = index (*ap++ = add (buffer, NULLCP), '=');
6831 *ap = NULL;
6832 *cp++ = '\0';
6833 *ep = cp;
6834 }
6835 else
6836 if (ct -> c_type == CT_MESSAGE && ct -> c_rfc934)
6837 goto rfc934_mode;
6838
6839 len = 0;
6840 fprintf (out, "%s: %s/%s", TYPE_FIELD, ci -> ci_type, ci -> ci_subtype);
6841 len += strlen (TYPE_FIELD) + 2 + strlen (ci -> ci_type)
6842 + 1 + strlen (ci -> ci_subtype);
6843 mailbody = ct -> c_type == CT_MESSAGE
6844 && ct -> c_subtype == MESSAGE_EXTERNAL
6845 && ((struct exbody *) ct -> c_ctparams) -> eb_body;
6846 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++) {
6847 if (mailbody && uleq (*ap, "body"))
6848 continue;
6849
6850 (void) putc (';', out);
6851 len++;
6852
6853 (void) sprintf (buffer, "%s=\"%s\"", *ap, *ep);
6854
6855 if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
6856 (void) fputs ("\n\t", out);
6857 len = 8;
6858 }
6859 else {
6860 (void) putc (' ', out);
6861 len++;
6862 }
6863 fputs (buffer, out);
6864 len += cc;
6865 }
6866 if (ci -> ci_comment) {
6867 if (len + 1 + (cc = 2 + strlen (ci -> ci_comment)) >= CPERLIN) {
6868 (void) fputs ("\n\t", out);
6869 len = 8;
6870 }
6871 else {
6872 (void) putc (' ', out);
6873 len++;
6874 }
6875 fprintf (out, "(%s)", ci -> ci_comment);
6876 len += cc;
6877 }
6878 (void) putc ('\n', out);
6879 if (ct -> c_id)
6880 fprintf (out, "%s: %s", ID_FIELD, ct -> c_id);
6881 if (ct -> c_descr)
6882 fprintf (out, "%s: %s", DESCR_FIELD, ct -> c_descr);
6883
6884 rfc934_mode: ;
6885 if (ct -> c_ctextern)
6886 return OK;
6887 switch (ct -> c_type) {
6888 case CT_MULTIPART:
6889 {
6890 struct multipart *m = (struct multipart *) ct -> c_ctparams;
6891 register struct part *part;
6892
6893 if (ct -> c_rfc934)
6894 (void) putc ('\n', out);
6895
6896 for (part = m -> mp_parts; part; part = part -> mp_next) {
6897 register CT p = part -> mp_part;
6898
6899 fprintf (out, "\n--%s\n", ci -> ci_values[0]);
6900 (void) output_content (p, out);
6901 }
6902
6903 fprintf (out, "\n--%s--\n", ci -> ci_values[0]);
6904 }
6905 break;
6906
6907 case CT_TEXT:
6908 if (ct -> c_ctparams
6909 && ((struct text *) ct -> c_ctparams) -> tx_charset
6910 != CHARSET_USASCII) {
6911 quoted_printable: ;
6912 if (checksw)
6913 writeDigest (ct, out, 1);
6914 fprintf (out, "%s: %s\n\n", ENCODING_FIELD,
6915 "quoted-printable");
6916 (void) writeQuoted (ct, out);
6917 break;
6918 }
6919 if ((ct -> c_subtype != TEXT_PLAIN && ct -> c_encoding != CE_7BIT)
6920 || checksw)
6921 goto quoted_printable;
6922 /* else fall... */
6923
6924 case CT_MESSAGE:
6925 seven_bit: ;
6926 (void) putc ('\n', out);
6927 if (ct -> c_type == CT_MESSAGE
6928 && ct -> c_subtype == MESSAGE_EXTERNAL) {
6929 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
6930
6931 (void) output_content (e -> eb_content, out);
6932 if (e -> eb_body) {
6933 register char *cp;
6934
6935 putc ('\n', out);
6936 for (cp = e -> eb_body; *cp; cp++) {
6937 CT ct2 = e -> eb_content;
6938 CI ci2 = &ct2 -> c_ctinfo;
6939
6940 if (*cp == '\\')
6941 switch (*++cp) {
6942 case 'I':
6943 if (ct2 -> c_id) {
6944 char *dp = trimcpy (ct2 -> c_id);
6945
6946 (void) fputs (dp, out);
6947 free (dp);
6948 }
6949 continue;
6950
6951 case 'N':
6952 for (ap = ci2 -> ci_attrs,
6953 ep = ci2 -> ci_values;
6954 *ap;
6955 ap++, ep++)
6956 if (uleq (*ap, "name")) {
6957 fprintf (out, "%s", *ep);
6958 break;
6959 }
6960 continue;
6961
6962 case 'T':
6963 fprintf (out, "%s/%s", ci2 -> ci_type,
6964 ci2 -> ci_subtype);
6965 for (ap = ci2 -> ci_attrs,
6966 ep = ci2 -> ci_values;
6967 *ap;
6968 ap++, ep++)
6969 fprintf (out, "; %s=\"%s\"", *ap, *ep);
6970 continue;
6971
6972 case 'n':
6973 (void) putc ('\n', out);
6974 continue;
6975
6976 case 't':
6977 (void) putc ('\t', out);
6978 continue;
6979
6980 case '\0':
6981 cp--;
6982 break;
6983
6984 case '\\':
6985 case '"':
6986 break;
6987
6988 default:
6989 (void) putc ('\\', out);
6990 break;
6991 }
6992
6993 (void) putc (*cp, out);
6994 }
6995 putc ('\n', out);
6996 }
6997 }
6998 else
6999 (void) write7Bit (ct, out);
7000 break;
7001
7002 case CT_APPLICATION:
7003 switch (ct -> c_encoding) {
7004 case CE_7BIT:
7005 goto seven_bit;
7006
7007 case CE_QUOTED:
7008 goto quoted_printable;
7009
7010 default:
7011 break;
7012 }
7013 /* else fall... */
7014
7015 default:
7016 if (checksw)
7017 writeDigest (ct, out, 0);
7018 fprintf (out, "%s: %s\n\n", ENCODING_FIELD, "base64");
7019 (void) writeBase64 (ct, out);
7020 break;
7021 }
7022
7023 return OK;
7024 }
7025
7026 /* \f */
7027
7028 static int write7Bit (ct, out)
7029 register CT ct;
7030 FILE *out;
7031 {
7032 char c,
7033 buffer[BUFSIZ];
7034 FILE *in;
7035
7036 if ((in = fopen (ct -> c_file, "r")) == NULL)
7037 adios (ct -> c_file, "unable to open for reading");
7038
7039 c = '\n';
7040 while (fgets (buffer, sizeof buffer - 1, in)) {
7041 c = buffer[strlen (buffer) - 1];
7042 (void) fputs (buffer, out);
7043 }
7044 if (c != '\n')
7045 (void) putc ('\n', out);
7046
7047 (void) fclose (in);
7048
7049 return OK;
7050 }
7051
7052 /* \f */
7053
7054 static int writeQuoted (ct, out)
7055 register CT ct;
7056 FILE *out;
7057 {
7058 register char *cp;
7059 char c,
7060 buffer[BUFSIZ];
7061 FILE *in;
7062
7063 if ((in = fopen (ct -> c_file, "r")) == NULL)
7064 adios (ct -> c_file, "unable to open for reading");
7065
7066 while (fgets (buffer, sizeof buffer - 1, in)) {
7067 register int n;
7068
7069 cp = buffer + strlen (buffer) - 1;
7070 if ((c = *cp) == '\n')
7071 *cp = '\0';
7072
7073 if ((*(cp = buffer) == '.')
7074 || (strncmp (cp, "From ", sizeof "From " - 1) == 0)) {
7075 (void) fprintf (out, "=%02X", *cp++ & 0xff);
7076 n = 3;
7077 }
7078 else
7079 n = 0;
7080 for (; *cp; cp++) {
7081 if (n > CPERLIN - 3) {
7082 (void) fputs ("=\n", out);
7083 n = 0;
7084 }
7085
7086 switch (*cp) {
7087 case ' ':
7088 case '\t':
7089 (void) putc (*cp, out);
7090 n++;
7091 break;
7092
7093 default:
7094 if (*cp < '!'
7095 || *cp > '~'
7096 || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
7097 goto three_print;
7098 (void) putc (*cp, out);
7099 n++;
7100 break;
7101
7102 case '=':
7103 three_print: ;
7104 (void) fprintf (out, "=%02X", *cp & 0xff);
7105 n += 3;
7106 break;
7107 }
7108 }
7109
7110 if (c == '\n') {
7111 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
7112 (void) fputs ("=\n", out);
7113
7114 (void) putc ('\n', out);
7115 }
7116 else
7117 (void) fputs ("=\n", out);
7118 }
7119
7120 (void) fclose (in);
7121
7122 return OK;
7123 }
7124
7125 /* \f */
7126
7127 static char nib2b64[0x40+1] =
7128 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7129
7130
7131 static int writeBase64 (ct, out)
7132 register CT ct;
7133 FILE *out;
7134 {
7135 int result;
7136 FILE *in;
7137
7138 if ((in = fopen (ct -> c_file, "r")) == NULL)
7139 adios (ct -> c_file, "unable to open for reading");
7140
7141 result = writeBase64aux (in, out);
7142
7143 (void) fclose (in);
7144
7145 return result;
7146 }
7147
7148
7149 static int writeBase64aux (in, out)
7150 FILE *in,
7151 *out;
7152 {
7153 int cc,
7154 n;
7155 char inbuf[3];
7156
7157 n = BPERLIN;
7158 while ((cc = fread (inbuf, sizeof *inbuf, sizeof inbuf, in)) > 0) {
7159 unsigned long bits;
7160 register char *bp;
7161 char outbuf[4];
7162
7163 if (cc < sizeof inbuf) {
7164 inbuf[2] = 0;
7165 if (cc < sizeof inbuf - 1)
7166 inbuf[1] = 0;
7167 }
7168 bits = (inbuf[0] & 0xff) << 16;
7169 bits |= (inbuf[1] & 0xff) << 8;
7170 bits |= inbuf[2] & 0xff;
7171
7172 for (bp = outbuf + sizeof outbuf; bp > outbuf; bits >>= 6)
7173 *--bp = nib2b64[bits & 0x3f];
7174 if (cc < sizeof inbuf) {
7175 outbuf[3] = '=';
7176 if (cc < sizeof inbuf - 1)
7177 outbuf[2] = '=';
7178 }
7179
7180 (void) fwrite (outbuf, sizeof *outbuf, sizeof outbuf, out);
7181
7182 if (cc < sizeof inbuf) {
7183 (void) putc ('\n', out);
7184 return OK;
7185 }
7186
7187 if (--n <= 0) {
7188 n = BPERLIN;
7189 (void) putc ('\n', out);
7190 }
7191 }
7192 if (n != BPERLIN)
7193 (void) putc ('\n', out);
7194
7195 return OK;
7196 }
7197
7198 /* \f */
7199
7200 static int writeDigest (ct, out, asciiP)
7201 register CT ct;
7202 FILE *out;
7203 int asciiP;
7204 {
7205 int cc;
7206 char buffer[BUFSIZ];
7207 register unsigned char *dp;
7208 unsigned char digest[16];
7209 FILE *in;
7210 MD5_CTX mdContext;
7211
7212 if ((in = fopen (ct -> c_file, "r")) == NULL)
7213 adios (ct -> c_file, "unable to open for reading");
7214
7215 MD5Init (&mdContext);
7216 if (asciiP) {
7217 while (fgets (buffer, sizeof buffer - 1, in)) {
7218 register char *cp;
7219 char c;
7220
7221 cp = buffer + strlen (buffer) - 1;
7222 if ((c = *cp) == '\n')
7223 *cp = '\0';
7224
7225 MD5Update (&mdContext, (unsigned char *) buffer,
7226 (unsigned int) strlen (buffer));
7227
7228 if (c == '\n')
7229 MD5Update (&mdContext, (unsigned char *) "\r\n", 2);
7230 }
7231 }
7232 else
7233 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, in)) > 0)
7234 MD5Update (&mdContext, (unsigned char *) buffer,
7235 (unsigned int) cc);
7236 MD5Final (digest, &mdContext);
7237 if (debugsw) {
7238 unsigned char *ep;
7239
7240 fprintf (stderr, "MD5 digest=");
7241 for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
7242 dp < ep;
7243 dp++)
7244 fprintf (stderr, "%02x", *dp & 0xff);
7245 fprintf (stderr, "\n");
7246 }
7247
7248 (void) fclose (in);
7249
7250 fprintf (out, "%s: ", MD5_FIELD);
7251 for (dp = digest, cc = sizeof digest / sizeof digest[0]; cc > 0; cc -= 3) {
7252 unsigned long bits;
7253 register char *bp;
7254 char outbuf[4];
7255
7256 bits = (*dp++ & 0xff) << 16;
7257 if (cc > 1) {
7258 bits |= (*dp++ & 0xff) << 8;
7259 if (cc > 2)
7260 bits |= *dp++ & 0xff;
7261 }
7262
7263 for (bp = outbuf + sizeof outbuf; bp > outbuf; bits >>= 6)
7264 *--bp = nib2b64[bits & 0x3f];
7265 if (cc < 3) {
7266 outbuf[3] = '=';
7267 if (cc < 2)
7268 outbuf[2] = '=';
7269 }
7270
7271 (void) fwrite (outbuf, sizeof *outbuf, sizeof outbuf, out);
7272 }
7273 fprintf (out, "\n");
7274 }
7275
7276 /* \f */
7277
7278 static int readDigest (ct, cp)
7279 register CT ct;
7280 register char *cp;
7281 {
7282 int bitno,
7283 skip;
7284 unsigned long bits;
7285 char *bp = cp;
7286 register unsigned char *dp;
7287 unsigned char value,
7288 *ep,
7289 *b = (unsigned char *) &bits,
7290 *b1 = &b[endian > 0 ? 1 : 2],
7291 *b2 = &b[endian > 0 ? 2 : 1],
7292 *b3 = &b[endian > 0 ? 3 : 0];
7293
7294 bitno = 18, bits = 0L, skip = 0;
7295 for (ep = (dp = ct -> c_digest)
7296 + sizeof ct -> c_digest / sizeof ct -> c_digest[0];
7297 *cp;
7298 cp++)
7299 switch (*cp) {
7300 default:
7301 if (skip
7302 || (*cp & 0x80)
7303 || (value = b642nib[*cp & 0x7f]) > 0x3f) {
7304 if (debugsw)
7305 fprintf (stderr, "invalid BASE64 encoding\n");
7306 return NOTOK;
7307 }
7308
7309 bits |= value << bitno;
7310 test_end: ;
7311 if ((bitno -= 6) < 0) {
7312 if (dp + (3 - skip) > ep)
7313 goto invalid_digest;
7314 *dp++ = *b1;
7315 if (skip < 2) {
7316 *dp++ = *b2;
7317 if (skip < 1)
7318 *dp++ = *b3;
7319 }
7320 bitno = 18, bits = 0L, skip = 0;
7321 }
7322 break;
7323
7324 case '=':
7325 if (++skip > 3)
7326 goto self_delimiting;
7327 goto test_end;
7328 }
7329 if (bitno != 18) {
7330 if (debugsw)
7331 fprintf (stderr, "premature ending (bitno %d)\n", bitno);
7332
7333 return NOTOK;
7334 }
7335 self_delimiting: ;
7336 if (dp != ep) {
7337 invalid_digest: ;
7338 if (debugsw) {
7339 while (*cp)
7340 cp++;
7341 fprintf (stderr, "invalid MD5 digest (got %d octets)\n",
7342 cp - bp);
7343 }
7344
7345 return NOTOK;
7346 }
7347
7348 if (debugsw) {
7349 fprintf (stderr, "MD5 digest=");
7350 for (dp = ct -> c_digest; dp < ep; dp++)
7351 fprintf (stderr, "%02x", *dp & 0xff);
7352 fprintf (stderr, "\n");
7353 }
7354
7355 return OK;
7356 }
7357
7358 /* \f VIAMAIL */
7359
7360 #include "../zotnet/tws.h"
7361
7362
7363 static int via_mail (mailsw, subjsw, parmsw, descsw, cmntsw, slowsw, fromsw)
7364 char *mailsw,
7365 *subjsw,
7366 *parmsw,
7367 *descsw,
7368 *cmntsw,
7369 *fromsw;
7370 int slowsw;
7371 {
7372 int nlines,
7373 nparts,
7374 status;
7375 long pos;
7376 long offset;
7377 char tmpfil[BUFSIZ];
7378 struct stat st;
7379 FILE *fp;
7380
7381 (void) umask (~m_gmprot ());
7382
7383 (void) strcpy (tmpfil, m_tmpfil (invo_name));
7384 if ((fp = fopen (tmpfil, "w+")) == NULL)
7385 adios (tmpfil, "unable to open for writing");
7386 (void) chmod (tmpfil, 0600);
7387
7388 if (!index (mailsw, '@@'))
7389 mailsw = concat (mailsw, "@@", LocalName (), NULLCP);
7390 fprintf (fp, "To: %s\n", mailsw);
7391 nlines = 1;
7392 if (subjsw)
7393 fprintf (fp, "Subject: %s\n", subjsw), nlines++;
7394 if (fromsw) {
7395 if (!index (fromsw, '@@'))
7396 fromsw = concat (fromsw, "@@", LocalName (), NULLCP);
7397 fprintf (fp, "From: %s\n", fromsw), nlines++;
7398 }
7399 fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE), nlines++;
7400 offset = ftell (fp);
7401 fprintf (fp, "%s: application/octet-stream", TYPE_FIELD);
7402 if (parmsw)
7403 fprintf (fp, "; %s", parmsw);
7404 if (cmntsw)
7405 fprintf (fp, "\n\t(%s)", cmntsw), nlines++;
7406 if (descsw)
7407 fprintf (fp, "\n%s: %s", DESCR_FIELD, descsw), nlines++;
7408 fprintf (fp, "\n%s: %s\n\n", ENCODING_FIELD, "base64"), nlines += 2;
7409 if (fflush (fp))
7410 adios (tmpfil, "error writing to");
7411
7412 pos = ftell (fp);
7413 (void) writeBase64aux (stdin, fp);
7414 if (fflush (fp))
7415 adios (tmpfil, "error writing to");
7416
7417 if (fstat (fileno (fp), &st) == NOTOK)
7418 adios ("failed", "fstat of %s", tmpfil);
7419 nlines += (((long) st.st_size - pos) + CPERLIN) / (CPERLIN + 1);
7420 nparts = (nlines + (LPERMSG - 1)) / LPERMSG;
7421
7422 if (nparts <= 1)
7423 status = via_post (tmpfil, 0);
7424 else {
7425 int partno;
7426 long clock;
7427 char buffer[BUFSIZ],
7428 msgid[BUFSIZ];
7429
7430 if (verbosw) {
7431 printf ("sending binary image as %d partial messages\n", nparts);
7432 (void) fflush (stdout);
7433 }
7434
7435 (void) time (&clock);
7436 (void) sprintf (msgid, "<%d.%ld@@%s>", getpid (), clock, LocalName ());
7437
7438 (void) fseek (fp, offset, 0);
7439 for (partno = 1; partno <= nparts; partno++) {
7440 int lineno;
7441 char tmpdrf[BUFSIZ];
7442 FILE *out;
7443
7444 (void) strcpy (tmpdrf, m_tmpfil (invo_name));
7445 if ((out = fopen (tmpdrf, "w")) == NULL)
7446 adios (tmpdrf, "unable to open for writing");
7447 (void) chmod (tmpdrf, 0600);
7448
7449 fprintf (out, "To: %s\n", mailsw);
7450 if (subjsw)
7451 fprintf (out, "Subject: %s\n", subjsw);
7452 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
7453 fprintf (out,
7454 "%s: message/partial; id=\"%s\";\n\tnumber=%d; total=%d\n",
7455 TYPE_FIELD, msgid, partno, nparts);
7456 fprintf (out, "%s: part %d of %d\n\n", DESCR_FIELD, partno,
7457 nparts);
7458
7459 if (partno == 1)
7460 fprintf (out, "Message-ID: %s\n", msgid);
7461
7462 for (lineno = LPERMSG; lineno > 0; lineno--) {
7463 if (!fgets (buffer, sizeof buffer, fp)) {
7464 if (partno == nparts)
7465 break;
7466 adios (NULLCP, "premature eof");
7467 }
7468
7469 (void) fputs (buffer, out);
7470 }
7471 offset = ftell (fp);
7472
7473 if (fflush (out))
7474 adios (tmpdrf, "error writing to");
7475
7476 (void) fclose (out);
7477
7478 status = via_post (tmpdrf, slowsw == 0);
7479 (void) unlink (tmpdrf);
7480 if (status)
7481 break;
7482
7483 if (slowsw > 0 && partno < nparts) {
7484 if (verbosw) {
7485 printf ("pausing %d seconds before sending part %d...\n",
7486 slowsw, partno + 1);
7487 (void) fflush (stdout);
7488 }
7489
7490 sleep ((unsigned) slowsw);
7491 }
7492 }
7493 }
7494
7495 (void) fclose (fp);
7496 (void) unlink (tmpfil);
7497
7498 done (status ? 1 : 0);
7499 }
7500
7501 /* \f */
7502
7503 static int via_post (file, queued)
7504 char *file;
7505 int queued;
7506 {
7507 int child_id,
7508 i;
7509
7510 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
7511 sleep (5);
7512 switch (child_id) {
7513 case NOTOK:
7514 adios ("fork", "unable to");
7515 /* NOTREACHED */
7516
7517 case OK:
7518 (void) execlp (postproc, r1bindex (postproc, '/'), file,
7519 queued ? "-queued" : NULLCP, NULLCP);
7520 fprintf (stderr, "unable to exec ");
7521 perror (postproc);
7522 _exit (-1);
7523 /* NOTREACHED */
7524
7525 default:
7526 return pidXwait (child_id, postproc);
7527 }
7528 }
7529
7530 /* \f */
7531
7532 void done (status)
7533 int status;
7534 {
7535 register CT *ctp;
7536
7537 if (ctp = cts)
7538 for (; *ctp; ctp++)
7539 free_content (*ctp);
7540 if (free_ct)
7541 free_content (free_ct);
7542 if (free_file)
7543 (void) unlink (free_file);
7544
7545 exit (status);
7546 }
7547
7548
7549 static int pidcheck (status)
7550 int status;
7551 {
7552 if ((status & 0xff00) == 0xff00 || (status & 0x007f) != SIGQUIT)
7553 return status;
7554
7555 (void) unlink ("core");
7556
7557 (void) fflush (stdout);
7558
7559 (void) fflush (stderr);
7560
7561 done (1);
7562 /* NOTREACHED */
7563 }
7564 @
7565
7566
7567 2.41
7568 log
7569 @pgp fixes from mtr
7570 @
7571 text
7572 @d3 1
7573 a3 1
7574 static char ident[] = "@@(#)$Id: mhn.c,v 2.40 1995/12/06 21:03:37 jromine Exp jromine $";
7575 d1019 1
7576 a1019 1
7577 int si_value;
7578 d1162 1
7579 a1162 1
7580 ct -> c_type = s2i -> si_value;
7581 d1201 1
7582 a1201 1
7583 ct -> c_encoding = s2i -> si_value;
7584 d3674 1
7585 a3674 1
7586 e -> eb_flags = s2i -> si_value;
7587 d5889 1
7588 a5889 1
7589 switch (ct -> c_type = s2i -> si_value) {
7590 d5925 1
7591 a5925 1
7592 switch (ct -> c_type = s2i -> si_value) {
7593 @
7594
7595
7596 2.40
7597 log
7598 @mhn bugfix
7599 @
7600 text
7601 @d3 1
7602 a3 1
7603 static char ident[] = "@@(#)$Id: mhn.c,v 2.39 1995/12/06 21:02:05 jromine Exp jromine $";
7604 d1093 1
7605 d1098 1
7606 d1100 1
7607 d1102 2
7608 @
7609
7610
7611 2.39
7612 log
7613 @enhancements for quoted-printable from mtr
7614 @
7615 text
7616 @d3 1
7617 a3 1
7618 static char ident[] = "@@(#)$Id: mhn.c,v 2.38 1995/12/06 20:55:31 jromine Exp jromine $";
7619 d3383 3
7620 a3385 1
7621 if (ct -> c_subtype == MULTI_ALTERNATE && m -> mp_parts -> mp_next) {
7622 @
7623
7624
7625 2.38
7626 log
7627 @fix from mtr
7628 @
7629 text
7630 @d3 1
7631 a3 1
7632 static char ident[] = "@@(#)$Id: mhn.c,v 2.37 1995/12/06 19:20:22 jromine Exp jromine $";
7633 d6452 10
7634 a6461 4
7635 if (linelen == -1
7636 && (cp = buffer + strlen (buffer) - 2) > buffer
7637 && isspace (*cp))
7638 linelen = 1;
7639 d6798 2
7640 a6799 1
7641 if (strncmp (cp = buffer, "From ", sizeof "From " - 1) == 0) {
7642 @
7643
7644
7645 2.37
7646 log
7647 @fixes from mtr
7648 @
7649 text
7650 @d3 1
7651 a3 1
7652 static char ident[] = "@@(#)$Id: mhn.c,v 2.36 1994/04/21 19:23:38 jromine Exp jromine $";
7653 a6618 4
7654 if (p -> c_type == CT_MESSAGE
7655 && p -> c_subtype != MESSAGE_EXTERNAL
7656 && !p -> c_rfc934)
7657 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
7658 @
7659
7660
7661 2.36
7662 log
7663 @mhn fixes from MTR
7664 @
7665 text
7666 @d3 1
7667 a3 1
7668 static char ident[] = "@@(#)$Id: mhn.c,v 2.35 1993/10/26 22:17:44 jromine Exp jromine $";
7669 d1291 1
7670 d2130 1
7671 a2130 1
7672 if (intr != OK) {
7673 d5074 1
7674 a5074 1
7675 e -> eb_mode && uleq (e -> eb_mode, "ascii"), 0)
7676 @
7677
7678
7679 2.35
7680 log
7681 @change to re-sync with mtr's version
7682 @
7683 text
7684 @d3 1
7685 a3 1
7686 static char ident[] = "@@(#)$Id: mhn.c,v 2.34 1993/10/26 20:15:00 jromine Exp jromine $";
7687 d2608 1
7688 d2611 1
7689 d2613 1
7690 a2613 1
7691 free (*ap);
7692 d2616 1
7693 d2619 1
7694 d2631 1
7695 d2635 1
7696 d2639 1
7697 d2645 1
7698 d2649 1
7699 d2652 1
7700 d2655 1
7701 d2659 1
7702 d2662 1
7703 d2666 1
7704 d2669 1
7705 d2675 1
7706 d2679 1
7707 d2683 1
7708 d2745 1
7709 a2745 1
7710 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7711 d2844 1
7712 a2844 1
7713 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7714 d4063 1
7715 a4063 1
7716 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7717 d4445 5
7718 a4449 2
7719 if ((cp = getenv ("MM_NOASK")) && strcmp (cp, "1") == 0)
7720 nolist = 1, listsw = pausesw = 0;
7721 d6397 1
7722 a6397 3
7723 if (ct -> c_type != CT_TEXT
7724 && !(ct -> c_type == CT_APPLICATION
7725 && ct -> c_subtype == APPLICATION_POSTSCRIPT))
7726 d6474 4
7727 a6477 1
7728 ? CE_7BIT : CE_QUOTED;
7729 d6725 2
7730 a6726 2
7731 if (ct -> c_subtype == APPLICATION_POSTSCRIPT) {
7732 if (ct -> c_encoding == CE_7BIT)
7733 d6728 6
7734 a6733 1
7735 goto quoted_printable;
7736 @
7737
7738
7739 2.34
7740 log
7741 @fixes from mtr -- content-id?
7742 @
7743 text
7744 @d3 1
7745 a3 1
7746 static char ident[] = "@@(#)$Id: mhn.c,v 2.33 1993/10/26 20:11:27 jromine Exp jromine $";
7747 d12 1
7748 d2564 1
7749 a2564 1
7750 for (cp = file; cp = index (cp, '/'); cp++) {
7751 d3598 2
7752 a3603 3
7753
7754 unsigned long
7755 eb_size;
7756 d3922 3
7757 a3924 2
7758 content_error (NULLCP, ct,
7759 "empty body for access-type=mail-server");
7760 d4682 1
7761 a4682 1
7762
7763 d5223 1
7764 a5223 1
7765 && find_cache_aux (writing, cache_private, id,
7766 d5235 1
7767 a5235 1
7768 && find_cache_aux (writing, cache_public, id,
7769 d5247 1
7770 a5247 1
7771 && find_cache_aux (writing, cache_private, id,
7772 d5301 1
7773 a5301 1
7774 int *writing;
7775 d5306 1
7776 d5315 3
7777 d5338 16
7778 a5353 2
7779 (void) sprintf (mapname, "%s/%s", directory, invo_name);
7780 (void) strcpy (mapname, r1bindex (m_scratch (mapname, invo_name), '/'));
7781 d5355 2
7782 d5360 12
7783 a5371 1
7784 if (!(fp = fopen (mapfile, "a")))
7785 d5374 1
7786 a5374 1
7787 (void) fclose (fp);
7788 d5399 1
7789 a5399 1
7790 if (!(fp = fopen (mapfile, "r")))
7791 d5430 1
7792 a5430 1
7793 (void) fclose (fp);
7794 d5446 1
7795 a5446 1
7796 (void) fclose (fp);
7797 d5862 5
7798 d5874 1
7799 d6032 7
7800 a6038 6
7801 if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK)
7802 done (1);
7803 ct -> c_type = CT_MULTIPART;
7804 ct -> c_subtype = MULTI_DIGEST;
7805 ct -> c_ctlistfnx = list_multi;
7806 ct -> c_ctfreefnx = free_multi;
7807 d6040 3
7808 a6042 3
7809 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
7810 adios (NULLCP, "out of memory");
7811 ct -> c_ctparams = (caddr_t) m;
7812 d6044 4
7813 a6047 1
7814 pp = &m -> mp_parts;
7815 d6066 9
7816 a6074 4
7817 if ((part = (struct part *) calloc (1, sizeof *part)) == NULL)
7818 adios (NULLCP, "out of memory");
7819 *pp = part, pp = &part -> mp_next;
7820 part -> mp_part = p;
7821 d6637 3
7822 d6642 30
7823 @
7824
7825
7826 2.33
7827 log
7828 @minor fixup in DESCR/ID_FIELD
7829 @
7830 text
7831 @d3 1
7832 a3 1
7833 static char ident[] = "@@(#)$Id: mhn.c,v 2.32 1993/10/26 15:56:01 jromine Exp jromine $";
7834 d1518 20
7835 a6044 1
7836
7837 d6512 1
7838 a6512 1
7839 fprintf (out, "%s", buffer);
7840 d6527 1
7841 a6527 1
7842 fprintf (out, "\n");
7843 d6543 1
7844 a6543 1
7845 fprintf (out, "\n");
7846 d6572 2
7847 a6573 1
7848 if (ct -> c_subtype != TEXT_PLAIN && ct -> c_encoding != CE_7BIT)
7849 a6574 2
7850 if (checksw)
7851 goto quoted_printable;
7852 d6579 1
7853 a6579 1
7854 fprintf (out, "\n");
7855 d6585 32
7856 a6616 2
7857 if (e -> eb_body)
7858 fprintf (out, "\n%s\n", e -> eb_body);
7859 @
7860
7861
7862 2.32
7863 log
7864 @formatting fixup (part 2)
7865 @
7866 text
7867 @d3 1
7868 a3 1
7869 static char ident[] = "@@(#)$Id: mhn.c,v 2.28 1993/10/25 19:58:19 jromine Exp jromine $";
7870 d4699 1
7871 a4699 1
7872 fprintf (ce -> ce_fp, "%s: %s", ID_FIELD, ct -> c_id);
7873 d4701 2
7874 a4702 1
7875 fprintf (ce -> ce_fp, "%s: %s", DESCR_FIELD, ct -> c_descr);
7876 @
7877
7878
7879 2.31
7880 log
7881 @fixup formatting
7882 @
7883 text
7884 @d4867 1
7885 a4867 3
7886 (void) fclose (fp);
7887 }
7888 (void) umask (mask);
7889 d4869 2
7890 @
7891
7892
7893 2.30
7894 log
7895 @cache changes (part 2)
7896 @
7897 text
7898 @d4793 1
7899 a4793 1
7900 ce -> ce_unlink = 0;
7901 d4795 2
7902 a4796 2
7903 goto ready_already;
7904 }
7905 d4799 1
7906 a4799 1
7907 }
7908 d4842 2
7909 a4843 2
7910 int mask;
7911 FILE *fp;
7912 d4846 2
7913 a4847 2
7914 if (fp = fopen (cachefile, "w")) {
7915 int cc;
7916 d4851 1
7917 a4851 1
7918 (void) fseek (gp, 0L, 0);
7919 d4855 2
7920 a4856 2
7921 (void) fwrite (buffer, sizeof *buffer, cc, fp);
7922 (void) fflush (fp);
7923 d4858 4
7924 a4861 4
7925 if (ferror (gp)) {
7926 admonish (ce -> ce_file, "error reading");
7927 (void) unlink (cachefile);
7928 }
7929 d4959 3
7930 a4961 4
7931 if (*file == NULL) {
7932 ce -> ce_unlink = 0;
7933 caching = 1;
7934 }
7935 d4963 1
7936 d5059 4
7937 a5062 4
7938 if (ferror (fp)) {
7939 admonish (cachefile, "error writing");
7940 (void) unlink (cachefile);
7941 }
7942 @
7943
7944
7945 2.29
7946 log
7947 @add -nocache, -rcache, -wcache
7948 @
7949 text
7950 @d147 7
7951 a153 3
7952 #define CACHE_ALWAYS 0
7953 "always", 0,
7954 #define CACHE_ASK 1
7955 a154 2
7956 #define CACHE_NEVER 2
7957 "never", 0,
7958 d160 1
7959 a160 1
7960 static int cachesw = CACHE_ASK;
7961 d173 1
7962 d182 1
7963 d190 2
7964 a191 1
7965 static char *cache;
7966 d318 1
7967 d330 1
7968 d352 2
7969 a353 1
7970 msgnum;
7971 d413 12
7972 d427 1
7973 a427 1
7974 switch (cachesw = smatch (cp, caches)) {
7975 d639 6
7976 a644 1
7977 cache = cachesw != CACHE_NEVER ? m_find (buf) : NULLCP;
7978 d658 1
7979 d781 1
7980 a781 1
7981 if (!listsw && !showsw && !storesw)
7982 d817 2
7983 d831 2
7984 d838 13
7985 d862 2
7986 d896 2
7987 d949 2
7988 d2057 1
7989 a2057 1
7990 list_content (ct, -1);
7991 a3977 1
7992
7993 a4656 3
7994 if ((len = ct -> c_end - ct -> c_begin) < 0)
7995 adios (NULLCP, "internal error(3)");
7996
7997 a4657 1
7998 int len = 0;
7999 d4662 2
8000 d4704 3
8001 d4772 1
8002 a4772 1
8003 char *id;
8004 d4791 2
8005 a4792 33
8006 if (xpid) {
8007 if (xpid < 0)
8008 xpid = -xpid;
8009 (void) pidcheck (pidwait (xpid, NOTOK));
8010 xpid = 0;
8011 }
8012
8013 if (cache && (id = cb -> c_id)) {
8014 char buffer[BUFSIZ];
8015
8016 (void) sprintf (buffer, "%s/%s", cache, id = trimcpy (id));
8017 free (id);
8018
8019 id = getcpy (buffer);
8020 if (ce -> ce_fp = fopen (id, "r")) {
8021 char *bp;
8022 struct stat st;
8023
8024 if (cachesw == CACHE_ALWAYS)
8025 goto do_cache;
8026
8027 (void) fstat (fileno (ce -> ce_fp), &st);
8028 (void) sprintf (bp = buffer,
8029 "Use cached copy %s of size %lu octets",
8030 id, (unsigned long) st.st_size);
8031 bp += strlen (bp);
8032 if (ct -> c_partno) {
8033 (void) sprintf (bp, " (content %s)", ct -> c_partno);
8034 bp += strlen (bp);
8035 }
8036 (void) sprintf (bp, "? ");
8037 if (getanswer (buffer)) {
8038 do_cache: ;
8039 d4794 1
8040 a4794 1
8041 ce -> ce_file = id;
8042 d4797 2
8043 a4798 2
8044
8045 (void) fclose (ce -> ce_fp), ce -> ce_fp = NULL;
8046 a4799 2
8047 free (id);
8048 }
8049 d4810 3
8050 a4812 2
8051 int fd;
8052 char *id;
8053 d4839 3
8054 a4841 9
8055 if (cache
8056 && (id = e -> eb_content -> c_id)
8057 && (!e -> eb_permission
8058 || !uleq (e -> eb_permission, "read-write"))) {
8059 char buffer[BUFSIZ];
8060
8061 (void) sprintf (buffer, "Make cached, publically-accessible copy of %s? ",
8062 e -> eb_name);
8063 if (cachesw == CACHE_ALWAYS || getanswer (buffer)) {
8064 a4842 1
8065 char cachefile[BUFSIZ];
8066 d4845 1
8067 a4845 4
8068 (void) sprintf (cachefile, "%s/%s", cache, id = trimcpy (id));
8069 free (id);
8070
8071 mask = umask (0022);
8072 d4848 2
8073 a4849 1
8074 register FILE *gp = ce -> ce_fp;
8075 d4853 2
8076 a4854 2
8077 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer,
8078 gp)) > 0)
8079 d4862 1
8080 a4862 1
8081
8082 a4870 1
8083 }
8084 d4883 2
8085 a4884 1
8086 int caching,
8087 d4886 2
8088 a4887 2
8089 char *ftp,
8090 *id,
8091 d4921 22
8092 a4942 7
8093 (void) sprintf (buffer,
8094 e -> eb_size > 0
8095 ? "Retrieve %s (content %s)\n using %sFTP from site %s (%lu octets)? "
8096 : "Retrieve %s (content %s)\n using %sFTP from site %s? ",
8097 e -> eb_name, e -> eb_partno,
8098 e -> eb_flags ? "anonymous " : "",
8099 e -> eb_site, e -> eb_size);
8100 d4956 3
8101 a4958 9
8102 if (cache
8103 && (id = e -> eb_content -> c_id)
8104 && (!e -> eb_permission
8105 || !uleq (e -> eb_permission, "read-write"))) {
8106 (void) sprintf (buffer, "Make cached, publically-accessible copy? ");
8107 if (cachesw == CACHE_ALWAYS || getanswer (buffer)) {
8108 (void) sprintf (cachefile, "%s/%s", cache, id = trimcpy (id));
8109 free (id);
8110
8111 a4963 1
8112 }
8113 a4975 1
8114
8115 d5037 1
8116 a5037 1
8117 (void) chmod (cachefile, 0644);
8118 d5040 1
8119 a5040 1
8120 register FILE *fp;
8121 d5042 1
8122 a5042 1
8123 mask = umask (0022);
8124 d5044 2
8125 a5045 1
8126 register FILE *gp = ce -> ce_fp;
8127 d5049 3
8128 a5051 2
8129 while (fgets (buffer, sizeof buffer - 1, gp))
8130 (void) fputs (buffer, fp);
8131 d5058 1
8132 a5058 1
8133
8134 a5081 1
8135 result,
8136 a5083 1
8137 *id,
8138 d5105 6
8139 a5110 6
8140 bp = concat ("Retrieve content ", e -> eb_partno, " by asking mailbox ",
8141 e -> eb_server, "\n\n",
8142 e -> eb_subject ? e -> eb_subject: e -> eb_body, "\n? ",
8143 NULLCP);
8144 result = getanswer (bp);
8145 free (bp);
8146 d5112 11
8147 a5122 1
8148 if (!result)
8149 d5129 1
8150 a5129 15
8151 if (e -> eb_subject)
8152 vec[vecp++] = "mail-server request";
8153 else
8154 if (cache
8155 && (id = e -> eb_content -> c_id)
8156 && (!e -> eb_permission
8157 || !uleq (e -> eb_permission, "read-write"))) {
8158 (void) sprintf (buffer, "cache content as %s/%s", cache,
8159 id = trimcpy (id));
8160 free (id);
8161
8162 vec[vecp++] = buffer;
8163 }
8164 else
8165 vec[vecp++] = "mail-server request";
8166 d5170 311
8167 @
8168
8169
8170 2.28
8171 log
8172 @fixes from mtr (20-sep-93)
8173 @
8174 text
8175 @d3 1
8176 a3 1
8177 static char ident[] = "@@(#)$Id: mhn.c,v 2.27 1993/10/25 19:32:05 jromine Exp jromine $";
8178 d30 3
8179 a32 1
8180 "cache policy", 0,
8181 d34 1
8182 a34 1
8183 #define CHECKSW 3
8184 d36 1
8185 a36 1
8186 #define NCHECKSW 4
8187 d39 1
8188 a39 1
8189 #define DEBUGSW 5
8190 d42 1
8191 a42 1
8192 #define EBCDICSW 6
8193 d44 1
8194 a44 1
8195 #define NEBCDICSW 7
8196 d47 1
8197 a47 1
8198 #define FILESW 8 /* interface from show */
8199 d50 1
8200 a50 1
8201 #define FORMSW 9
8202 d53 1
8203 a53 1
8204 #define HEADSW 10
8205 d55 1
8206 a55 1
8207 #define NHEADSW 11
8208 d58 1
8209 a58 1
8210 #define LISTSW 12
8211 d60 1
8212 a60 1
8213 #define NLISTSW 13
8214 d63 1
8215 a63 1
8216 #define PARTSW 14
8217 d66 1
8218 a66 1
8219 #define PAUSESW 15
8220 d68 1
8221 a68 1
8222 #define NPAUSESW 16
8223 d71 4
8224 a74 1
8225 #define SIZESW 17
8226 d76 1
8227 a76 1
8228 #define NSIZESW 18
8229 d79 1
8230 a79 1
8231 #define RFC934SW 19
8232 d81 1
8233 a81 1
8234 #define NRFC934SW 20
8235 d84 1
8236 a84 1
8237 #define SERIALSW 21
8238 d86 1
8239 a86 1
8240 #define NSERIALSW 22
8241 d89 1
8242 a89 1
8243 #define SHOWSW 23
8244 d91 1
8245 a91 1
8246 #define NSHOWSW 24
8247 d94 1
8248 a94 1
8249 #define STORESW 25
8250 d96 1
8251 a96 1
8252 #define NSTORESW 26
8253 d99 1
8254 a99 1
8255 #define TYPESW 27
8256 d102 1
8257 a102 1
8258 #define VERBSW 28
8259 d104 1
8260 a104 1
8261 #define NVERBSW 29
8262 d106 3
8263 d110 1
8264 a110 1
8265 #define HELPSW 30
8266 d113 1
8267 a113 1
8268 #define PROGSW 31
8269 d115 1
8270 a115 1
8271 #define NPROGSW 32
8272 d118 1
8273 a118 1
8274 #define LENSW 33
8275 d120 1
8276 a120 1
8277 #define WIDSW 34
8278 d123 1
8279 a123 1
8280 #define VIAMSW 35
8281 d125 1
8282 a125 1
8283 #define VIASSW 36
8284 d127 1
8285 a127 1
8286 #define VIAPSW 37
8287 d129 1
8288 a129 1
8289 #define VIADSW 38
8290 d131 1
8291 a131 1
8292 #define VIACSW 39
8293 d133 1
8294 a133 1
8295 #define VIAZSW 40
8296 d135 1
8297 a135 1
8298 #define VIAFSW 41
8299 @
8300
8301
8302 2.27
8303 log
8304 @fixes from mtr: add MHN_SILENT, changes something in printing
8305 multi-part messages
8306 @
8307 text
8308 @d3 1
8309 a3 1
8310 static char ident[] = "@@(#)$Id: mhn.c,v 2.26 1993/09/09 22:38:43 jromine Exp jromine $";
8311 a818 4
8312 int child_id,
8313 i,
8314 vecp;
8315 char *vec[8];
8316 d846 5
8317 a850 14
8318 vecp = 0;
8319 vec[vecp++] = r1bindex (mhlproc, '/');
8320 vec[vecp++] = "-form";
8321 vec[vecp++] = formsw;
8322 vec[vecp++] = "-nobody";
8323 vec[vecp++] = ct -> c_file;
8324 if (nomore)
8325 vec[vecp++] = "-nomoreproc";
8326 else
8327 if (progsw) {
8328 vec[vecp++] = "-moreproc";
8329 vec[vecp++] = progsw;
8330 }
8331 vec[vecp] = NULL;
8332 d852 14
8333 a865 8
8334 (void) fflush (stdout);
8335
8336 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
8337 sleep (5);
8338 switch (child_id) {
8339 case NOTOK:
8340 adios ("fork", "unable to");
8341 /* NOTREACHED */
8342 d867 1
8343 a867 6
8344 case OK:
8345 (void) execvp (mhlproc, vec);
8346 fprintf (stderr, "unable to exec ");
8347 perror (mhlproc);
8348 _exit (-1);
8349 /* NOTREACHED */
8350 d869 18
8351 a886 3
8352 default:
8353 xpid = -child_id;
8354 break;
8355 d888 2
8356 d4336 1
8357 d4350 1
8358 a4350 1
8359 if (getenv ("MHN_SILENT"))
8360 @
8361
8362
8363 2.26
8364 log
8365 @fixes from mtr
8366 @
8367 text
8368 @d3 1
8369 a3 1
8370 static char ident[] = "@@(#)$Id: mhn.c,v 2.25 1993/09/01 21:46:58 jromine Exp jromine $";
8371 d157 1
8372 d1916 1
8373 a1916 1
8374 xlist = 1;
8375 d1994 4
8376 a1997 1
8377 (*ct -> c_ctlistfnx) (ct, -1);
8378 d3040 1
8379 a3040 1
8380 xlist = 1;
8381 d4343 3
8382 d4597 46
8383 @
8384
8385
8386 2.25
8387 log
8388 @fix from mrose for quoted-printable 8-bit chars
8389 @
8390 text
8391 @d3 1
8392 a3 1
8393 static char ident[] = "@@(#)$Id: mhn.c,v 2.24 1993/09/01 20:50:03 jromine Exp jromine $";
8394 d302 4
8395 a305 4
8396 static CT get_content ();
8397 static int list_content (), show_content (), store_content ();
8398 static int user_content(), compose_content(), output_content();
8399 static void free_content (), flush_errors ();
8400 d313 1
8401 a313 1
8402 static int init_encoding(), type_ok(), copy_some_headers(), set_endian();
8403 d315 1
8404 a315 1
8405 static int write7Bit(), writeQuoted(), writeBase64(), writeBase64aux();
8406 d317 1
8407 a317 1
8408 static int via_mail(), via_post(), pidcheck();
8409 d760 1
8410 a760 1
8411 if (type_ok (ct)
8412 d777 1
8413 a777 1
8414 if (type_ok (ct) && ct -> c_ctlistfnx) {
8415 d789 1
8416 a789 1
8417 if (type_ok (ct) && ct -> c_ctstorefnx) {
8418 d805 1
8419 a805 1
8420 if (type_ok (ct) && ct -> c_ctlistfnx) {
8421 d829 1
8422 a829 1
8423 if (!type_ok (ct))
8424 d1805 1
8425 a1805 1
8426 static int show_content_aux ();
8427 d1807 1
8428 d1842 1
8429 a1842 3
8430 int child_id,
8431 fd,
8432 i,
8433 d1849 1
8434 a1849 3
8435 *vec[4],
8436 buffer[BUFSIZ],
8437 exec[BUFSIZ + sizeof "exec "];
8438 d1890 9
8439 d1943 1
8440 d1945 3
8441 d1949 20
8442 d2087 2
8443 a2088 1
8444 (void) (*ct -> c_ceclosefnx) (ct);
8445 d2249 8
8446 a2256 17
8447 /*
8448 if (debugsw) {
8449 */
8450 (void) fflush (stdout);
8451
8452 fprintf (stderr, "storing message %s", ct -> c_file);
8453 if (ct -> c_partno)
8454 fprintf (stderr, " part %s", ct -> c_partno);
8455 fprintf (stderr, " as file %s\n",
8456 strncmp (ct -> c_storage, cwd, cwdlen)
8457 || ct -> c_storage[cwdlen] != '/'
8458 ? ct -> c_storage
8459 : ct -> c_storage + cwdlen + 1);
8460 /*
8461 }
8462 */
8463
8464 d2585 1
8465 a2585 1
8466 static int part_ok (ct)
8467 d2587 1
8468 d2591 2
8469 a2592 1
8470 if (ct -> c_type == CT_MULTIPART || npart == 0)
8471 d2604 1
8472 a2604 1
8473 static int type_ok (ct)
8474 d2606 1
8475 d2612 2
8476 a2613 1
8477 if (ct -> c_type == CT_MULTIPART || ntype == 0)
8478 d2786 1
8479 a2786 1
8480 if (part_ok (p) && type_ok (p) && p -> c_ctlistfnx)
8481 d2834 1
8482 a2834 1
8483 result = OK;
8484 d2838 5
8485 a2842 4
8486 if (part_ok (p)
8487 && type_ok (p)
8488 && p -> c_ctshowfnx) {
8489 switch ((*p -> c_ctshowfnx) (p, nowserial, nowalternate)) {
8490 d2856 1
8491 a2856 1
8492 if (alternate)
8493 d2858 3
8494 d2928 142
8495 d3084 2
8496 a3085 2
8497 if (part_ok (p)
8498 && type_ok (p)
8499 d3185 2
8500 a3186 1
8501 ct -> c_ctshowfnx = show_multi;
8502 d3658 1
8503 a3658 1
8504 if (!type_ok (p))
8505 d3676 1
8506 a3676 1
8507 if (!type_ok (p))
8508 d5221 2
8509 d5331 1
8510 d5461 1
8511 a5473 1
8512 char msgid[BUFSIZ];
8513 a5475 3
8514 static int partno;
8515 static long clock = 0L;
8516 static char *msgfmt;
8517 a5509 11
8518 if (clock == 0L) {
8519 (void) time (&clock);
8520 (void) sprintf (msgid, "<%d.%ld.%%d@@%s>\n", getpid (), clock,
8521 LocalName ());
8522 partno = 0;
8523 msgfmt = getcpy (msgid);
8524 }
8525
8526 (void) sprintf (msgid, msgfmt, ++partno);
8527 p -> c_id = getcpy (msgid);
8528
8529 d5635 14
8530 a5648 3
8531 vrsn = !ci -> ci_magic ? MULTI_MIXED
8532 : uprf (ci -> ci_magic, "alt") ? MULTI_ALTERNATE
8533 : MULTI_PARALLEL;
8534 d5650 1
8535 a5650 1
8536 (void) sprintf (buffer, "multipart/%s", SubMultiPart[vrsn - 1].kv_key);
8537 d5682 22
8538 @
8539
8540
8541 2.24
8542 log
8543 @document -file
8544 @
8545 text
8546 @d3 1
8547 a3 1
8548 static char ident[] = "@@(#)$Id: mhn.c,v 2.23 1993/08/25 17:26:22 jromine Exp jromine $";
8549 d6075 3
8550 a6077 1
8551 if (ebcdicsw && !ebcdicsafe[*cp & 0xff])
8552 @
8553
8554
8555 2.23
8556 log
8557 @off_t fixes for BSD44
8558 @
8559 text
8560 @d3 1
8561 a3 1
8562 static char ident[] = "@@(#)$Id: mhn.c,v 2.22 1993/08/20 15:52:01 jromine Exp jromine $";
8563 d45 4
8564 a48 1
8565 #define FORMSW 8
8566 d51 1
8567 a51 1
8568 #define HEADSW 9
8569 d53 1
8570 a53 1
8571 #define NHEADSW 10
8572 d56 1
8573 a56 1
8574 #define LISTSW 11
8575 d58 1
8576 a58 1
8577 #define NLISTSW 12
8578 d61 1
8579 a61 1
8580 #define PARTSW 13
8581 d64 1
8582 a64 1
8583 #define PAUSESW 14
8584 d66 1
8585 a66 1
8586 #define NPAUSESW 15
8587 d69 1
8588 a69 1
8589 #define SIZESW 16
8590 d71 1
8591 a71 1
8592 #define NSIZESW 17
8593 d74 1
8594 a74 1
8595 #define RFC934SW 18
8596 d76 1
8597 a76 1
8598 #define NRFC934SW 19
8599 d79 1
8600 a79 1
8601 #define SERIALSW 20
8602 d81 1
8603 a81 1
8604 #define NSERIALSW 21
8605 d84 1
8606 a84 1
8607 #define SHOWSW 22
8608 d86 1
8609 a86 1
8610 #define NSHOWSW 23
8611 d89 1
8612 a89 1
8613 #define STORESW 24
8614 d91 1
8615 a91 1
8616 #define NSTORESW 25
8617 d94 1
8618 a94 1
8619 #define TYPESW 26
8620 d97 1
8621 a97 1
8622 #define VERBSW 27
8623 d99 1
8624 a99 1
8625 #define NVERBSW 28
8626 d102 1
8627 a102 1
8628 #define HELPSW 29
8629 d105 1
8630 a105 1
8631 #define PROGSW 30
8632 d107 1
8633 a107 1
8634 #define NPROGSW 31
8635 d110 1
8636 a110 1
8637 #define LENSW 32
8638 d112 1
8639 a112 1
8640 #define WIDSW 33
8641 a113 3
8642
8643 #define FILESW 34 /* interface from show */
8644 "file file", -4,
8645 @
8646
8647
8648 2.22
8649 log
8650 @fixes from mtr:
8651 added "-cache policy" switch
8652 added "-[no]pause" switch
8653 remove application/oda content-type (change in MIME standard)
8654 add subject=/size= for external-parts (change in MIME standard)
8655 @
8656 text
8657 @d3 1
8658 a3 1
8659 static char ident[] = "@@(#)$Id: mhn.c,v 2.21 1992/12/15 00:20:22 jromine Exp jromine $";
8660 d186 1
8661 d189 1
8662 d3893 1
8663 a3893 1
8664 return st.st_size;
8665 d3896 1
8666 a3896 1
8667 return stat (ce -> ce_file, &st) != NOTOK ? st.st_size : 0L;
8668 d3905 1
8669 a3905 1
8670 size = fstat (fd, &st) != NOTOK ? st.st_size : 0L;
8671 d4038 1
8672 a4038 1
8673 (void) lseek (fd = fileno (ct -> c_fp), ct -> c_begin, 0);
8674 d4066 1
8675 a4066 1
8676 lseek (fd, 0L, 1) - (ep - cp),
8677 d4423 1
8678 a4423 1
8679 (void) lseek (fd = fileno (ct -> c_fp), ct -> c_begin, 0);
8680 d5366 1
8681 a5366 1
8682 ct -> c_end = st.st_size;
8683 d5450 1
8684 a5450 1
8685 p -> c_end = st.st_size;
8686 d5723 1
8687 a5723 1
8688 ct -> c_end = st.st_size;
8689 d6398 1
8690 a6398 1
8691 nlines += ((st.st_size - pos) + CPERLIN) / (CPERLIN + 1);
8692 @
8693
8694
8695 2.21
8696 log
8697 @endif sugar
8698 @
8699 text
8700 @d3 1
8701 a3 1
8702 static char ident[] = "@@(#)$Id: mhn.c,v 2.20 1992/12/14 17:10:25 jromine Exp jromine $";
8703 d24 1
8704 a24 1
8705 #define AUTOSW 0
8706 d26 1
8707 a26 1
8708 #define NAUTOSW 1
8709 d29 9
8710 a37 1
8711 #define DEBUGSW 2
8712 d40 1
8713 a40 1
8714 #define EBCDICSW 3
8715 d42 1
8716 a42 1
8717 #define NEBCDICSW 4
8718 d45 1
8719 a45 1
8720 #define FORMSW 5
8721 d48 1
8722 a48 1
8723 #define HEADSW 6
8724 d50 1
8725 a50 1
8726 #define NHEADSW 7
8727 d53 1
8728 a53 1
8729 #define LISTSW 8
8730 d55 1
8731 a55 1
8732 #define NLISTSW 9
8733 d58 1
8734 a58 1
8735 #define PARTSW 10
8736 d61 6
8737 a66 1
8738 #define SIZESW 11
8739 d68 1
8740 a68 1
8741 #define NSIZESW 12
8742 d71 1
8743 a71 1
8744 #define RFC934SW 13
8745 d73 1
8746 a73 1
8747 #define NRFC934SW 14
8748 d76 1
8749 a76 1
8750 #define SERIALSW 15
8751 d78 1
8752 a78 1
8753 #define NSERIALSW 16
8754 d81 1
8755 a81 1
8756 #define SHOWSW 17
8757 d83 1
8758 a83 1
8759 #define NSHOWSW 18
8760 d86 1
8761 a86 1
8762 #define STORESW 19
8763 d88 1
8764 a88 1
8765 #define NSTORESW 20
8766 d91 1
8767 a91 1
8768 #define TYPESW 21
8769 d94 1
8770 a94 1
8771 #define VERBSW 22
8772 d96 1
8773 a96 1
8774 #define NVERBSW 23
8775 d99 1
8776 a99 1
8777 #define HELPSW 24
8778 d102 1
8779 a102 1
8780 #define PROGSW 25
8781 d104 1
8782 a104 1
8783 #define NPROGSW 26
8784 d107 1
8785 a107 1
8786 #define LENSW 27
8787 d109 1
8788 a109 1
8789 #define WIDSW 28
8790 d112 1
8791 a112 1
8792 #define FILESW 29 /* interface from show */
8793 d115 1
8794 a115 1
8795 #define VIAMSW 30
8796 d117 1
8797 a117 1
8798 #define VIASSW 31
8799 d119 1
8800 a119 1
8801 #define VIAPSW 32
8802 d121 1
8803 a121 1
8804 #define VIADSW 33
8805 d123 1
8806 a123 1
8807 #define VIACSW 34
8808 d125 1
8809 a125 1
8810 #define VIAZSW 35
8811 d127 1
8812 a127 1
8813 #define VIAFSW 36
8814 d138 11
8815 d150 2
8816 d160 1
8817 d249 1
8818 a249 1
8819 char *c_storeproc; /* default, if not in profile */
8820 d283 2
8821 d312 1
8822 d314 1
8823 d393 21
8824 d457 7
8825 d589 1
8826 a589 1
8827 if (f2 || f3 || f4 || f5 || f6)
8828 d608 1
8829 a608 1
8830 cache = m_find (buf);
8831 d879 1
8832 a879 1
8833 xpid = child_id;
8834 d958 2
8835 a959 1
8836 static int InitApplication (), InitMessage (), InitMultiPart (), InitText ();
8837 d964 2
8838 a965 2
8839 "audio", CT_AUDIO, NULL,
8840 "image", CT_IMAGE, NULL,
8841 d969 1
8842 a969 1
8843 "video", CT_VIDEO, NULL,
8844 d1015 4
8845 a1018 1
8846 register char *cp;
8847 a1026 2
8848 char *dp = trimcpy (cp);
8849
8850 d1029 1
8851 a1029 1
8852 ct -> c_file, VRSN_FIELD, dp);
8853 a1035 1
8854 #ifdef whocares
8855 d1038 12
8856 d1052 6
8857 a1057 6
8858 c = *dp, *dp = NULL;
8859 if (!uleq (cp, VRSN_VALUE)) {
8860 if (!isspace (c))
8861 *dp = c;
8862 advise (NULLCP,
8863 "message %s has unsupported value for %s: field (%s)",
8864 a1058 4
8865 goto out;
8866 }
8867 *dp = c;
8868 #endif
8869 d1154 53
8870 d1301 1
8871 a1301 1
8872 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8873 d1323 1
8874 a1323 1
8875 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8876 d1336 1
8877 a1336 1
8878 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8879 d1360 1
8880 a1360 1
8881 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8882 d1379 1
8883 a1379 1
8884 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8885 d1449 1
8886 a1449 1
8887 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8888 d1489 1
8889 a1489 1
8890 static int get_comment (ct, ap)
8891 d1492 1
8892 d1511 1
8893 a1511 1
8894 ct -> c_file, TYPE_FIELD);
8895 d1538 7
8896 a1544 3
8897 if (dp = ci -> ci_comment) {
8898 ci -> ci_comment = concat (dp, " ", buffer, NULLCP);
8899 free (dp);
8900 a1545 2
8901 else
8902 ci -> ci_comment = add (buffer, NULLCP);
8903 d1628 1
8904 a1628 1
8905 fprintf (stderr, " %s:%s", VRSN_FIELD, ct -> c_vrsn);
8906 d1903 1
8907 a1903 1
8908 xpause = 1;
8909 d1950 3
8910 a1952 1
8911 if (xtty && xpid) {
8912 d2233 4
8913 d2367 1
8914 d2412 3
8915 a2414 1
8916 if (uprf (name, XXX_FIELD_PRF) || uleq (name, "Message-ID")) {
8917 d2447 40
8918 d2603 23
8919 d2688 1
8920 a2688 1
8921 if (uleq (*ap, "charset")) {
8922 a2708 2
8923
8924 break;
8925 d2710 3
8926 d2714 8
8927 d3338 1
8928 d3421 4
8929 d3458 2
8930 d3742 1
8931 a3742 2
8932 #define APPLICATION_ODA 0x02
8933 #define APPLICATION_POSTSCRIPT 0x03
8934 a3764 1
8935 "oda", APPLICATION_ODA,
8936 d3783 3
8937 a3785 4
8938 if (autosw && !ct -> c_storeproc)
8939 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
8940 if (uleq (*ap, "name")) {
8941 register char *cp;
8942 d3787 7
8943 a3793 8
8944 if (*(cp = *ep) != '/'
8945 && *cp != '.'
8946 && *cp != '|'
8947 && *cp != '!'
8948 && !index (cp, '%'))
8949 ct -> c_storeproc = add (cp, NULLCP);
8950 break;
8951 }
8952 d3809 1
8953 a3809 1
8954 if (uleq (*ap, "conversions")
8955 d3836 3
8956 d3987 1
8957 d4001 1
8958 d4033 3
8959 d4075 2
8960 d4079 3
8961 a4081 1
8962 if (skip < 1)
8963 d4083 3
8964 d4118 13
8965 d4193 1
8966 d4201 1
8967 d4233 3
8968 d4269 2
8969 d4276 3
8970 d4315 6
8971 d4348 13
8972 d4474 1
8973 a4474 1
8974 static int openExternal (ct, ce, file, fd)
8975 d4476 1
8976 d4501 2
8977 d4507 1
8978 a4507 1
8979 if (cache && (id = ct -> c_id)) {
8980 d4515 1
8981 d4518 3
8982 d4522 9
8983 a4530 4
8984 (void) sprintf (buffer,
8985 "Use cached copy %s of size %lu octets (content %s)? ",
8986 id, (unsigned long) st.st_size,
8987 ct -> c_partno);
8988 d4532 1
8989 d4557 1
8990 a4557 1
8991 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
8992 d4581 1
8993 a4581 1
8994 && (id = e -> eb_parent -> c_id)
8995 d4588 1
8996 a4588 1
8997 if (getanswer (buffer)) {
8998 d4598 1
8999 d4603 3
9000 a4605 2
9001 while (fgets (buffer, sizeof buffer - 1, gp))
9002 (void) fputs (buffer, fp);
9003 d4654 1
9004 a4654 1
9005 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
9006 d4692 1
9007 a4692 1
9008 && (id = e -> eb_parent -> c_id)
9009 d4696 1
9010 a4696 1
9011 if (getanswer (buffer)) {
9012 d4832 1
9013 a4832 1
9014 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
9015 d4849 3
9016 a4851 1
9017 e -> eb_server, "\n\n", e -> eb_body, "\n? ", NULLCP);
9018 d4862 10
9019 a4871 7
9020 if (cache
9021 && (id = e -> eb_parent -> c_id)
9022 && (!e -> eb_permission
9023 || !uleq (e -> eb_permission, "read-write"))) {
9024 (void) sprintf (buffer, "cache content as %s/%s", cache,
9025 id = trimcpy (id));
9026 free (id);
9027 d4873 4
9028 a4876 4
9029 vec[vecp++] = buffer;
9030 }
9031 else
9032 vec[vecp++] = "mail-server request";
9033 d5344 1
9034 a5344 1
9035 ct -> c_id = getcpy (msgid);
9036 d5511 35
9037 d5745 1
9038 a5745 1
9039 linelen = 0;
9040 d5758 1
9041 a5758 1
9042 for (cp = buffer; *cp; cp++)
9043 d5763 5
9044 d5779 5
9045 d5840 2
9046 d5955 1
9047 a5955 2
9048 if (ct -> c_subtype != TEXT_PLAIN
9049 || (ct -> c_ctparams
9050 d5957 1
9051 a5957 1
9052 != CHARSET_USASCII)) {
9053 d5959 2
9054 d5966 4
9055 d5996 2
9056 d6072 2
9057 a6073 3
9058 case '@@':
9059 case '`':
9060 if (ebcdicsw)
9061 a6074 1
9062 one_print: ;
9063 a6078 12
9064 default:
9065 if (('!' <= *cp && *cp <= '$')
9066 || ('[' <= *cp && *cp <= '^')
9067 || ('{' <= *cp && *cp <= '~')) {
9068 if (ebcdicsw)
9069 goto three_print;
9070 goto one_print;
9071 }
9072
9073 if ('%' <= *cp && *cp <= 'z')
9074 goto one_print;
9075 /* else fall... */
9076 d6104 1
9077 a6104 1
9078 static char nib2b64[0x40f] =
9079 d6175 160
9080 d6353 1
9081 d6377 1
9082 d6400 1
9083 a6400 1
9084 status = via_post (tmpfil);
9085 d6406 1
9086 a6406 1
9087
9088 d6415 1
9089 a6415 5
9090 (void) fseek (fp, 0L, 0);
9091 if (!fgets (buffer, sizeof buffer, fp)
9092 || !fgets (buffer, sizeof buffer, fp)
9093 || (subjsw && !fgets (buffer, sizeof buffer, fp)))
9094 adios (NULLCP, "premature eof");
9095 d6448 1
9096 d6455 6
9097 a6460 1
9098 if (slowsw > 0 && 1 < partno && partno < nparts) {
9099 d6463 1
9100 a6463 1
9101 slowsw, partno);
9102 a6468 5
9103
9104 status = via_post (tmpdrf);
9105 (void) unlink (tmpdrf);
9106 if (status)
9107 break;
9108 d6480 1
9109 a6480 1
9110 static int via_post (file)
9111 d6482 1
9112 d6495 2
9113 a6496 1
9114 (void) execlp (postproc, r1bindex (postproc, '/'), file, NULLCP);
9115 @
9116
9117
9118 2.20
9119 log
9120 @WAITINT ifdefs
9121 @
9122 text
9123 @d3 2
9124 a4 2
9125 static char ident[] = "@@(#)$Id: mhn.c,v 2.19 1992/12/10 22:27:15 jromine Exp jromine $";
9126 #endif lint
9127 @
9128
9129
9130 2.19
9131 log
9132 @fix from mtr
9133 @
9134 text
9135 @d3 1
9136 a3 1
9137 static char ident[] = "@@(#)$Id: mhn.c,v 2.18 1992/12/09 19:23:22 jromine Exp jromine $";
9138 d761 3
9139 a763 1
9140 #ifndef BSD42
9141 a764 2
9142 #else
9143 union wait status;
9144 d834 3
9145 a836 1
9146 #ifndef BSD42
9147 a837 2
9148 #else
9149 (void) pidcheck (status.w_status);
9150 d2641 3
9151 a2643 1
9152 #ifndef BSD42
9153 a2644 2
9154 #else
9155 union wait status;
9156 d2659 3
9157 a2661 1
9158 #ifndef BSD42
9159 a2662 2
9160 #else
9161 (void) pidcheck (status.w_status);
9162 @
9163
9164
9165 2.18
9166 log
9167 @fix from mtr
9168 @
9169 text
9170 @d3 1
9171 a3 1
9172 static char ident[] = "@@(#)$Id: mhn.c,v 2.17 1992/12/03 21:58:18 jromine Exp jromine $";
9173 d1086 1
9174 d1091 1
9175 @
9176
9177
9178 2.17
9179 log
9180 @ignore return value of vsprintf()
9181 @
9182 text
9183 @d3 1
9184 a3 1
9185 static char ident[] = "@@(#)$Id: mhn.c,v 2.16 1992/12/02 18:50:39 jromine Exp jromine $";
9186 d4481 1
9187 @
9188
9189
9190 2.16
9191 log
9192 @#ifdef bug
9193 @
9194 text
9195 @d3 1
9196 a3 1
9197 static char ident[] = "@@(#)$Id: mhn.c,v 2.15 1992/11/24 18:21:54 jromine Exp jromine $";
9198 d1599 2
9199 a1600 1
9200 bp += vsprintf (bp, fmt, arglist);
9201 @
9202
9203
9204 2.15
9205 log
9206 @add/fixup decl
9207 @
9208 text
9209 @d3 1
9210 a3 1
9211 static char ident[] = "@@(#)$Id: mhn.c,v 2.14 1992/11/24 17:18:52 jromine Exp jromine $";
9212 d1581 1
9213 a1581 1
9214 register CI ci = &ct -> c_ctinfo;
9215 d1604 1
9216 @
9217
9218
9219 2.14
9220 log
9221 @fix from mtr
9222 @
9223 text
9224 @d3 1
9225 a3 1
9226 static char ident[] = "@@(#)$Id: mhn.c,v 2.13 1992/11/24 17:18:04 jromine Exp jromine $";
9227 d273 1
9228 d282 4
9229 d3136 3
9230 a3138 3
9231 extern int openFile ();
9232 extern int openFTP ();
9233 extern int openMail ();
9234 @
9235
9236
9237 2.13
9238 log
9239 @messed up ifdefs for VSPRINTF & __STDC__
9240 @
9241 text
9242 @d3 1
9243 a3 1
9244 static char ident[] = "@@(#)$Id: mhn.c,v 2.12 1992/11/23 19:07:08 jromine Exp jromine $";
9245 d916 1
9246 a916 1
9247 "8bit", CE_8BIT, NULL,
9248 @
9249
9250
9251 2.12
9252 log
9253 @fix from mtr
9254 @
9255 text
9256 @d3 1
9257 a3 1
9258 static char ident[] = "@@(#)$Id: mhn.c,v 2.11 1992/11/23 19:05:18 jromine Exp jromine $";
9259 d275 1
9260 a275 1
9261 #ifdef __STDC__
9262 d1545 1
9263 a1548 1
9264 #ifdef VSPRINTF
9265 d1551 2
9266 a1552 1
9267 #else
9268 a1563 1
9269 #endif
9270 @
9271
9272
9273 2.11
9274 log
9275 @fix from mtr
9276 @
9277 text
9278 @d3 1
9279 a3 1
9280 static char ident[] = "@@(#)$Id: mhn.c,v 2.10 1992/11/23 19:04:27 jromine Exp jromine $";
9281 d2861 2
9282 a2864 3
9283 if (p -> c_end < p -> c_begin) {
9284 p -> c_begin = p -> c_end;
9285 }
9286 @
9287
9288
9289 2.10
9290 log
9291 @fix '-moreproc' -- from mtr
9292 @
9293 text
9294 @d3 1
9295 a3 1
9296 static char ident[] = "@@(#)$Id: mhn.c,v 2.9 1992/11/11 17:57:04 jromine Exp jromine $";
9297 d4300 2
9298 a4301 1
9299 (void) sprintf (buffer, "Make cached, publically-accessible copy? ");
9300 @
9301
9302
9303 2.9
9304 log
9305 @minor fix from mtr
9306 @
9307 text
9308 @d3 1
9309 a3 1
9310 static char ident[] = "@@(#)$Id: mhn.c,v 2.8 1992/11/09 17:46:01 jromine Exp jromine $";
9311 d2477 2
9312 a2478 1
9313 moreproc && *moreproc ? moreproc : "more");
9314 @
9315
9316
9317 2.8
9318 log
9319 @fixup varargs include
9320 @
9321 text
9322 @d3 1
9323 a3 1
9324 static char ident[] = "@@(#)$Id: mhn.c,v 2.7 1992/11/09 17:45:19 jromine Exp jromine $";
9325 d550 1
9326 a550 1
9327 : m_maildir (invo_name);
9328 @
9329
9330
9331 2.7
9332 log
9333 @charset changes via MTR
9334 @
9335 text
9336 @d3 1
9337 a3 1
9338 static char ident[] = "@@(#)$Id: mhn.c,v 2.6 1992/11/06 03:24:40 jromine Exp jromine $";
9339 d1538 1
9340 d1540 3
9341 @
9342
9343
9344 2.6
9345 log
9346 @AUX fixups - varargs
9347 @
9348 text
9349 @d3 1
9350 a3 1
9351 static char ident[] = "@@(#)$Id: mhn.c,v 2.5 1992/11/04 00:47:59 jromine Exp jromine $";
9352 d3272 1
9353 d3281 1
9354 a3281 1
9355 (*p -> c_ctstorefnx) (p, NULLCP);
9356 d3284 1
9357 a3284 1
9358 return OK;
9359 d5463 5
9360 a5467 2
9361 if (charset == -1)
9362 charset = CHARSET_USASCII;
9363 d5476 15
9364 a5490 6
9365 cp = index (*ap++ =
9366 add ((t -> tx_charset = charset)
9367 == CHARSET_USASCII
9368 ? "charset=us-ascii"
9369 : "charset=x-unknown", NULLCP),
9370 '=');
9371 @
9372
9373
9374 2.5
9375 log
9376 @LOCALE
9377 TYPESIG
9378 isupper with isalpha
9379 @
9380 text
9381 @d3 1
9382 a3 1
9383 static char ident[] = "@@(#)$Id: mhn.c,v 2.4 1992/11/02 17:01:08 jromine Exp jromine $";
9384 d275 1
9385 a275 1
9386 #if defined(VSPRINTF) && !defined(hpux)
9387 d1541 1
9388 a1541 1
9389 #if defined(VSPRINTF) && !defined(hpux)
9390 d1544 4
9391 d1560 1
9392 d1565 4
9393 d1582 1
9394 d1584 6
9395 @
9396
9397
9398 2.4
9399 log
9400 @fixes from mtr
9401 @
9402 text
9403 @d3 1
9404 a3 1
9405 static char ident[] = "@@(#)$Id: mhn.c,v 2.3 1992/10/26 16:58:47 jromine Exp jromine $";
9406 d17 3
9407 d285 1
9408 a285 1
9409 static int pipeser ();
9410 d319 3
9411 d866 1
9412 a866 1
9413 static int pipeser (i)
9414 d1189 1
9415 a1189 1
9416 if (isupper (*dp))
9417 d1225 1
9418 a1225 1
9419 if (isupper (*dp))
9420 d1262 1
9421 a1262 1
9422 if (isupper (*dp))
9423 d1636 1
9424 a1636 1
9425 static int intrser (i)
9426 @
9427
9428
9429 2.3
9430 log
9431 @add single quotes areound %f
9432 @
9433 text
9434 @d3 1
9435 a3 1
9436 static char ident[] = "@@(#)$Id: mhn.c,v 2.2 1992/10/20 20:30:08 jromine Exp jromine $";
9437 d272 1
9438 a272 1
9439 #ifdef VSPRINTF
9440 d1535 1
9441 a1535 1
9442 #ifdef VSPRINTF
9443 d2661 1
9444 d2665 1
9445 d2669 6
9446 a2674 2
9447 if (part_ok (p) && type_ok (p) && p -> c_ctstorefnx)
9448 (void) (*p -> c_ctstorefnx) (p, NULLCP);
9449 d2677 1
9450 a2677 1
9451 return OK;
9452 a3105 1
9453 #ifdef FTP
9454 a3106 1
9455 #endif
9456 d3112 4
9457 a3115 6
9458 "local-file", 0, openFile,
9459 "afs", 1, openFile,
9460 #ifdef FTP
9461 "ftp", 0, openFTP,
9462 "anon-ftp", 1, openFTP,
9463 #endif
9464 d3412 6
9465 a3417 1
9466 size = ct -> c_end - p -> c_begin;
9467 d3434 1
9468 a4312 1
9469 #ifdef FTP
9470 d4319 2
9471 a4320 1
9472 char *id,
9473 d4330 7
9474 d4401 49
9475 a4449 6
9476 if (ftp_get (e -> eb_site, user, pass, e -> eb_dir, e -> eb_name,
9477 ce -> ce_file,
9478 e -> eb_mode && uleq (e -> eb_mode, "ascii"), 0)
9479 == NOTOK) {
9480 username = password = NULL;
9481 return NOTOK;
9482 d4451 8
9483 a4494 1
9484 #endif
9485 d4954 6
9486 @
9487
9488
9489 2.2
9490 log
9491 @MIME upgrade 10
9492 @
9493 text
9494 @d3 1
9495 a3 1
9496 static char ident[] = "@@(#)$Id: mhn.c,v 2.1 1992/10/20 16:26:29 jromine Exp jromine $";
9497 d2450 1
9498 a2450 1
9499 (void) sprintf (buffer, "%%p%s %%F",
9500 d3309 1
9501 a3309 1
9502 ct -> c_showproc = add ("%pshow -file %F", NULLCP);
9503 @
9504
9505
9506 2.1
9507 log
9508 @null fixes
9509 @
9510 text
9511 @d3 1
9512 a3 1
9513 static char ident[] = "@@(#)$Id: mhn.c,v 1.5 1992/02/18 17:36:22 jromine Exp $";
9514 d148 1
9515 d461 1
9516 a461 1
9517 if (!(cp = *argp++) || *cp == '-')
9518 d463 1
9519 a463 1
9520 file = path (cp, TFILE);
9521 d540 1
9522 a540 1
9523 cwd = getcpy (pwd ());
9524 d563 2
9525 d572 2
9526 a573 2
9527 if ((fp = fopen (file, "r")) == NULL)
9528 adios (file, "unable to read");
9529 d575 25
9530 d601 3
9531 d1262 2
9532 a1263 2
9533 "invalid parameter in message %s's %s: field\n%*.*s(%s)\n%*.*sstarting at %s",
9534 ct -> c_file, TYPE_FIELD, i, i, "", cp, i, i, "", dp);
9535 d2063 5
9536 a2067 1
9537 fprintf (stderr, " as file %s\n", ct -> c_storage);
9538 d3410 1
9539 a3413 1
9540 size = ct -> c_end - p -> c_begin;
9541 d4481 1
9542 a4481 1
9543 (void) sprintf (buffer, "mail-server request (cache as %s/%s)", cache,
9544 @
9545
9546
9547 2.0
9548 log
9549 @new version from /mtr - MIME/update9
9550 @
9551 text
9552 @d1217 1
9553 a1217 1
9554 if (*cp == NULL) {
9555 d2158 1
9556 a2158 1
9557 buffer[0] = NULL;
9558 d2169 1
9559 a2169 1
9560 buffer[0] = NULL;
9561 d3391 1
9562 a3391 1
9563 *bp = NULL;
9564 d4323 1
9565 a4323 1
9566 ce -> ce_unlink = *file == NULL, caching = 0, cachefile[0] = NULL;
9567 d4695 1
9568 a4695 1
9569 *cp = NULL, n -= (i - 2);
9570 @
9571
9572
9573 1.7
9574 log
9575 @NULL->0, AIX
9576 @
9577 text
9578 @d3 1
9579 a3 1
9580 static char ident[] = "@@(#)$Id: mhn.c,v 1.6 1992/03/03 17:13:54 jromine Exp jromine $";
9581 d9 1
9582 d111 2
9583 d141 3
9584 d147 1
9585 d151 1
9586 d217 1
9587 d280 1
9588 d282 1
9589 d301 1
9590 d491 4
9591 d509 2
9592 d514 1
9593 a514 1
9594 via_mail (f1, f2, f3, f4, f5, f6);
9595 d530 1
9596 a530 1
9597 if (fp = fopen (cp = libpath ("mhn_profile"), "r")) {
9598 d536 3
9599 d541 3
9600 a543 1
9601 dir = getcpy ((cp = m_find (buf)) ? cp : cwd);
9602 d653 1
9603 d656 12
9604 d675 1
9605 a683 10
9606 if (storesw || showsw)
9607 for (ctp = cts; ct = *ctp; ctp++)
9608 if (type_ok (ct) && (ct -> c_ctstorefnx || ct -> c_ctshowfnx)) {
9609 struct stat st;
9610
9611 if (!ct -> c_umask)
9612 ct -> c_umask = ~(stat (ct -> c_file, &st) != NOTOK
9613 ? (st.st_mode & 0777) : m_gmprot ());
9614 }
9615
9616 d703 1
9617 d718 1
9618 a718 1
9619 char *vec[7];
9620 d729 2
9621 a745 1
9622 (void) umask (ct -> c_umask);
9623 d750 1
9624 d761 2
9625 d791 6
9626 a796 1
9627 while (wait (&status) != NOTOK)
9628 d798 1
9629 a828 2
9630 /* ARGSUSED */
9631
9632 d832 9
9633 d913 1
9634 a913 3
9635 register char *cp,
9636 *dp;
9637 char c;
9638 a914 6
9639 if (ct -> c_vrsn) {
9640 advise (NULLCP, "message %s has multiple %s: fields",
9641 ct -> c_file, VRSN_FIELD);
9642 goto out;
9643 }
9644
9645 d921 11
9646 a956 6
9647 if (ct -> c_ctline) {
9648 advise (NULLCP, "message %s has multiple %s: fields",
9649 ct -> c_file, TYPE_FIELD);
9650 goto out;
9651 }
9652
9653 d963 11
9654 a991 6
9655 if (ct -> c_celine) {
9656 advise (NULLCP, "message %s has multiple %s: fields",
9657 ct -> c_file, ENCODING_FIELD);
9658 goto out;
9659 }
9660
9661 d998 10
9662 d1117 1
9663 d1146 2
9664 a1147 3
9665 advise (NULLCP, "invalid %s: field in message %s (empty type)",
9666 TYPE_FIELD,
9667 ct -> c_file);
9668 d1162 2
9669 a1163 10
9670 if (magic)
9671 goto magic_skip;
9672
9673 #ifdef notdef
9674 advise (NULLCP,
9675 "invalid %s: field in message %s (missing subtype for \"%s\")",
9676 TYPE_FIELD, ct -> c_file, ci -> ci_type);
9677 return NOTOK;
9678 #else
9679 ci -> ci_subtype = add ("", NULLCP);
9680 a1164 1
9681 #endif
9682 d1200 2
9683 a1201 1
9684 char *vp;
9685 d1217 7
9686 d1227 2
9687 d1231 2
9688 a1232 2
9689 "invalid parameter in message %s's %s: field (%s)",
9690 ct -> c_file, TYPE_FIELD, cp);
9691 d1236 5
9692 a1240 4
9693 vp = (*ap = add (cp, NULLCP)) + (dp - cp);
9694 *vp++ = '\0';
9695 ci -> ci_values[ap - ci -> ci_attrs] = vp;
9696 dp++;
9697 d1247 2
9698 a1248 2
9699 "invalid quoted-string in message %s's %s: field (parameter %s)",
9700 ct -> c_file, TYPE_FIELD, *ap);
9701 a1264 1
9702
9703 d1275 2
9704 a1276 2
9705 "invalid parameter in message %s's %s: field (parameter %s)",
9706 ct -> c_file, TYPE_FIELD, *ap);
9707 d1294 1
9708 a1294 2
9709 advise (NULLCP, "invalid description in message %s's %s: field",
9710 ct -> c_file, TYPE_FIELD);
9711 d1315 2
9712 a1316 2
9713 "extraneous information in message %s's %s: field (%s)",
9714 ct -> c_file, TYPE_FIELD, cp);
9715 d1474 4
9716 d1523 1
9717 d1556 3
9718 a1558 1
9719 (void) sprintf (bp, " (content %s/%s", ci -> ci_type, ci -> ci_subtype);
9720 d1594 19
9721 d1626 1
9722 a1626 1
9723 if ((cp = m_find (buffer)) == NULL) {
9724 d1628 1
9725 a1628 1
9726 if ((cp = m_find (buffer)) == NULL
9727 d1653 1
9728 d1659 2
9729 a1660 1
9730 buffer[BUFSIZ];
9731 d1673 2
9732 d1676 1
9733 a1676 1
9734 xlist = xstdin = xtty = 0;
9735 d1712 3
9736 d1739 6
9737 d1747 1
9738 a1747 1
9739 if (debugsw) {
9740 d1749 2
9741 a1750 1
9742 fprintf (stderr, "%s msg %s", cracked ? "store" : "show",
9743 d1754 4
9744 a1757 1
9745 fprintf (stderr, " using command %s\n", buffer);
9746 a1759 2
9747 (void) fflush (stdout);
9748
9749 d1761 1
9750 a1761 1
9751 (void) pidwait (xpid, NOTOK);
9752 d1765 2
9753 a1766 2
9754 if (xlist && ct -> c_ctlistfnx)
9755 (*ct -> c_ctlistfnx) (ct, -1);
9756 d1768 59
9757 d1829 1
9758 a1829 1
9759 vec[2] = buffer;
9760 d1832 2
9761 d1861 1
9762 a1861 1
9763 (void) pidXwait (child_id, NULLCP);
9764 d1889 7
9765 a1895 7
9766 (void) sprintf (buffer, "%s-store-%s/%s", invo_name, ci -> ci_type,
9767 ci -> ci_subtype);
9768 if ((cp = m_find (buffer)) == NULL) {
9769 (void) sprintf (buffer, "%s-store-%s", invo_name, ci -> ci_type);
9770 if ((cp = m_find (buffer)) == NULL
9771 && (cp = ct -> c_storeproc) == NULL)
9772 cp = ct -> c_type == CT_MESSAGE ? "+" : "%m%P.%s";
9773 d1897 1
9774 d1953 3
9775 a1955 2
9776 (void) sprintf (bp = buffer, "%s/", dir[1] ? dir : "");
9777 bp += strlen (bp);
9778 d2020 1
9779 a2020 1
9780 return show_content_aux (ct, 1, 0, buffer + 1, dir);
9781 d2024 1
9782 d2026 1
9783 d2033 1
9784 d2035 1
9785 d2047 2
9786 a2048 1
9787 file = appending ? NULLCP : ct -> c_storage;
9788 d2056 15
9789 a2070 5
9790 if ((fp = fopen (ct -> c_storage, appending ? "a" : "w")) == NULL) {
9791 advise (ct -> c_storage, "unable to fopen for %s",
9792 appending ? "appending" : "writing");
9793 (void) (*ct -> c_ceclosefnx) (ct);
9794 return NOTOK;
9795 d2072 7
9796 d2117 13
9797 a2129 4
9798 if ((fp = fopen (ct -> c_storage, appending ? "a" : "w")) == NULL) {
9799 advise (ct -> c_storage, "unable to fopen for %s",
9800 appending ? "appending" : "writing");
9801 return NOTOK;
9802 d2131 6
9803 d2138 1
9804 a2138 1
9805 if (append && !*append)
9806 d2140 4
9807 d2152 24
9808 d2217 1
9809 a2217 1
9810 fprintf (out, "%s: %s", name, buf);
9811 d2287 2
9812 d2364 1
9813 a2365 1
9814
9815 d2395 1
9816 d2409 2
9817 d2415 1
9818 a2415 1
9819 (void) sprintf (buffer, "%s %%F",
9820 d2422 8
9821 d2432 2
9822 a2433 8
9823 register struct text *t;
9824
9825 if ((t = (struct text *) calloc (1, sizeof *t)) == NULL)
9826 adios (NULLCP, "out of memory");
9827 ct -> c_ctparams = (caddr_t) t;
9828 ct -> c_ctfreefnx = free_text;
9829
9830 t -> tx_charset = kv -> kv_value;
9831 d2436 7
9832 d2509 1
9833 d2521 2
9834 a2522 1
9835 nowserial = 1;
9836 d2587 7
9837 a2593 1
9838 while (kids > 0 && (pid = wait (&status)) != NOTOK)
9839 d2605 1
9840 d2704 1
9841 a2704 1
9842 ci -> ci_type, ci -> ci_subtype);
9843 d3042 1
9844 d3044 1
9845 a3044 1
9846 int eb_didone;
9847 d3050 2
9848 d3055 6
9849 d3064 1
9850 d3068 1
9851 d3073 2
9852 d3079 1
9853 d3085 1
9854 a3085 1
9855 static int params_external (ct)
9856 d3087 1
9857 d3119 4
9858 d3135 12
9859 d3149 1
9860 a3149 1
9861 if (!e -> eb_access || !e -> eb_name || !e -> eb_site) {
9862 d3168 2
9863 a3169 1
9864 printf ("\t retrieve %s ", e -> eb_name);
9865 d3171 6
9866 a3176 3
9867 printf ("in directory %s ", e -> eb_dir);
9868 printf ("\n\t\t from %s\n\t\tusing %s", e -> eb_site,
9869 e -> eb_access);
9870 d3179 2
9871 a3201 14
9872 if (!e -> eb_didone) {
9873 char *file;
9874
9875 e -> eb_didone = 1;
9876
9877 file = NULL;
9878 if ((*p -> c_ceopenfnx) (p, &file) == NOTOK)
9879 return NOTOK;
9880 (void) (*p -> c_ceclosefnx) (p);
9881
9882 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK)
9883 return NOTOK;
9884 }
9885
9886 a3218 15
9887 if (!e -> eb_didone) {
9888 char *file;
9889
9890 e -> eb_didone = 1;
9891
9892 file = NULL; /* would be great to have this filled in, but it's
9893 a chicken-and-egg situation... */
9894 if ((*p -> c_ceopenfnx) (p, &file) == NOTOK)
9895 return NOTOK;
9896 (void) (*p -> c_ceclosefnx) (p);
9897
9898 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK)
9899 return NOTOK;
9900 }
9901
9902 d3237 2
9903 d3262 1
9904 a3262 1
9905 ci -> ci_type, ci -> ci_subtype);
9906 d3266 2
9907 d3274 1
9908 a3274 1
9909 ct -> c_showproc = add ("show -file %F", NULLCP);
9910 d3340 1
9911 a3364 2
9912 p -> c_fp = NULL;
9913 p -> c_end = p -> c_begin;
9914 d3366 1
9915 d3369 14
9916 d3384 12
9917 d3400 1
9918 a3400 1
9919 if (params_external (ct) == NOTOK)
9920 d3405 15
9921 d3431 1
9922 a3431 1
9923 e -> eb_didone = 1;
9924 d3483 2
9925 d3493 15
9926 a3510 2
9927 register char **ap,
9928 **ep;
9929 d3522 2
9930 a3523 1
9931 if (uleq (*ap, "conversions") && uleq (*ep, "compress")) {
9932 a3526 8
9933
9934 if (autosw && !ct -> c_storeproc && uleq (*ap, "file")) {
9935 register char *cp;
9936
9937 if (*(cp = *ep) != '/' && *cp != '+' && *cp != '@@')
9938 ct -> c_storeproc = add (cp, NULLCP);
9939 break;
9940 }
9941 a3700 1
9942 unsigned char *b = (unsigned char *) &bits;
9943 d3703 5
9944 a3707 1
9945 unsigned char value;
9946 d3725 1
9947 a3725 3
9948 add (*file ? *file
9949 : m_scratch ("",
9950 m_maildir (invo_name)),
9951 d3763 2
9952 a3764 1
9953 if ((*cp & 0x80)
9954 d3767 4
9955 a3770 2
9956 fprintf (stderr, "*cp=0x%x pos=%ld\n", *cp,
9957 lseek (fd, 0L, 1) - (ep - cp));
9958 d3772 1
9959 a3772 3
9960 "invalid BASE64 encoding (char 0x%x at position %ld) -- continuing",
9961 *cp,
9962 lseek (fd, 0L, 1) - (ep - cp));
9963 d3779 1
9964 a3779 2
9965 #if defined(i386) || defined(vax)
9966 (void) putc (b[2], ce -> ce_fp);
9967 d3781 1
9968 a3781 1
9969 (void) putc (b[1], ce -> ce_fp);
9970 d3783 1
9971 a3783 1
9972 (void) putc (b[0], ce -> ce_fp);
9973 d3785 5
9974 a3789 6
9975 #else
9976 (void) putc (b[1], ce -> ce_fp);
9977 if (skip < 2) {
9978 (void) putc (b[2], ce -> ce_fp);
9979 if (skip < 1)
9980 (void) putc (b[3], ce -> ce_fp);
9981 a3790 2
9982 #endif
9983
9984 d3796 2
9985 a3797 1
9986 skip++;
9987 a3798 14
9988
9989 #ifdef notanymore
9990 case ',':
9991 if (bitno != 18) {
9992 if (debugsw)
9993 fprintf (stderr,
9994 "unaligned ',' (bitno %d)\n",
9995 bitno);
9996
9997 goto invalid_encoding;
9998 }
9999 (void) putc ('\n', ce -> ce_fp);
10000 break;
10001 #endif
10002 a3803 3
10003 #ifdef notanymore
10004 invalid_encoding: ;
10005 #endif
10006 d3808 1
10007 d3834 17
10008 d3900 1
10009 a3900 3
10010 add (*file ? *file
10011 : m_scratch ("",
10012 m_maildir (invo_name)),
10013 d3964 4
10014 d3990 4
10015 d4061 1
10016 a4061 3
10017 add (*file ? *file
10018 : m_scratch ("",
10019 m_maildir (invo_name)),
10020 d4094 4
10021 d4128 140
10022 d4275 7
10023 a4281 2
10024 char *user,
10025 *pass;
10026 d4285 1
10027 a4285 1
10028 static char *password = NULL;
10029 d4287 2
10030 a4288 5
10031 if (ce -> ce_fp)
10032 goto ready_to_go;
10033 if (ce -> ce_file) {
10034 if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
10035 content_error (ce -> ce_file, ct, "unable to fopen for reading");
10036 a4289 1
10037 }
10038 d4291 5
10039 a4295 2
10040 *file = ce -> ce_file;
10041 return fileno (ce -> ce_fp);
10042 d4298 20
10043 a4317 2
10044 if (e -> eb_flags)
10045 user = "anonymous", pass = "guest";
10046 a4318 5
10047 if (xpid) {
10048 (void) pidwait (xpid, NOTOK);
10049 xpid = 0;
10050 }
10051
10052 d4323 17
10053 a4339 1
10054 ce -> ce_unlink = *file == NULL;
10055 d4342 2
10056 a4343 2
10057 : m_scratch ("",
10058 m_maildir (invo_name)),
10059 a4350 3
10060 if (verbosw)
10061 printf ("Retrieving %s using %sFTP from site %s\n",
10062 e -> eb_name, e -> eb_flags ? "Anonymous " : "", e -> eb_site);
10063 d4359 31
10064 a4389 1
10065 ready_to_go: ;
10066 d4396 100
10067 d4523 1
10068 d4550 1
10069 a4550 1
10070 fprintf (out, "%s: %s", name, buf);
10071 d4595 1
10072 a4595 1
10073 while (fgets (buf, sizeof buf - 1, in)) {
10074 d4631 1
10075 a4631 1
10076 if (*++cp == '\n')
10077 d4676 27
10078 d4732 5
10079 a4736 2
10080 if (buf[0] != '#' || buf[1] == '#') {
10081 int headers;
10082 d4745 9
10083 d4766 1
10084 a4766 1
10085 if (!fgets (buffer, sizeof buffer - 1, in))
10086 d4789 1
10087 d4792 2
10088 a4793 1
10089 if ((cp = fgets (buffer, sizeof buffer - 1, in)) == NULL)
10090 d4810 1
10091 a4810 1
10092 if (get_ctinfo ("text/plain", ct, 0) == NOTOK)
10093 d4812 19
10094 a4830 3
10095 ct -> c_type = CT_TEXT;
10096 ct -> c_ctinitfnx = InitText;
10097 (void) (*ct -> c_ctinitfnx) (ct);
10098 d4832 1
10099 a4832 1
10100 (void) fseek (in, (long) (-strlen (cp)), 1);
10101 d4866 1
10102 d4869 3
10103 d4897 1
10104 d4903 1
10105 a4903 1
10106 if (params_external (ct) == NOTOK)
10107 d4906 11
10108 d4943 1
10109 a4943 1
10110 if ((cp = m_find (buffer)) == NULL) {
10111 d4945 1
10112 a4945 1
10113 if ((cp = m_find (buffer)) == NULL) {
10114 d5059 1
10115 a5059 1
10116 while (fgets (buffer, sizeof buffer - 1, in)) {
10117 a5081 20
10118 static char asciiP[0x80] = {
10119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10120 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
10121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10123 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10124 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10125 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10126 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10127 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10128 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10129 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10130 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10131 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10132 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10133 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10134 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00
10135 };
10136
10137
10138 d5144 1
10139 a5144 1
10140 ct -> c_end += 1 /* notdef 2 */;
10141 d5248 1
10142 a5248 1
10143 if (pidXwait (child_id, NULLCP) & 0377)
10144 d5259 3
10145 a5261 1
10146 if (ct -> c_type != CT_TEXT)
10147 d5269 1
10148 d5278 14
10149 a5291 1
10150 charset = ct -> c_type != CT_TEXT || ct -> c_ctparams ? 0 : -1;
10151 d5295 6
10152 a5300 4
10153 if (!isascii (*cp) || !asciiP[*cp & 0x7f]) {
10154 charset = CHARSET_UNKNOWN;
10155 break;
10156 }
10157 d5304 3
10158 d5320 1
10159 a5320 1
10160 if (charset != -1)
10161 d5325 4
10162 d5348 1
10163 a5348 1
10164 : "charset=iso8859-1", NULLCP),
10165 d5371 1
10166 a5388 4
10167
10168 if (!ci -> ci_comment && ct -> c_rfc934)
10169 ci -> ci_comment = add ("RFC 934 compatible encapsulation",
10170 NULLCP);
10171 d5398 3
10172 d5402 3
10173 d5480 1
10174 d5487 2
10175 d5495 3
10176 a5497 1
10177 if (ct -> c_subtype == APPLICATION_POSTSCRIPT)
10178 d5499 1
10179 d5558 7
10180 a5564 2
10181 n = 0;
10182 for (cp = buffer; *cp; cp++) {
10183 a5575 1
10184
10185 a5577 3
10186 case '[':
10187 case ']':
10188 case '^':
10189 d5588 1
10190 d5659 5
10191 a5667 4
10192 #if defined(i386) || defined(vax)
10193 for (bp = outbuf; bp < outbuf + sizeof outbuf; bits >>= 6)
10194 *bp++ = nib2b64[bits & 0x3f];
10195 #else
10196 a5669 1
10197 #endif
10198 d5699 1
10199 a5699 1
10200 static int via_mail (mailsw, subjsw, parmsw, descsw, cmntsw, slowsw)
10201 d5704 2
10202 a5705 1
10203 *cmntsw;
10204 d5726 1
10205 d5728 7
10206 a5734 2
10207 fprintf (fp, "Subject: %s\n", subjsw);
10208 fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
10209 d5739 1
10210 a5739 1
10211 fprintf (fp, "\n\t(%s)", cmntsw);
10212 d5741 2
10213 a5742 3
10214 fprintf (fp, "\n%s: %s", DESCR_FIELD, descsw);
10215 fprintf (fp, "\n%s: %s\n\n", ENCODING_FIELD, "base64");
10216 nlines = 4 + (subjsw ? 1 : 0) + (descsw ? 1 : 0) + (cmntsw ? 1 : 0);
10217 d5797 3
10218 d5881 17
10219 @
10220
10221
10222 1.6
10223 log
10224 @fixes from mtr
10225 @
10226 text
10227 @d3 1
10228 a3 1
10229 static char ident[] = "@@(#)$Id: mhn.c,v 1.5 1992/02/18 17:36:22 jromine Exp jromine $";
10230 d111 1
10231 a111 1
10232 NULL, NULL
10233 d166 1
10234 d182 2
10235 a183 1
10236 int get_ctinfo ();
10237 d258 3
10238 a260 3
10239 CT get_content ();
10240 int list_content (), show_content (), store_content ();
10241 void free_content (), content_error (), flush_errors ();
10242 d262 6
10243 d812 1
10244 a812 1
10245 int InitApplication (), InitMessage (), InitMultiPart (), InitText ();
10246 d829 1
10247 a829 1
10248 int InitBase64 (), InitQuoted (), Init7Bit ();
10249 d956 1
10250 a956 1
10251 c = *dp, *dp = NULL;
10252 d1074 1
10253 a1074 1
10254 *++dp = NULL;
10255 d1083 1
10256 a1083 1
10257 c = *dp, *dp = NULL;
10258 d1128 1
10259 a1128 1
10260 c = *dp, *dp = NULL;
10261 d1179 1
10262 a1179 1
10263 *vp++ = NULL;
10264 d1185 1
10265 a1185 1
10266 case NULL:
10267 d1194 1
10268 a1194 1
10269 if ((c = *cp++) == NULL)
10270 d1203 1
10271 a1203 1
10272 *dp = NULL;
10273 d1213 1
10274 a1213 1
10275 *dp = NULL;
10276 d1242 1
10277 a1242 1
10278 c = *dp, *dp = NULL;
10279 d1285 1
10280 a1285 1
10281 case NULL:
10282 d1293 1
10283 a1293 1
10284 if ((c = *cp++) == NULL)
10285 d1313 1
10286 a1313 1
10287 *bp = NULL;
10288 d1370 1
10289 a1370 1
10290 case NULL:
10291 d1439 7
10292 a1446 1
10293
10294 d1457 1
10295 d1459 3
10296 d1473 4
10297 d1479 1
10298 d1509 1
10299 a1509 1
10300 *bp = NULL;
10301 d1530 2
10302 d1594 1
10303 a1594 1
10304 buffer[0] = NULL;
10305 d1639 1
10306 a1639 1
10307 *bp = NULL;
10308 d1647 1
10309 a1647 1
10310 *bp = NULL;
10311 d1789 1
10312 a1789 1
10313 buffer[0] = NULL;
10314 d1803 1
10315 a1803 1
10316 *bp = NULL;
10317 d1848 1
10318 a1848 1
10319 *bp = NULL;
10320 d1856 1
10321 a1856 1
10322 *bp = NULL;
10323 d1948 1
10324 a1948 1
10325 buffer[diff] = NULL;
10326 d2494 1
10327 a2494 1
10328 *++dp = NULL;
10329 d3544 6
10330 a3549 6
10331 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10332 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10333 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10334 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10335 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10336 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10337 d3551 9
10338 a3559 9
10339 0x08, 0x09, NULL, NULL, NULL, NULL, NULL, NULL,
10340 NULL, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, NULL,
10341 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10342 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10343 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10344 NULL, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, NULL,
10345 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10346 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
10347 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
10348 d3886 1
10349 a3886 1
10350 static int build_comp (file)
10351 d4142 1
10352 a4142 1
10353 *bp = NULL;
10354 d4498 1
10355 a4498 1
10356 buffer[0] = NULL;
10357 d4534 1
10358 a4534 1
10359 *bp = NULL;
10360 d4542 1
10361 a4542 1
10362 *bp = NULL;
10363 d4623 1
10364 a4623 1
10365 *++cp = NULL;
10366 d4654 1
10367 a4654 1
10368 *cp++ = NULL;
10369 d4689 1
10370 a4689 1
10371 *cp++ = NULL;
10372 d4850 1
10373 a4850 1
10374 *cp = NULL;
10375 @
10376
10377
10378 1.5
10379 log
10380 @fix from mrose
10381 @
10382 text
10383 @d3 1
10384 a3 1
10385 static char ident[] = "@@(#)$Id: mhn.c,v 1.4 1992/02/14 16:22:17 jromine Exp jromine $";
10386 d1960 1
10387 a1960 1
10388 if (uprf (name, XXX_FIELD_PRF)) {
10389 @
10390
10391
10392 1.4
10393 log
10394 @fixes from /mtr
10395 @
10396 text
10397 @d3 1
10398 a3 1
10399 static char ident[] = "@@(#)$Id: mhn.c,v 1.3 1992/02/07 16:07:46 jromine Exp jromine $";
10400 a2426 6
10401 if (ct -> c_celine && ct -> c_encoding != CE_7BIT) {
10402 admonish (NULLCP, "%s: field should not be present for \"%s/%s\" type in message %s's %s: field",
10403 ENCODING_FIELD, ci -> ci_type, ci -> ci_subtype, ct -> c_file,
10404 TYPE_FIELD);
10405 return NOTOK;
10406 }
10407 a2974 6
10408 if (ct -> c_celine && ct -> c_encoding != CE_7BIT) {
10409 admonish (NULLCP, "%s: field should not be present for \"%s/%s\" type in message %s's %s: field",
10410 ENCODING_FIELD, ci -> ci_type, ci -> ci_subtype, ct -> c_file,
10411 TYPE_FIELD);
10412 return NOTOK;
10413 }
10414 @
10415
10416
10417 1.3
10418 log
10419 @patch from mrose
10420 @
10421 text
10422 @d3 1
10423 a3 1
10424 static char ident[] = "@@(#)$Id: mhn.c,v 1.2 1992/02/07 03:44:12 jromine Exp jromine $";
10425 d2427 1
10426 a2427 1
10427 if (ct -> c_celine) {
10428 d2981 1
10429 a2981 1
10430 if (ct -> c_celine) {
10431 d3612 1
10432 a3612 1
10433 for (ep = (cp = buffer) + cc - 2; cp <= ep; ep--)
10434 @
10435
10436
10437 1.2
10438 log
10439 @fix from mrose
10440 @
10441 text
10442 @d3 1
10443 a3 1
10444 static char ident[] = "@@(#)$Id: mhn.c,v 1.1 1992/01/31 16:28:15 jromine Exp jromine $";
10445 d2159 2
10446 a2160 1
10447 (void) sprintf (buffer, "%s %%F", moreproc);
10448 @
10449
10450
10451 1.1
10452 log
10453 @Initial revision
10454 @
10455 text
10456 @d3 1
10457 a3 1
10458 static char ident[] = "@@(#)$Id$";
10459 d1100 1
10460 d1105 4
10461 @