9 date 95.12.06.22.32.29; author jromine; state Exp;
14 date 95.12.06.21.05.46; author jromine; state Exp;
19 date 95.12.06.21.03.37; author jromine; state Exp;
24 date 95.12.06.21.02.05; author jromine; state Exp;
29 date 95.12.06.20.55.31; author jromine; state Exp;
34 date 95.12.06.19.20.22; author jromine; state Exp;
39 date 94.04.21.19.23.38; author jromine; state Exp;
44 date 93.10.26.22.17.44; author jromine; state Exp;
49 date 93.10.26.20.15.00; author jromine; state Exp;
54 date 93.10.26.20.11.27; author jromine; state Exp;
59 date 93.10.26.15.56.01; author jromine; state Exp;
64 date 93.10.26.15.51.19; author jromine; state Exp;
69 date 93.10.26.15.44.42; author jromine; state Exp;
74 date 93.10.26.15.41.33; author jromine; state Exp;
79 date 93.10.25.19.58.19; author jromine; state Exp;
84 date 93.10.25.19.32.05; author jromine; state Exp;
89 date 93.09.09.22.38.43; author jromine; state Exp;
94 date 93.09.01.21.46.58; author jromine; state Exp;
99 date 93.09.01.20.50.03; author jromine; state Exp;
104 date 93.08.25.17.26.22; author jromine; state Exp;
109 date 93.08.20.15.52.01; author jromine; state Exp;
114 date 92.12.15.00.20.22; author jromine; state Exp;
119 date 92.12.14.17.10.25; author jromine; state Exp;
124 date 92.12.10.22.27.15; author jromine; state Exp;
129 date 92.12.09.19.23.22; author jromine; state Exp;
134 date 92.12.03.21.58.18; author jromine; state Exp;
139 date 92.12.02.18.50.39; author jromine; state Exp;
144 date 92.11.24.18.21.54; author jromine; state Exp;
149 date 92.11.24.17.18.52; author jromine; state Exp;
154 date 92.11.24.17.18.04; author jromine; state Exp;
159 date 92.11.23.19.07.08; author jromine; state Exp;
164 date 92.11.23.19.05.18; author jromine; state Exp;
169 date 92.11.23.19.04.27; author jromine; state Exp;
174 date 92.11.11.17.57.04; author jromine; state Exp;
179 date 92.11.09.17.46.01; author jromine; state Exp;
184 date 92.11.09.17.45.19; author jromine; state Exp;
189 date 92.11.06.03.24.40; author jromine; state Exp;
194 date 92.11.04.00.47.59; author jromine; state Exp;
199 date 92.11.02.17.01.08; author jromine; state Exp;
204 date 92.10.26.16.58.47; author jromine; state Exp;
209 date 92.10.20.20.30.08; author jromine; state Exp;
214 date 92.10.20.16.26.29; author jromine; state Exp;
219 date 92.10.20.16.24.21; author jromine; state Exp;
224 date 92.05.19.21.01.53; author jromine; state Exp;
229 date 92.03.03.17.13.54; author jromine; state Exp;
234 date 92.02.18.17.36.22; author jromine; state Exp;
239 date 92.02.14.16.22.17; author jromine; state Exp;
244 date 92.02.07.16.07.46; author jromine; state Exp;
249 date 92.02.07.03.44.12; author jromine; state Exp;
254 date 92.01.31.16.28.15; author jromine; state Exp;
266 @rename si_value for Solaris 2.x
269 @/* mhn.c - multi-media MH */
271 static char ident[] = "@@(#)$Id: mhn.c,v 2.41 1995/12/06 21:05:46 jromine Exp jromine $";
280 #include "../zotnet/mts.h"
281 #include <sys/types.h>
282 #include <sys/stat.h>
284 #include <sys/wait.h>
292 static struct swit switches[] = {
316 #define FILESW 9 /* interface from show */
383 "moreproc program", -4,
393 "viamail mailpath", -7,
395 "viasubj subject", -7,
397 "viaparm arguments", -7,
403 "viadelay seconds", -8,
405 "viafrom mailpath", -7,
415 static struct swit caches[] = {
416 #define CACHE_NEVER 0
418 #define CACHE_PRIVATE 1
420 #define CACHE_PUBLIC 2
428 static int autosw = 0;
429 static int cachesw = 0;
430 static int checksw = 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];
451 static int wcachesw = CACHE_ASK;
453 static int endian = 0;
454 static char *mm_charset = NULL;
457 static int userrs = 0;
459 static char *cache_public;
460 static char *cache_private;
464 static char *errs = NULL;
471 extern char *sys_errlist[];
479 #define LSTFMT1 "%4s %-5s %-24s %5s %-36s\n"
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"
490 static void build_comp ();
492 typedef struct CTinfo {
497 char *ci_attrs[NPARMS + 2];
498 char *ci_values[NPARMS];
504 #define NULLCI ((CI) 0)
506 static int get_ctinfo ();
507 static int get_comment ();
510 typedef struct Content {
511 char *c_partno; /* within multipart content */
513 char *c_vrsn; /* Body-Version: */
515 char *c_ctline; /* Content-Type: */
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
526 #define CT_VIDEO 0x07
527 #define CT_EXTENSION 0x08
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 */
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 */
543 char *c_celine; /* Content-Transfer-Encoding: */
545 int c_encoding; /* internal form */
546 #define CE_UNKNOWN 0x00
547 #define CE_BASE64 0x01
548 #define CE_QUOTED 0x02
551 #define CE_BINARY 0x05
552 #define CE_EXTENSION 0x06
553 #define CE_EXTERNAL 0x07 /* for external-body */
555 caddr_t c_ceparams; /* filled-in by encoding initfnx */
557 int (*c_ceopenfnx) (); /* get a stream to decoded contents */
558 int (*c_ceclosefnx) (); /* release stream */
559 int (*c_celistfnx) (); /* list decoding info */
561 (*c_cesizefnx) (); /* size of decoded contents */
562 int (*c_cefreefnx) (); /* free encoding-specific structures */
565 char *c_id; /* Content-ID: */
566 char *c_descr; /* Content-Description: */
568 int c_digested; /* Content-MD5: */
569 unsigned char c_digest[16]; /* .. */
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 */
578 int c_pid; /* process doing display */
579 char *c_storage; /* write contents (file) */
581 int c_rfc934; /* rfc934 compatibility */
583 #define NULLCT ((CT) 0)
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 ();
591 #if defined(__STDC__) && defined(VSPRINTF)
592 static void content_error (char *, register CT, char *, ...);
594 static void content_error ();
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 ();
604 static CT *cts = NULL;
607 #define quitser pipeser
608 static TYPESIG pipeser ();
609 static char *fgetstr ();
644 setlocale(LC_ALL, "");
646 invo_name = r1bindex (argv[0], '/');
647 if (argv[1] && uprf (argv[1], "-via"))
649 if ((cp = m_find (invo_name)) != NULL) {
650 ap = brkstring (cp = getcpy (cp), " ", "\n");
651 ap = copyip (ap, arguments);
655 (void) copyip (argv + 1, ap);
660 while (cp = *argp++) {
662 switch (smatch (++cp, switches)) {
664 ambigsw (cp, switches);
667 adios (NULLCP, "-%s unknown", cp);
669 (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
671 help (buf, switches);
689 icachesw = &rcachesw;
692 icachesw = &wcachesw;
694 if (!(cp = *argp++) || *cp == '-')
695 adios (NULLCP, "missing argument to %s", argp[-2]);
696 switch (*icachesw = smatch (cp, caches)) {
698 ambigsw (cp, caches);
701 adios (NULLCP, "%s unknown", cp);
726 if (!(cp = *argp++) || *cp == '-')
727 adios (NULLCP, "missing argument to %s", argp[-2]);
730 formsw = getcpy (libpath (cp));
748 if (!(cp = *argp++) || *cp == '-')
749 adios (NULLCP, "missing argument to %s", argp[-2]);
752 "too many parts (starting with %s), %d max",
800 if (!(cp = *argp++) || *cp == '-')
801 adios (NULLCP, "missing argument to %s", argp[-2]);
804 "too many types (starting with %s), %d max",
817 if (!(progsw = *argp++) || *progsw == '-')
818 adios (NULLCP, "missing argument to %s", argp[-2]);
826 if (!(cp = *argp++) || *cp == '-')
827 adios (NULLCP, "missing argument to %s", argp[-2]);
831 if (!(cp = *argp++) || (*cp == '-' && cp[1]))
832 adios (NULLCP, "missing argument to %s", argp[-2]);
833 file = *cp == '-' ? cp : path (cp, TFILE);
838 adios (NULLCP, "missing argument to %s", argp[-2]);
842 adios (NULLCP, "missing argument to %s", argp[-2]);
846 adios (NULLCP, "missing argument to %s", argp[-2]);
850 adios (NULLCP, "missing argument to %s", argp[-2]);
854 adios (NULLCP, "missing argument to %s", argp[-2]);
857 if (!(cp = *argp++) || *cp == '-')
858 adios (NULLCP, "missing argument to %s", argp[-2]);
859 if (sscanf (cp, "%d", &f6) != 1 || f6 < 0)
864 adios (NULLCP, "missing argument to %s", argp[-2]);
867 if (*cp == '+' || *cp == '@@') {
869 adios (NULLCP, "only one folder at a time!");
871 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
876 parts[npart] = NULL, types[ntype] = NULL;
878 formsw = getcpy (libpath ("mhl.headers"));
885 via_mail (f1, f2, f3, f4, f5, f6, f7);
889 if (f2 || f3 || f4 || f5 || f6 || f7)
890 adios (NULLCP, "missing -viamail \"mailpath\" switch");
892 if (cp = getenv ("MHN")) {
893 if (fp = fopen (cp, "r")) {
894 m_readefs ((struct node **) 0, fp, cp, 0);
899 admonish ("", "unable to read $MHN profile (%s)", cp);
901 if (fp = fopen (cp = libpath ("mhn_defaults"), "r")) {
902 m_readefs ((struct node **) 0, fp, cp, 0);
907 (void) sprintf (buf, "%s-cache", invo_name);
908 if ((cache_public = m_find (buf)) && *cache_public != '/')
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));
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);
921 if (!m_find ("path"))
922 free (path ("./", TFOLDER));
932 && (cp = getenv ("mhdraft"))
933 && strcmp (cp, msgs[0]) == 0) {
942 adios (NULLCP, "only one file at a time!");
944 if ((cts = (CT *) calloc ((unsigned) 2, sizeof *cts)) == NULL)
945 adios (NULLCP, "out of memory");
948 if (stdinP = (strcmp (file, "-") == 0)) {
951 file = add (m_tmpfil (invo_name), NULLCP);
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);
960 if (ferror (stdin)) {
961 (void) unlink (file);
962 adios ("stdin", "error reading");
966 (void) unlink (file);
967 adios (file, "error writing");
970 (void) fseek (fp, 0L, 0);
973 if ((fp = fopen (file, "r")) == NULL)
974 adios (file, "unable to read");
976 if (ct = get_content (fp, file, 1)) {
981 if (ct -> c_end == 0L) {
982 (void) fseek (fp, 0L, 2);
983 ct -> c_end = ftell (fp);
985 if (ct -> c_ctinitfnx && (*ct -> c_ctinitfnx) (ct) == NOTOK)
991 advise (NULLCP, "unable to decode %s", file);
1000 msgs[msgp++] = "cur";
1002 folder = m_getfolder ();
1003 maildir = m_maildir (folder);
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);
1012 for (msgnum = 0; msgnum < msgp; msgnum++)
1013 if (!m_convert (mp, msgs[msgnum]))
1017 if ((cts = (CT *) calloc ((unsigned) (mp -> numsel + 1), sizeof *cts))
1019 adios (NULLCP, "out of memory");
1022 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1023 if (mp -> msgstats[msgnum] & SELECTED) {
1026 if ((fp = fopen (msgnam = m_name (msgnum), "r")) == NULL)
1027 adios (msgnam, "unable to read message");
1029 if (ct = get_content (fp, msgnam, 1)) {
1031 if (ct -> c_end == 0L) {
1032 (void) fseek (fp, 0L, 2);
1033 ct -> c_end = ftell (fp);
1035 if (ct -> c_ctinitfnx && (*ct -> c_ctinitfnx) (ct) == NOTOK)
1041 advise (NULLCP, "unable to decode message %s", msgnam);
1050 if (!listsw && !showsw && !storesw && !cachesw)
1053 /* listsw && showsw -> user wants per-message listing,
1054 so delay until showsw processing
1056 && storesw && sizesw -> evaluating size will cause more work,
1057 so delay until after storesw processing
1060 (void) signal (SIGQUIT, quitser);
1061 (void) signal (SIGPIPE, pipeser);
1063 for (ctp = cts; ct = *ctp; ctp++)
1065 && (ct -> c_ctlistfnx
1066 || ct -> c_ctstorefnx
1067 || ct -> c_ctshowfnx)) {
1071 ct -> c_umask = ~(stat (ct -> c_file, &st) != NOTOK
1072 ? (st.st_mode & 0777) : m_gmprot ());
1075 if (listsw && !showsw && (!storesw || !sizesw)) {
1077 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
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);
1085 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1086 if (ct -> c_ceclosefnx)
1087 (*ct -> c_ceclosefnx) (ct);
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);
1099 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1100 if (ct -> c_ceclosefnx)
1101 (*ct -> c_ceclosefnx) (ct);
1108 for (ctp = cts; ct = *ctp; ctp++)
1109 if (type_ok (ct, 1)) {
1112 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1113 if (ct -> c_ceclosefnx)
1114 (*ct -> c_ceclosefnx) (ct);
1120 if (listsw && !showsw && storesw && sizesw) {
1122 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
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);
1130 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1131 if (ct -> c_ceclosefnx)
1132 (*ct -> c_ceclosefnx) (ct);
1140 for (ctp = cts; ct = *ctp; ctp++) {
1141 #if defined(BSD42) && !defined(WAITINT)
1146 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
1148 if (!type_ok (ct, 0))
1151 (void) umask (ct -> c_umask);
1155 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
1158 if (ct -> c_ctlistfnx)
1159 (void) (*ct -> c_ctlistfnx) (ct, 1);
1162 if (!ct -> c_ctshowfnx) {
1164 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1165 if (ct -> c_ceclosefnx)
1166 (*ct -> c_ceclosefnx) (ct);
1170 if (strcmp (formsw, "mhl.null")) {
1177 vec[vecp++] = r1bindex (mhlproc, '/');
1178 vec[vecp++] = "-form";
1179 vec[vecp++] = formsw;
1180 vec[vecp++] = "-nobody";
1181 vec[vecp++] = ct -> c_file;
1183 vec[vecp++] = "-nomoreproc";
1186 vec[vecp++] = "-moreproc";
1187 vec[vecp++] = progsw;
1191 (void) fflush (stdout);
1193 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
1197 adios ("fork", "unable to");
1201 (void) execvp (mhlproc, vec);
1202 fprintf (stderr, "unable to exec ");
1215 (void) (*ct -> c_ctshowfnx) (ct, 1, 0);
1217 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
1218 if (ct -> c_ceclosefnx)
1219 (*ct -> c_ceclosefnx) (ct);
1221 hstat = signal (SIGHUP, SIG_IGN);
1222 istat = signal (SIGINT, SIG_IGN);
1223 qstat = signal (SIGQUIT, SIG_IGN);
1224 tstat = signal (SIGTERM, SIG_IGN);
1226 while (wait (&status) != NOTOK) {
1227 #if defined(BSD42) && !defined(WAITINT)
1228 (void) pidcheck (status.w_status);
1230 (void) pidcheck (status);
1235 (void) signal (SIGHUP, hstat);
1236 (void) signal (SIGINT, istat);
1237 (void) signal (SIGQUIT, qstat);
1238 (void) signal (SIGTERM, tstat);
1245 for (ctp = cts; *ctp; ctp++)
1246 free_content (*ctp);
1247 free ((char *) cts);
1251 m_replace (pfolder, folder);
1252 if (mp -> hghsel != mp -> curmsg)
1253 m_setcur (mp, mp -> hghsel);
1264 static TYPESIG pipeser (i)
1268 (void) unlink ("core");
1270 (void) fflush (stdout);
1272 fprintf (stderr, "\n");
1273 (void) fflush (stderr);
1282 #include "../h/mhn.h"
1292 static int InitApplication (), InitMessage (), InitMultiPart (), InitText (),
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,
1305 NULL, CT_EXTENSION, NULL, /* these two must be last! */
1306 NULL, CT_UNKNOWN, NULL,
1310 static int InitBase64 (), InitQuoted (), Init7Bit ();
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,
1319 NULL, CE_EXTENSION, NULL, /* these two must be last! */
1320 NULL, CE_UNKNOWN, NULL,
1325 static CT get_content (in, file, toplevel)
1336 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
1337 adios (NULLCP, "out of memory");
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)) {
1348 if (uleq (name, VRSN_FIELD)) {
1354 cp = add (buf, NULLCP);
1355 while (state == FLDPLUS) {
1356 state = m_getfld (state, name, buf, sizeof buf, in);
1363 "message %s has multiple %s: fields (%s)",
1364 ct -> c_file, VRSN_FIELD, dp = trimcpy (cp));
1375 while (isspace (*cp))
1377 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1379 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1384 fprintf (stderr, "%s: %s\n", VRSN_FIELD, cp);
1386 if (*cp == '(' && get_comment (ct, &cp, 0) == NOTOK)
1389 for (dp = cp; istoken (*dp); dp++)
1391 c = *dp, *dp = '\0';
1392 ucmp = uleq (cp, VRSN_VALUE);
1396 "message %s has unknown value for %s: field (%s)",
1397 ct -> c_file, VRSN_FIELD, cp);
1401 if (uleq (name, TYPE_FIELD)) {
1403 register struct str2init *s2i;
1404 register CI ci = &ct -> c_ctinfo;
1406 cp = add (buf, NULLCP);
1407 while (state == FLDPLUS) {
1408 state = m_getfld (state, name, buf, sizeof buf, in);
1412 if (ct -> c_ctline) {
1413 char *dp = trimcpy (cp);
1416 "message %s has multiple %s: fields (%s)",
1417 ct -> c_file, TYPE_FIELD, dp);
1423 if (get_ctinfo (cp, ct, 0) == NOTOK)
1425 for (s2i = str2cts; s2i -> si_key; s2i++)
1426 if (uleq (ci -> ci_type, s2i -> si_key))
1428 if (!s2i -> si_key && !uprf (ci -> ci_type, "X-"))
1430 ct -> c_type = s2i -> si_val;
1431 ct -> c_ctinitfnx = s2i -> si_init;
1435 if (uleq (name, ENCODING_FIELD)) {
1439 register struct str2init *s2i;
1441 cp = add (buf, NULLCP);
1442 while (state == FLDPLUS) {
1443 state = m_getfld (state, name, buf, sizeof buf, in);
1447 if (ct -> c_celine) {
1449 "message %s has multiple %s: fields (%s)",
1450 ct -> c_file, ENCODING_FIELD,
1457 ct -> c_celine = cp;
1458 while (isspace (*cp))
1460 for (dp = cp; istoken (*dp); dp++)
1462 c = *dp, *dp = '\0';
1463 for (s2i = str2ces; s2i -> si_key; s2i++)
1464 if (uleq (cp, s2i -> si_key))
1466 if (!s2i -> si_key && !uprf (cp, "X-"))
1469 ct -> c_encoding = s2i -> si_val;
1470 if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
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);
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);
1493 if (uleq (name, MD5_FIELD)) {
1498 cp = add (buf, NULLCP);
1499 while (state == FLDPLUS) {
1500 state = m_getfld (state, name, buf, sizeof buf, in);
1509 if (ct -> c_digested) {
1511 "message %s has multiple %s: fields (%s)",
1512 ct -> c_file, MD5_FIELD,
1520 while (isspace (*cp))
1522 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1524 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1529 fprintf (stderr, "%s: %s\n", MD5_FIELD, cp);
1531 if (*cp == '(' && get_comment (ct, &cp, 0) == NOTOK) {
1536 for (dp = cp; *dp && !isspace (*dp); dp++)
1540 (void) readDigest (ct, cp);
1547 if (uprf (name, XXX_FIELD_PRF))
1548 advise (NULLCP, "unknown field (%s) in message %s",
1549 name, ct -> c_file);
1553 while (state == FLDPLUS)
1554 state = m_getfld (state, name, buf, sizeof buf, in);
1556 if (state != FLDEOF) {
1557 ct -> c_begin = ftell (in) + 1;
1564 ct -> c_begin = ftell (in) - strlen (buf);
1568 ct -> c_begin = ftell (in);
1573 adios (NULLCP, "message format error in component #%d",
1577 adios (NULLCP, "getfld() returned %d", state);
1582 if (!ct -> c_ctline) {
1584 if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK)
1586 ct -> c_type = CT_MESSAGE;
1587 ct -> c_ctinitfnx = InitMessage;
1590 if (get_ctinfo ("text/plain", ct, 0) == NOTOK)
1592 ct -> c_type = CT_TEXT;
1593 ct -> c_ctinitfnx = InitText;
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;
1603 if (!ct -> c_celine) {
1604 ct -> c_encoding = CE_7BIT;
1605 (void) Init7Bit (ct);
1617 static int get_ctinfo (cp, ct, magic)
1622 int i = strlen (invo_name) + 2;
1627 register CI ci = &ct -> c_ctinfo;
1629 cp = ct -> c_ctline = add (cp, NULLCP);
1630 while (isspace (*cp))
1632 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
1634 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1639 fprintf (stderr, "%s: %s\n", TYPE_FIELD, cp);
1641 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1644 for (dp = cp; istoken (*dp); dp++)
1646 c = *dp, *dp = '\0';
1647 ci -> ci_type = add (cp, NULLCP);
1650 if (!*ci -> ci_type) {
1651 advise (NULLCP, "invalid %s: field in message %s (empty type)",
1652 TYPE_FIELD, ct -> c_file);
1656 for (dp = ci -> ci_type; *dp; dp++)
1657 if (isalpha(*dp) && isupper (*dp))
1658 *dp = tolower (*dp);
1660 while (isspace (*cp))
1663 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1668 ci -> ci_subtype = add ("", NULLCP);
1673 while (isspace (*cp))
1676 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1679 for (dp = cp; istoken (*dp); dp++)
1681 c = *dp, *dp = '\0';
1682 ci -> ci_subtype = add (cp, NULLCP);
1685 if (!*ci -> ci_subtype) {
1687 "invalid %s: field in message %s (empty subtype for \"%s\")",
1688 TYPE_FIELD, ct -> c_file, ci -> ci_type);
1692 for (dp = ci -> ci_subtype; *dp; dp++)
1693 if (isalpha(*dp) && isupper (*dp))
1694 *dp = tolower (*dp);
1697 while (isspace (*cp))
1700 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1703 ep = (ap = ci -> ci_attrs) + NPARMS;
1704 while (*cp == ';') {
1710 "too many parameters in message %s's %s: field (%d max)",
1711 ct -> c_file, TYPE_FIELD, NPARMS);
1716 while (isspace (*cp))
1719 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1724 "extraneous trailing ';' in message %s's %s: parameter list",
1725 ct -> c_file, TYPE_FIELD);
1729 for (dp = cp; istoken (*dp); dp++)
1730 if (isalpha(*dp) && isupper (*dp))
1731 *dp = tolower (*dp);
1732 for (up = dp; isspace (*dp); )
1734 if (dp == cp || *dp != '=') {
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);
1741 vp = (*ap = add (cp, NULLCP)) + (up - cp);
1743 for (dp++; isspace (*dp); )
1745 ci -> ci_values[ap - ci -> ci_attrs] = vp = *ap + (dp - cp);
1747 for (cp = ++dp, dp = vp;;) {
1748 switch (c = *cp++) {
1752 "invalid quoted-string in message %s's %s: field\n%*.*s(parameter %s)",
1753 ct -> c_file, TYPE_FIELD, i, i, "", *ap);
1758 if ((c = *cp++) == '\0')
1774 for (cp = dp, dp = vp; istoken (*cp); cp++, dp++)
1780 "invalid parameter in message %s's %s: field\n%*.*s(parameter %s)",
1781 ct -> c_file, TYPE_FIELD, i, i, "", *ap);
1786 while (isspace (*cp))
1789 if (*cp == '(' && get_comment (ct, &cp, 1) == NOTOK)
1793 if (magic && *cp == '<') {
1795 free (ct -> c_id), ct -> c_id = NULL;
1797 if (!(dp = index (ct -> c_id = ++cp, '>'))) {
1798 advise (NULLCP, "invalid ID in message %s", ct -> c_file);
1802 c = *dp, *dp = '\0';
1804 ct -> c_id = concat ("<", ct -> c_id, ">\n", NULLCP);
1809 while (isspace (*cp))
1813 if (magic && *cp == '[') {
1814 ct -> c_descr = ++cp;
1815 for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
1819 advise (NULLCP, "invalid description in message %s", ct -> c_file);
1820 ct -> c_descr = NULL;
1824 c = *dp, *dp = '\0';
1826 ct -> c_descr = concat (ct -> c_descr, "\n", NULLCP);
1828 ct -> c_descr = NULL;
1831 while (isspace (*cp))
1837 ci -> ci_magic = add (cp, NULLCP);
1840 "extraneous information in message %s's %s: field\n%*.*s(%s)",
1841 ct -> c_file, TYPE_FIELD, i, i, "", cp);
1849 static int get_comment (ct, ap, istype)
1860 register CI ci = &ct -> c_ctinfo;
1867 switch (c = *cp++) {
1870 advise (NULLCP, "invalid comment in message %s's %s: field",
1871 ct -> c_file, istype ? TYPE_FIELD : VRSN_FIELD);
1876 if ((c = *cp++) == '\0')
1899 if (dp = ci -> ci_comment) {
1900 ci -> ci_comment = concat (dp, " ", buffer, NULLCP);
1904 ci -> ci_comment = add (buffer, NULLCP);
1907 while (isspace (*cp))
1917 #define empty(s) ((s) ? (s) : "")
1920 static int list_content (ct, toplevel)
1929 register CI ci = &ct -> c_ctinfo;
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);
1937 size = ct -> c_cesizefnx && sizesw ? (*ct -> c_cesizefnx) (ct)
1938 : ct -> c_end - ct -> c_begin;
1940 for (cp = " KMGT"; size > 9999; size >>= 10)
1945 if (size > 0 || ct -> c_encoding != CE_EXTERNAL)
1946 printf (LSTFMT2c1, size);
1952 printf (LSTFMT2c2, size, *cp);
1959 if (ct -> c_descr) {
1962 dp = trimcpy (cp = add (ct -> c_descr, NULLCP));
1964 printf (LSTFMT2d1, dp);
1970 if (verbosw && ci -> ci_comment) {
1973 dp = trimcpy (cp = add (ci -> ci_comment, NULLCP));
1975 (void) sprintf (buffer, "(%s)", dp);
1977 printf (LSTFMT2d2, buffer);
1983 (void) fflush (stdout);
1985 fprintf (stderr, " partno \"%s\"\n", empty (ct -> c_partno));
1988 fprintf (stderr, " %s:%s\n", VRSN_FIELD, ct -> c_vrsn);
1991 fprintf (stderr, " %s:%s", TYPE_FIELD, ct -> c_ctline);
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);
1999 " type 0x%x subtype 0x%x params 0x%x\n",
2000 ct -> c_type, ct -> c_subtype, ct -> c_ctparams);
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));
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);
2012 fprintf (stderr, " %s:%s", ID_FIELD, ct -> c_id);
2014 fprintf (stderr, " %s:%s", DESCR_FIELD, ct -> c_descr);
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);
2019 if (ct -> c_celistfnx)
2020 (void) (*ct -> c_celistfnx) (ct);
2032 #include <varargs.h>
2038 static void content_error (char *what, register CT ct, char *fmt, ...)
2040 static void content_error (va_alist)
2043 #else /* !VSPRINTF */
2045 static void content_error (what, ct, fmt, a, b, c, d, e, f)
2060 #if defined(VSPRINTF) && !defined(__STDC__)
2066 char buffer[BUFSIZ];
2071 if (userrs && invo_name && *invo_name) {
2072 (void) sprintf (bp, "%s: ", invo_name);
2078 va_start (arglist, fmt);
2081 what = va_arg(arglist, char *);
2082 ct = va_arg(arglist, CT);
2083 fmt = va_arg(arglist, char *);
2085 (void) vsprintf (bp, fmt, arglist);
2088 (void) sprintf (bp, fmt, a, b, c, d, e, f);
2091 ci = &ct -> c_ctinfo;
2095 (void) sprintf (bp, " %s: ", what);
2099 if (errno > 0 && errno < sys_nerr)
2100 (void) sprintf (bp, "%s", sys_errlist[errno]);
2102 (void) sprintf (bp, "Error %d", errno);
2106 i = strlen (invo_name) + 2;
2107 (void) sprintf (bp, "\n%*.*s(content %s/%s", i, i, "", ci -> ci_type,
2111 (void) sprintf (bp, " in message %s", ct -> c_file);
2113 if (ct -> c_partno) {
2114 (void) sprintf (bp, ", part %s", ct -> c_partno);
2118 (void) sprintf (bp, ")");
2125 errs = add (buffer, errs);
2128 advise (NULLCP, "%s", buffer);
2132 static void flush_errors ()
2135 (void) fflush (stdout);
2136 fprintf (stderr, "%s", errs);
2144 static jmp_buf intrenv;
2149 static TYPESIG intrser (i)
2153 (void) signal (SIGINT, intrser);
2156 (void) putchar ('\n');
2158 longjmp (intrenv, DONE);
2163 static int show_content_aux (), show_content_aux2 ();
2166 static int show_content (ct, serial, alternate)
2172 char buffer[BUFSIZ];
2173 register CI ci = &ct -> c_ctinfo;
2175 (void) sprintf (buffer, "%s-show-%s/%s", invo_name, ci -> ci_type,
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) {
2182 content_error (NULLCP, ct,
2183 "don't know how to display content");
2189 return show_content_aux (ct, serial, alternate, cp, NULLCP);
2193 static int show_content_aux (ct, serial, alternate, cp, cracked)
2208 register CI ci = &ct -> c_ctinfo;
2210 if (!ct -> c_ceopenfnx) {
2212 content_error (NULLCP, ct, "don't know how to decode content");
2218 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
2220 if (ct -> c_showproc && strcmp (ct -> c_showproc, "true") == 0)
2221 return (alternate ? DONE : OK);
2223 xlist = xpause = xstdin = xtty = 0;
2225 (void) strcpy (buffer, cp);
2229 for (bp = buffer; *cp; cp++)
2232 case 'a': /* additional arguments */
2238 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
2241 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
2248 case 'd': /* content description */
2249 if (ct -> c_descr) {
2252 (void) strcpy (bp, s = trimcpy (ct -> c_descr));
2257 case 'e': /* exclusive execution */
2261 case 'F': /* %e, %f, and stdin is terminal not content */
2264 case 'f': /* filename */
2265 (void) sprintf (bp, "%s", file);
2268 case 'p': /* pause prior to displaying content */
2271 case 'l': /* display listing prior to displaying
2276 case 's': /* subtype */
2277 (void) strcpy (bp, ci -> ci_subtype);
2295 if (ct -> c_termproc) {
2298 (void) strcpy (term, buffer);
2299 (void) sprintf (buffer, ct -> c_termproc, term);
2303 return show_content_aux2 (ct, serial, alternate, cracked, buffer,
2304 fd, xlist, xpause, xstdin, xtty);
2308 static int show_content_aux2 (ct, serial, alternate, cracked, buffer,
2309 fd, xlist, xpause, xstdin, xtty)
2324 exec[BUFSIZ + sizeof "exec "];
2325 register CI ci = &ct -> c_ctinfo;
2327 if (debugsw || cracked) {
2328 (void) fflush (stdout);
2330 fprintf (stderr, "%s msg %s", cracked ? "storing" : "show",
2333 fprintf (stderr, " part %s", ct -> c_partno);
2335 fprintf (stderr, " using command (cd %s; %s)\n", cracked, buffer);
2337 fprintf (stderr, " using command %s\n", buffer);
2340 if (xpid < 0 || (xtty && xpid)) {
2343 (void) pidcheck (pidwait (xpid, NOTOK));
2348 char prompt[BUFSIZ];
2350 if (ct -> c_ctlistfnx) {
2351 if (ct -> c_type == CT_MULTIPART)
2352 (void) list_content (ct, -1);
2354 (*ct -> c_ctlistfnx) (ct, -1);
2356 if (xpause && SOprintf ("Press <return> to show content..."))
2357 printf ("Press <return> to show content...");
2363 if (ct -> c_descr) {
2364 (void) sprintf (pp, "%s (", ct -> c_descr);
2368 (void) sprintf (pp, "content %s/%s", ci -> ci_type,
2372 (void) sprintf (pp, " in message %s", ct -> c_file);
2374 if (ct -> c_partno) {
2375 (void) sprintf (pp, ", part %s", ct -> c_partno);
2380 if (ct -> c_descr) {
2381 (void) sprintf (pp, ")");
2386 printf ("%s\n", prompt);
2388 if (SOprintf ("Press <return> to show %s...", prompt))
2389 printf ("Press <return> to show %s...", prompt);
2394 TYPESIG (*istat) ();
2396 istat = signal (SIGINT, intrser);
2397 if ((intr = setjmp (intrenv)) == OK) {
2398 (void) fflush (stdout);
2400 (void) read (fileno (stdout), prompt, sizeof prompt);
2402 (void) signal (SIGINT, istat);
2403 if (intr != OK || prompt[0] == 'q') {
2404 (void) (*ct -> c_ceclosefnx) (ct);
2405 return (alternate ? DONE : NOTOK);
2410 (void) sprintf (exec, "exec %s", buffer);
2417 (void) fflush (stdout);
2419 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
2423 advise ("fork", "unable to");
2424 (void) (*ct -> c_ceclosefnx) (ct);
2429 (void) chdir (cracked);
2431 (void) dup2 (fd, 0);
2433 (void) execvp ("/bin/sh", vec);
2434 fprintf (stderr, "unable to exec ");
2441 ct -> c_pid = child_id;
2446 (void) pidcheck (pidXwait (child_id, NULLCP));
2449 (void) (*ct -> c_ceclosefnx) (ct);
2450 return (alternate ? DONE : OK);
2456 static int store_content (ct, append)
2460 int appending = append && *append;
2467 register CI ci = &ct -> c_ctinfo;
2471 (void) strcpy (buffer, append);
2475 if ((cp = ct -> c_storeproc) == NULL || *cp == 0) {
2476 (void) sprintf (buffer, "%s-store-%s/%s", invo_name, ci -> ci_type,
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";
2489 char *folder = cp[1] ? path (cp + 1, *cp == '+' ? TFOLDER
2492 struct msgs *mp = NULL;
2495 if (stat (bp = m_mailpath (folder), &st) == NOTOK) {
2499 if (errno != ENOENT) {
2500 advise (bp, "error on folder");
2504 ep = concat ("Create folder \"", bp, "\"? ", NULLCP);
2505 answer = getanswer (ep);
2510 if (!makedir (bp)) {
2511 advise (NULLCP, "unable to create folder %s", bp);
2516 if (mp = m_gmsg (folder))
2517 (void) sprintf (buffer, "%s/%d", mp -> foldpath,
2520 advise (NULLCP, "unable to read folder %s", folder);
2539 bp = autosw ? cwd : dir;
2540 (void) sprintf (buffer, "%s/", bp[1] ? bp : "");
2541 bp = buffer + strlen (buffer);
2547 case 'a': /* additional arguments */
2548 if (buffer[0] != '|' && buffer[0] != '!') {
2558 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
2561 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
2568 case 'm': /* message */
2569 (void) sprintf (bp, "%s", r1bindex (ct -> c_file, '/'));
2572 case 'P': /* .part */
2574 (void) sprintf (bp, ".%s", ct -> c_partno);
2577 case 'p': /* part */
2579 (void) strcpy (bp, ct -> c_partno);
2582 case 't': /* type */
2583 (void) strcpy (bp, ci -> ci_type);
2586 case 's': /* subtype */
2587 (void) strcpy (bp, ci -> ci_subtype);
2605 if (buffer[0] == '|' || buffer[0] == '!')
2606 return show_content_aux (ct, 1, 0, buffer + 1, autosw ? cwd : dir);
2609 ct -> c_storage = add (buffer, NULLCP);
2610 (void) fflush (stdout);
2611 fprintf (stderr, "storing message %s", ct -> c_file);
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)
2622 if (ct -> c_encoding != CE_7BIT) {
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);
2632 file = appending || !strcmp (ct -> c_storage, "-") ? NULLCP
2634 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
2636 if (strcmp (file, ct -> c_storage) == 0) {
2637 (void) (*ct -> c_ceclosefnx) (ct);
2641 if (!strcmp (ct -> c_storage, "-")) {
2644 if ((gd = dup (fileno (stdout))) == NOTOK) {
2645 advise ("stdout", "unable to dup");
2647 (void) (*ct -> c_ceclosefnx) (ct);
2650 if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) {
2651 advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd,
2652 appending ? "a" : "w");
2658 if ((fp = fopen (ct -> c_storage, appending ? "a" : "w"))
2660 advise (ct -> c_storage, "unable to fopen for %s",
2661 appending ? "appending" : "writing");
2665 if (append && !*append)
2666 (void) copy_some_headers (fp, ct);
2669 switch (cc = read (fd, buffer, sizeof buffer)) {
2671 advise (file, "error reading content from");
2678 (void) fwrite (buffer, sizeof *buffer, cc, fp);
2684 (void) (*ct -> c_ceclosefnx) (ct);
2686 if (cc != NOTOK && fflush (fp))
2687 advise (ct -> c_storage, "error writing to");
2691 return (cc != NOTOK ? OK : NOTOK);
2694 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
2695 advise (ct -> c_file, "unable to open for reading");
2699 (void) fseek (ct -> c_fp, pos = ct -> c_begin, 0);
2702 if (!strcmp (ct -> c_storage, "-")) {
2705 if ((gd = dup (fileno (stdout))) == NOTOK) {
2706 advise ("stdout", "unable to dup");
2709 if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) {
2710 advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd,
2711 appending ? "a" : "w");
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");
2723 if (append && !*append) {
2724 (void) copy_some_headers (fp, ct);
2730 while (fgets (buffer, sizeof buffer - 1, ct -> c_fp)) {
2731 if ((pos += strlen (buffer)) > last) {
2732 int diff = strlen (buffer) - (pos - last);
2735 buffer[diff] = '\0';
2739 switch (buffer[0]) {
2751 if (!uprf (buffer, XXX_FIELD_PRF)
2752 && !uprf (buffer, "Encrypted:")
2753 && !uprf (buffer, "Message-ID:")) {
2762 (void) fputs (buffer, fp);
2768 advise (ct -> c_storage, "error writing to");
2772 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
2778 static int copy_some_headers (out, ct)
2787 if ((in = fopen (ct -> c_file, "r")) == NULL) {
2788 advise (ct -> c_file, "unable to open for reading");
2792 for (state = FLD;;) {
2793 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
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);
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);
2810 if (state != FLDEOF)
2833 static int make_intermediates (file)
2838 for (cp = file + 1; cp = index (cp, '/'); cp++) {
2843 if (stat (file, &st) == NOTOK) {
2847 if (errno != ENOENT) {
2848 advise (file, "error on directory");
2854 ep = concat ("Create directory \"", file, "\"? ", NULLCP);
2855 answer = getanswer (ep);
2859 goto losing_directory;
2860 if (!makedir (file)) {
2861 advise (NULLCP, "unable to create directory %s", file);
2862 goto losing_directory;
2874 static void free_ctinfo (ct)
2878 register CI ci = &ct -> c_ctinfo;
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;
2892 free (ci -> ci_magic);
2893 ci -> ci_magic = NULL;
2897 static void free_content (ct)
2904 free (ct -> c_partno);
2905 ct -> c_partno = NULL;
2908 free (ct -> c_vrsn);
2909 ct -> c_vrsn = NULL;
2912 free (ct -> c_ctline);
2913 ct -> c_ctline = NULL;
2917 if (ct -> c_ctfreefnx)
2918 (void) (*ct -> c_ctfreefnx) (ct);
2919 ct -> c_ctfreefnx = NULL;
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;
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;
2942 free (ct -> c_descr);
2943 ct -> c_descr = NULL;
2947 (void) unlink (ct -> c_file);
2948 free (ct -> c_file);
2949 ct -> c_file = NULL;
2952 (void) fclose (ct -> c_fp);
2955 if (ct -> c_storage)
2956 (void) free (ct -> c_storage);
2957 ct -> c_storage = NULL;
2964 static int part_ok (ct, sP)
2970 if ((ct -> c_type == CT_MULTIPART && (sP || ct -> c_subtype))
2974 for (ap = parts; *ap; ap++)
2975 if (strcmp (*ap, ct -> c_partno) == 0)
2983 static int type_ok (ct, sP)
2988 char buffer[BUFSIZ];
2989 register CI ci = &ct -> c_ctinfo;
2991 if ((ct -> c_type == CT_MULTIPART && (sP || ct -> c_subtype))
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))
3011 static int InitGeneric (ct)
3016 register CI ci = &ct -> c_ctinfo;
3018 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3019 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
3022 if (*(cp = *ep) != '/'
3026 && !index (cp, '%'))
3027 ct -> c_storeproc = add (cp, NULLCP);
3035 #define TEXT_UNKNOWN 0x00
3036 #define TEXT_PLAIN 0x01
3037 #define TEXT_RICHTEXT 0x02
3041 #define CHARSET_UNKNOWN 0x00
3042 #define CHARSET_USASCII 0x01
3043 #define CHARSET_LATIN 0x02
3046 static struct k2v Charset[] = {
3047 "us-ascii", CHARSET_USASCII,
3048 "iso-8859-1", CHARSET_LATIN,
3050 NULL, CHARSET_UNKNOWN /* this one must be last! */
3053 static int free_text (ct)
3056 register struct text *t = (struct text *) ct -> c_ctparams;
3062 ct -> c_ctparams = NULL;
3066 static struct k2v SubText[] = {
3067 "plain", TEXT_PLAIN,
3068 "richtext", TEXT_RICHTEXT,
3070 NULL, TEXT_UNKNOWN /* this one must be last! */
3073 static int InitText (ct)
3076 char buffer[BUFSIZ];
3079 register struct k2v *kv;
3080 register CI ci = &ct -> c_ctinfo;
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))
3087 if ((ct -> c_subtype = kv -> kv_value) == TEXT_PLAIN) {
3088 (void) sprintf (buffer, "%%p%s '%%F'",
3090 : moreproc && *moreproc ? moreproc : "more");
3091 ct -> c_showproc = add (buffer, NULLCP);
3094 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3095 if (!ct -> c_ctparams && uleq (*ap, "charset")) {
3097 register struct text *t;
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;
3104 for (kv = Charset; kv -> kv_key; kv++)
3105 if (uleq (*ep, kv -> kv_key)) {
3106 (void) sprintf (buffer, "%s-charset-%s", invo_name,
3110 t -> tx_charset = kv -> kv_value;
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);
3118 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
3121 if (*(cp = *ep) != '/'
3125 && !index (cp, '%'))
3126 ct -> c_storeproc = add (cp, NULLCP);
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
3148 struct part *mp_next;
3153 static int list_multi (ct, toplevel)
3157 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3158 register struct part *part;
3160 (void) list_content (ct, toplevel);
3162 for (part = m -> mp_parts; part; part = part -> mp_next) {
3163 register CT p = part -> mp_part;
3165 if (part_ok (p, 1) && type_ok (p, 1) && p -> c_ctlistfnx)
3166 (void) (*p -> c_ctlistfnx) (p, 0);
3173 static int show_multi (ct, serial, alternate)
3182 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3183 register struct part *part;
3185 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
3188 nowalternate = alternate;
3189 switch (ct -> c_subtype) {
3190 case MULTI_PARALLEL:
3191 if (!(nowserial = serialsw)) {
3193 hstat = signal (SIGHUP, SIG_IGN);
3194 istat = signal (SIGINT, SIG_IGN);
3195 qstat = signal (SIGQUIT, SIG_IGN);
3196 tstat = signal (SIGTERM, SIG_IGN);
3200 case MULTI_ALTERNATE:
3201 nowalternate = alternating = 1;
3204 if (!(nowserial = serial))
3209 /* alternate -> we're inside an alternative
3210 alternating -> we are an alternative
3213 result = alternate ? NOTOK : OK;
3214 for (part = m -> mp_parts; part; part = part -> mp_next) {
3215 p = part -> mp_part;
3217 if (part_ok (p, 0) && type_ok (p, 0) && p -> c_ctshowfnx) {
3220 switch (inneresult = (*p -> c_ctshowfnx) (p, nowserial,
3223 if (alternate && !alternating) {
3236 alternate = nowalternate = 0;
3237 if (result == NOTOK)
3238 result = inneresult;
3245 if (alternating && !part) {
3247 content_error (NULLCP, ct,
3248 "don't know how to display any of the contents");
3254 if (serial && !nowserial) {
3257 #if defined(BSD42) && !defined(WAITINT)
3264 for (part = m -> mp_parts; part; part = part -> mp_next) {
3265 p = part -> mp_part;
3267 if (p -> c_pid > OK)
3268 if (kill (p -> c_pid, 0) == NOTOK)
3274 while (kids > 0 && (pid = wait (&status)) != NOTOK) {
3275 #if defined(BSD42) && !defined(WAITINT)
3276 (void) pidcheck (status.w_status);
3278 (void) pidcheck (status);
3281 for (part = m -> mp_parts; part; part = part -> mp_next) {
3282 p = part -> mp_part;
3286 if (p -> c_pid == pid) {
3297 (void) signal (SIGHUP, hstat);
3298 (void) signal (SIGINT, istat);
3299 (void) signal (SIGQUIT, qstat);
3300 (void) signal (SIGTERM, tstat);
3307 static int show_unknown_multi (ct, serial, alternate)
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;
3323 (void) sprintf (buffer, "%s-show-%s/%s", invo_name, ci -> ci_type,
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) {
3330 content_error (NULLCP, ct,
3331 "don't know how to display content");
3337 for (part = m -> mp_parts; part; part = part -> mp_next) {
3338 p = part -> mp_part;
3340 if (!p -> c_ceopenfnx) {
3342 content_error (NULLCP, p, "don't know how to decode content");
3347 if (p -> c_storage == NULL) {
3348 if ((*p -> c_ceopenfnx) (p, &p -> c_storage) == NOTOK)
3351 if (p -> c_showproc && strcmp (p -> c_showproc, "true") == 0)
3352 return (alternate ? DONE : OK);
3353 (*p -> c_ceclosefnx) (p);
3357 xlist = xpause = xtty = 0;
3359 for (bp = buffer; *cp; cp++)
3362 case 'a': /* additional arguments */
3368 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
3371 (void) sprintf (bp, "%s%s=\"%s\"", s, *ap, *ep);
3378 case 'd': /* content description */
3379 if (ct -> c_descr) {
3382 (void) strcpy (bp, s = trimcpy (ct -> c_descr));
3387 case 'e': /* exclusive execution */
3391 case 'F': /* %e and %f */
3394 case 'f': /* filename(s) */
3398 for (part = m -> mp_parts;
3400 part = part -> mp_next) {
3401 p = part -> mp_part;
3403 (void) sprintf (bp, "%s'%s'", s, p -> c_storage);
3410 case 'p': /* pause prior to displaying content */
3413 case 'l': /* display listing prior to displaying
3418 case 's': /* subtype */
3419 (void) strcpy (bp, ci -> ci_subtype);
3437 if (ct -> c_termproc) {
3440 (void) strcpy (term, buffer);
3441 (void) sprintf (buffer, ct -> c_termproc, term);
3444 return show_content_aux2 (ct, serial, alternate, NULLCP, buffer,
3445 NOTOK, xlist, xpause, 0, xtty);
3451 static int store_multi (ct, unused)
3456 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3457 register struct part *part;
3460 for (part = m -> mp_parts; part; part = part -> mp_next) {
3461 register CT p = part -> mp_part;
3465 && p -> c_ctstorefnx
3466 && (result = (*p -> c_ctstorefnx) (p, NULLCP)) == OK
3467 && ct -> c_subtype == MULTI_ALTERNATE)
3475 static int free_multi (ct)
3478 register struct multipart *m = (struct multipart *) ct -> c_ctparams;
3479 register struct part *part,
3486 free (m -> mp_start);
3488 free (m -> mp_stop);
3490 for (part = m -> mp_parts; part; part = next) {
3491 next = part -> mp_next;
3493 free_content (part -> mp_part);
3495 free ((char *) part);
3497 m -> mp_parts = NULL;
3500 ct -> c_ctparams = NULL;
3504 static struct k2v SubMultiPart[] = {
3505 "mixed", MULTI_MIXED,
3506 "alternative", MULTI_ALTERNATE,
3507 "digest", MULTI_DIGEST,
3508 "parallel", MULTI_PARALLEL,
3510 NULL, MULTI_UNKNOWN /* this one must be last! */
3513 static int InitMultiPart (ct)
3525 register struct multipart *m;
3526 register struct k2v *kv;
3527 register struct part *part,
3529 register CI ci = &ct -> c_ctinfo;
3533 ct -> c_ctshowfnx = NULL;
3534 ct -> c_ctstorefnx = NULL;
3536 if (ct -> c_encoding != CE_7BIT) {
3538 "\"%s/%s\" type in message %s should be encoded in 7bit",
3539 ci -> ci_type, ci -> ci_subtype, ct -> c_file);
3543 for (kv = SubMultiPart; kv -> kv_key; kv++)
3544 if (uleq (ci -> ci_subtype, kv -> kv_key))
3546 ct -> c_subtype = kv -> kv_value;
3548 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
3549 if (uleq (*ap, "boundary")) {
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);
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;
3569 for (cp = bp; isspace (*cp); 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);
3576 for (cp = bp, dp = cp + strlen (cp) - 1; dp > cp; dp--)
3580 m -> mp_start = concat (bp, "\n", NULLCP);
3581 m -> mp_stop = concat (bp, "--\n", NULLCP);
3583 if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
3584 advise (ct -> c_file, "unable to open for reading");
3588 (void) fseek (fp = ct -> c_fp, pos = ct -> c_begin, 0);
3591 next = &m -> mp_parts, part = NULL, inout = 1;
3592 while (fgets (buffer, sizeof buffer - 1, fp)) {
3596 pos += strlen (buffer);
3598 if (buffer[0] != '-' || buffer[1] != '-')
3602 if (strcmp (buffer + 2, m -> mp_start))
3606 if ((part = (struct part *) calloc (1, sizeof *part)) == NULL)
3607 adios (NULLCP, "out of memory");
3608 *next = part, next = &part -> mp_next;
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;
3618 part -> mp_part = p;
3619 (void) fseek (fp, pos = p -> c_begin, 0);
3623 if (strcmp (buffer + 2, m -> mp_start) == 0) {
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;
3636 if (strcmp (buffer + 2, m -> mp_stop) == 0)
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;
3644 if (p -> c_begin >= p -> c_end) {
3645 for (next = &m -> mp_parts;
3647 next = &((*next) -> mp_next))
3651 free ((char *) part);
3656 if (ct -> c_subtype == MULTI_ALTERNATE
3658 && m -> mp_parts -> mp_next) {
3660 register struct part **base,
3664 for (part = m -> mp_parts; part; part = part -> mp_next)
3666 if ((base = (struct part **) calloc ((unsigned) (i + 1), sizeof *base))
3668 adios (NULLCP, "out of memory");
3670 for (part = m -> mp_parts; part; part = part -> mp_next)
3674 next = &m -> mp_parts;
3675 for (bmp--; bmp >= base; bmp--) {
3677 *next = part, next = &part -> mp_next;
3681 free ((char *) base);
3687 char partnam[BUFSIZ];
3689 if (ct -> c_partno) {
3690 (void) sprintf (partnam, "%s.", ct -> c_partno);
3691 pp = partnam + strlen (partnam);
3696 for (part = m -> mp_parts, partnum = 1;
3698 part = part -> mp_next, partnum++) {
3699 p = part -> mp_part;
3701 (void) sprintf (pp, "%d", partnum);
3702 p -> c_partno = add (partnam, NULLCP);
3704 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK) {
3705 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
3711 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
3718 #define MESSAGE_UNKNOWN 0x00
3719 #define MESSAGE_RFC822 0x01
3720 #define MESSAGE_PARTIAL 0x02
3721 #define MESSAGE_EXTERNAL 0x03
3735 static int list_partial (ct, toplevel)
3739 register struct partial *p = (struct partial *) ct -> c_ctparams;
3741 (void) list_content (ct, toplevel);
3743 printf ("\t [message %s, part %d", p -> pm_partid, p -> pm_partno);
3745 printf (" of %d", p -> pm_maxno);
3753 static int ct_compar (a, b)
3757 register struct partial *am = (struct partial *) ((*a) -> c_ctparams);
3758 register struct partial *bm = (struct partial *) ((*b) -> c_ctparams);
3760 return (am -> pm_marked - bm -> pm_marked);
3766 static int store_partial (ct, unused)
3777 struct partial *qm = (struct partial *) ct -> c_ctparams;
3779 if (qm -> pm_stored)
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;
3787 if (!pm -> pm_stored
3788 && strcmp (qm -> pm_partid, pm -> pm_partid) == 0) {
3789 pm -> pm_marked = pm -> pm_partno;
3791 hi = pm -> pm_maxno;
3792 pm -> pm_stored = 1;
3796 pm -> pm_marked = 0;
3799 advise (NULLCP, "missing (at least) last part of multipart message");
3803 if ((base = (CT *) calloc ((unsigned) (i + 1), sizeof *base)) == NULL)
3804 adios (NULLCP, "out of memory");
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;
3811 if (pm -> pm_marked)
3817 qsort ((char *) base, i, sizeof *base, ct_compar);
3820 for (ctq = base; p = *ctq; ctq++) {
3821 register struct partial *pm = (struct partial *) p -> c_ctparams;
3823 if (pm -> pm_marked != cur) {
3824 if (pm -> pm_marked == cur - 1) {
3826 "duplicate part %d of %d part multipart message",
3827 pm -> pm_marked, hi);
3833 "missing %spart %d of %d part multipart message",
3834 cur != hi ? "(at least) " : "", cur, hi);
3847 if (store_content (ct, "") == NOTOK) {
3849 free ((char *) base);
3853 for (; p = *ctq; ctq++)
3854 if (store_content (p, ct -> c_storage) == NOTOK)
3857 free ((char *) base);
3862 static int free_partial (ct)
3865 register struct partial *p = (struct partial *) ct -> c_ctparams;
3871 free (p -> pm_partid);
3874 ct -> c_ctparams = NULL;
3887 char *eb_permission;
3901 static int openFile ();
3902 static int openFTP ();
3903 static int openMail ();
3905 /* NOTE WELL: si_key MUST NOT have value of NOTOK */
3907 static struct str2init str2methods[] = {
3909 "anon-ftp", 1, openFTP,
3911 "local-file", 0, openFile,
3912 "mail-server", 0, openMail,
3918 static int params_external (ct, composing)
3924 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
3925 register CI ci = &ct -> c_ctinfo;
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;
3932 for (s2i = str2methods; s2i -> si_key; s2i++)
3933 if (uleq (*ep, s2i -> si_key))
3935 if (!s2i -> si_key) {
3936 e -> eb_access = *ep;
3937 e -> eb_flags = NOTOK;
3938 p -> c_encoding = CE_EXTERNAL;
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)
3948 if (uleq (*ap, "name")) {
3952 if (uleq (*ap, "permission")) {
3953 e -> eb_permission = *ep;
3956 if (uleq (*ap, "site")) {
3960 if (uleq (*ap, "directory")) {
3964 if (uleq (*ap, "mode")) {
3968 if (uleq (*ap, "size")) {
3969 (void) sscanf (*ep, "%lu", &e -> eb_size);
3972 if (uleq (*ap, "server")) {
3973 e -> eb_server = *ep;
3976 if (uleq (*ap, "subject")) {
3977 e -> eb_subject = *ep;
3980 if (composing && uleq (*ap, "body")) {
3981 e -> eb_body = getcpy (*ep);
3986 if (!e -> eb_access) {
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);
3997 static int list_external (ct, toplevel)
4001 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4003 (void) list_content (ct, toplevel);
4006 printf ("\t retrieve %s\n", e -> eb_name);
4008 printf ("\t in directory %s\n", e -> eb_dir);
4010 printf ("\t from %s\n", e -> eb_site);
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);
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]");
4024 (void) list_content (e -> eb_content, 0);
4030 static int show_external (ct, serial, alternate)
4035 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4036 register CT p = e -> eb_content;
4038 if (!type_ok (p, 0))
4041 if (p -> c_ctshowfnx)
4042 return (*p -> c_ctshowfnx) (p, serial, alternate);
4044 content_error (NULLCP, p, "don't know how to display content");
4049 static int store_external (ct)
4053 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4054 register CT p = e -> eb_content;
4056 if (!type_ok (p, 1))
4059 p -> c_partno = ct -> c_partno;
4060 if (p -> c_ctstorefnx)
4061 result = (*p -> c_ctstorefnx) (p, NULLCP);
4062 p -> c_partno = NULL;
4068 static int free_external (ct)
4071 register struct exbody *e = (struct exbody *) ct -> c_ctparams;
4076 free_content (e -> eb_content);
4078 free (e -> eb_body);
4081 ct -> c_ctparams = NULL;
4085 static struct k2v SubMessage[] = {
4086 "rfc822", MESSAGE_RFC822,
4087 "partial", MESSAGE_PARTIAL,
4088 "external-body", MESSAGE_EXTERNAL,
4090 NULL, MESSAGE_UNKNOWN /* this one must be last! */
4093 static int InitMessage (ct)
4096 register struct k2v *kv;
4097 register CI ci = &ct -> c_ctinfo;
4099 if (ct -> c_encoding != CE_7BIT) {
4101 "\"%s/%s\" type in message %s should be encoded in 7bit",
4102 ci -> ci_type, ci -> ci_subtype, ct -> c_file);
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))
4112 switch (ct -> c_subtype = kv -> kv_value) {
4113 case MESSAGE_RFC822:
4114 ct -> c_showproc = add ("%pshow -file '%F'", NULLCP);
4117 case MESSAGE_PARTIAL:
4121 register struct partial *p;
4123 ct -> c_ctshowfnx = NULL;
4124 ct -> c_ctstorefnx = NULL;
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;
4131 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
4134 if (uleq (*ap, "id")) {
4135 p -> pm_partid = add (*ep, NULLCP);
4140 if (uleq (*ap, "number")) {
4141 if (sscanf (*ep, "%d", &p -> pm_partno) != 1
4142 || p -> pm_partno < 1) {
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);
4154 if (uleq (*ap, "total")) {
4155 if (sscanf (*ep, "%d", &p -> pm_maxno) != 1
4156 || p -> pm_maxno < 1)
4165 || (p -> pm_maxno && p -> pm_partno > p -> pm_maxno)) {
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);
4173 ct -> c_ctlistfnx = list_partial;
4174 ct -> c_ctstorefnx = store_partial;
4178 case MESSAGE_EXTERNAL:
4181 register struct exbody *e;
4185 ct -> c_ctshowfnx = NULL;
4186 ct -> c_ctstorefnx = NULL;
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;
4194 && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
4195 advise (ct -> c_file, "unable to open for reading");
4199 (void) fseek (fp = ct -> c_fp, ct -> c_begin, 0);
4201 if ((p = get_content (fp, ct -> c_file, 0)) == NULLCT) {
4202 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
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) {
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");
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);
4226 switch (cc = fread (bp, sizeof *bp, size, p -> c_fp)) {
4228 adios ("failed", "fread");
4231 adios (NULLCP, "unexpected EOF from fread");
4234 bp += cc, size -= cc;
4241 p -> c_end = p -> c_begin;
4243 (void) fclose (ct -> c_fp), ct -> c_fp = NULL;
4245 ct -> c_ctlistfnx = list_external;
4247 if (exresult == NOTOK)
4249 if (e -> eb_flags == NOTOK)
4252 if (e -> eb_name && autosw) {
4253 char *cp = e -> eb_name;
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);
4267 ct -> c_ctshowfnx = show_external;
4268 ct -> c_ctstorefnx = store_external;
4269 switch (p -> c_type) {
4274 if (p -> c_subtype != MESSAGE_RFC822)
4278 e -> eb_partno = ct -> c_partno;
4279 if (p -> c_ctinitfnx)
4280 (void) (*p -> c_ctinitfnx) (p);
4293 /*
\f APPLICATION */
4295 #define APPLICATION_UNKNOWN 0x00
4296 #define APPLICATION_OCTETS 0x01
4297 #define APPLICATION_POSTSCRIPT 0x02
4300 static int list_application (ct, toplevel)
4304 (void) list_content (ct, toplevel);
4308 register CI ci = &ct -> c_ctinfo;
4310 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
4311 printf ("\t %s=\"%s\"\n", *ap, *ep);
4318 static struct k2v SubApplication[] = {
4319 "octet-stream", APPLICATION_OCTETS,
4320 "postscript", APPLICATION_POSTSCRIPT,
4321 NULL, APPLICATION_UNKNOWN /* this one must be last! */
4324 static int InitApplication (ct)
4329 register struct k2v *kv;
4330 register CI ci = &ct -> c_ctinfo;
4332 ct -> c_ctlistfnx = list_application;
4334 for (kv = SubApplication; kv -> kv_key; kv++)
4335 if (uleq (ci -> ci_subtype, kv -> kv_key))
4338 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
4339 if (autosw && !ct -> c_storeproc && uleq (*ap, "name")) {
4342 if (*(cp = *ep) != '/'
4346 && !index (cp, '%'))
4347 ct -> c_storeproc = add (cp, NULLCP);
4350 if ((ct -> c_subtype = kv -> kv_value) == APPLICATION_OCTETS) {
4355 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++) {
4356 if (uleq (*ap, "type")) {
4357 if (!uleq (*ep, "tar"))
4364 if ((uleq (*ap, "conversions") || uleq (*ap, "x-conversions"))
4365 && (uleq (*ep, "compress") || uleq (*ep, "x-compress"))) {
4372 ct -> c_showproc = add (zP ? "%euncompress | tar tvf -"
4373 : "%etar tvf -", NULLCP);
4374 if (!ct -> c_storeproc)
4376 ct -> c_storeproc = add (zP ? "| uncompress | tar xvpf -"
4377 : "| tar xvpf -", NULLCP);
4378 ct -> c_umask = 0022;
4381 ct -> c_storeproc = add (zP ? "%m%P.tar.Z" : "%m%P.tar",
4402 static int list_encoding (ct)
4405 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4408 fprintf (stderr, " decoded fp 0x%x file \"%s\"\n", ce -> ce_fp,
4409 ce -> ce_file ? ce -> ce_file : "");
4415 static int close_encoding (ct)
4418 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4424 (void) fclose (ce -> ce_fp);
4430 static unsigned long size_encoding (ct)
4436 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4442 return (ct -> c_end - ct -> c_begin);
4445 if (ce -> ce_fp && fstat (fileno (ce -> ce_fp), &st) != NOTOK)
4446 return (long) st.st_size;
4449 return stat (ce -> ce_file, &st) != NOTOK ? (long) st.st_size : 0L;
4451 if (ct -> c_encoding == CE_EXTERNAL)
4455 if ((fd = (*ct -> c_ceopenfnx) (ct, &file)) == NOTOK)
4458 size = fstat (fd, &st) != NOTOK ? (long) st.st_size : 0L;
4460 (*ct -> c_ceclosefnx) (ct);
4466 static int free_encoding (ct, toplevel)
4470 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
4476 (void) fclose (ce -> ce_fp);
4480 if (ce -> ce_file) {
4481 if (ce -> ce_unlink)
4482 (void) unlink (ce -> ce_file);
4483 free (ce -> ce_file);
4488 ct -> c_ceparams = NULL;
4491 ct -> c_ceopenfnx = NULL;
4495 static init_encoding (ct, openfnx)
4499 register struct cefile *ce;
4501 if ((ce = (struct cefile *) calloc (1, sizeof *ce)) == NULL)
4502 adios (NULLCP, "out of memory");
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;
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
4536 static int openBase64 (ct, file)
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;
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");
4566 *file = ce -> ce_file;
4567 return fileno (ce -> ce_fp);
4570 ce -> ce_unlink = *file == NULL;
4571 if ((ce -> ce_fp = fopen (ce -> ce_file =
4572 add (*file ? *file : m_scratch ("", tmp),
4575 content_error (ce -> ce_file, ct,
4576 "unable to fopen for writing and reading");
4580 if ((len = ct -> c_end - ct -> c_begin) < 0)
4581 adios (NULLCP, "internal error(1)");
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");
4588 if (digested = ct -> c_digested)
4589 MD5Init (&mdContext);
4591 (void) lseek (fd = fileno (ct -> c_fp), (off_t)ct -> c_begin, 0);
4592 bitno = 18, bits = 0L, skip = 0;
4594 switch (cc = read (fd, buffer, sizeof buffer - 1)) {
4596 content_error (ct -> c_file, ct, "error reading from");
4600 content_error (NULLCP, ct, "premature eof");
4608 for (ep = (cp = buffer) + cc; cp < ep; cp++)
4615 || (value = b642nib[*cp & 0x7f]) > 0x3f) {
4618 "*cp=0x%x pos=%ld skip=%d\n", *cp,
4619 (long) lseek (fd, (off_t)0, 1) - (ep - cp),
4621 content_error (NULLCP, ct,
4622 "invalid BASE64 encoding -- continuing");
4626 bits |= value << bitno;
4628 if ((bitno -= 6) < 0) {
4629 (void) putc ((char) *b1, ce -> ce_fp);
4631 MD5Update (&mdContext, b1, 1);
4633 (void) putc ((char) *b2, ce -> ce_fp);
4635 MD5Update (&mdContext, b2, 1);
4637 (void) putc ((char) *b3, ce -> ce_fp);
4639 MD5Update (&mdContext, b3, 1);
4643 if (ferror (ce -> ce_fp)) {
4644 content_error (ce -> ce_file, ct,
4645 "error writing to");
4648 bitno = 18, bits = 0L, skip = 0;
4654 goto self_delimiting;
4660 fprintf (stderr, "premature ending (bitno %d)\n", bitno);
4662 content_error (NULLCP, ct, "invalid BASE64 encoding");
4666 (void) fseek (ct -> c_fp, 0L, 0);
4668 if (fflush (ce -> ce_fp)) {
4669 content_error (ce -> ce_file, ct, "error writing to");
4674 unsigned char digest[16];
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");
4683 fprintf (stderr, "content integrity confirmed\n");
4687 (void) fseek (ce -> ce_fp, 0L, 0);
4688 *file = ce -> ce_file;
4689 return fileno (ce -> ce_fp);
4692 free_encoding (ct, 0);
4698 static int InitBase64 (ct)
4701 return init_encoding (ct, openBase64);
4705 static int set_endian ()
4710 char c[sizeof (long)];
4714 endian = un.c[0] ? -1 : 1;
4716 fprintf (stderr, "%s endian architecture\n",
4717 endian > 0 ? "big" : "little");
4719 mm_charset = getenv ("MM_CHARSET");
4721 if ((cp = getenv ("MM_NOASK")) && strcmp (cp, "1") == 0) {
4722 nolist = 1, pausesw = 0;
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
4750 static int openQuoted (ct, file)
4760 char buffer[BUFSIZ];
4762 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
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");
4773 *file = ce -> ce_file;
4774 return fileno (ce -> ce_fp);
4777 ce -> ce_unlink = *file == NULL;
4778 if ((ce -> ce_fp = fopen (ce -> ce_file =
4779 add (*file ? *file : m_scratch ("", tmp),
4782 content_error (ce -> ce_file, ct,
4783 "unable to fopen for writing and reading");
4787 if ((len = ct -> c_end - ct -> c_begin) < 0)
4788 adios (NULLCP, "internal error(2)");
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");
4795 if (digested = ct -> c_digested)
4796 MD5Init (&mdContext);
4798 (void) fseek (ct -> c_fp, ct -> c_begin, 0);
4806 if (fgets (buffer, sizeof buffer - 1, ct -> c_fp) == NULL) {
4807 content_error (NULLCP, ct, "premature eof");
4811 if ((cc = strlen (buffer)) > len)
4815 for (ep = (cp = buffer) + cc - 1; cp <= ep; ep--)
4820 for (; cp < ep; cp++) {
4823 if (!isxdigit (*cp)) {
4825 dp = "expecting hexidecimal-digit";
4826 goto invalid_encoding;
4829 mask |= hex2nib[*cp & 0x7f];
4830 (void) putc (mask, ce -> ce_fp);
4832 MD5Update (&mdContext, &mask, 1);
4837 (void) putc (*cp, ce -> ce_fp);
4839 MD5Update (&mdContext, (unsigned char *) ":",
4844 if (!isxdigit (*cp))
4846 mask = hex2nib[*cp & 0x7f];
4851 if (ferror (ce -> ce_fp)) {
4852 content_error (ce -> ce_file, ct, "error writing to");
4861 if (*cp < '!' || *cp > '~') {
4863 dp = "expecting character in range [!..~]";
4866 i = strlen (invo_name) + 2;
4867 content_error (NULLCP, ct,
4868 "invalid QUOTED-PRINTABLE encoding -- %s,\n%*.*sbut got char 0x%x",
4876 (void) putc (*cp, ce -> ce_fp);
4879 MD5Update (&mdContext, (unsigned char *) "\r\n",2);
4881 MD5Update (&mdContext, (unsigned char *) cp, 1);
4883 if (ferror (ce -> ce_fp)) {
4884 content_error (ce -> ce_file, ct, "error writing to");
4890 if (*++cp != '\n') {
4899 content_error (NULLCP, ct,
4900 "invalid QUOTED-PRINTABLE encoding -- end-of-content while still quoting");
4903 (void) fseek (ct -> c_fp, 0L, 0);
4905 if (fflush (ce -> ce_fp)) {
4906 content_error (ce -> ce_file, ct, "error writing to");
4911 unsigned char digest[16];
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");
4920 fprintf (stderr, "content integrity confirmed\n");
4924 (void) fseek (ce -> ce_fp, 0L, 0);
4925 *file = ce -> ce_file;
4926 return fileno (ce -> ce_fp);
4929 free_encoding (ct, 0);
4935 static int InitQuoted (ct)
4938 return init_encoding (ct, openQuoted);
4943 static int open7Bit (ct, file)
4950 char buffer[BUFSIZ];
4951 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
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");
4961 *file = ce -> ce_file;
4962 return fileno (ce -> ce_fp);
4965 ce -> ce_unlink = *file == NULL;
4966 if ((ce -> ce_fp = fopen (ce -> ce_file =
4967 add (*file ? *file : m_scratch ("", tmp),
4970 content_error (ce -> ce_file, ct,
4971 "unable to fopen for writing and reading");
4975 if (ct -> c_type == CT_MULTIPART) {
4978 register CI ci = &ct -> c_ctinfo;
4982 fprintf (ce -> ce_fp, "%s: %s/%s", TYPE_FIELD, ci -> ci_type,
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);
4990 (void) sprintf (buffer, "%s=\"%s\"", *ap, *ep);
4992 if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
4993 (void) fputs ("\n\t", ce -> ce_fp);
4997 (void) putc (' ', ce -> ce_fp);
5000 fprintf (ce -> ce_fp, "%s", buffer);
5003 if (ci -> ci_comment) {
5004 if (len + 1 + (cc = 2 + strlen (ci -> ci_comment)) >= CPERLIN) {
5005 (void) fputs ("\n\t", ce -> ce_fp);
5009 (void) putc (' ', ce -> ce_fp);
5012 fprintf (ce -> ce_fp, "(%s)", ci -> ci_comment);
5015 fprintf (ce -> ce_fp, "\n");
5017 fprintf (ce -> ce_fp, "%s:%s", ID_FIELD, ct -> c_id);
5019 fprintf (ce -> ce_fp, "%s:%s", DESCR_FIELD, ct -> c_descr);
5020 fprintf (ce -> ce_fp, "\n");
5023 if ((len = ct -> c_end - ct -> c_begin) < 0)
5024 adios (NULLCP, "internal error(3)");
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");
5031 (void) lseek (fd = fileno (ct -> c_fp), (off_t) ct -> c_begin, 0);
5033 switch (cc = read (fd, buffer, sizeof buffer - 1)) {
5035 content_error (ct -> c_file, ct, "error reading from");
5039 content_error (NULLCP, ct, "premature eof");
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");
5053 (void) fseek (ct -> c_fp, 0L, 0);
5055 if (fflush (ce -> ce_fp)) {
5056 content_error (ce -> ce_file, ct, "error writing to");
5061 (void) fseek (ce -> ce_fp, 0L, 0);
5062 *file = ce -> ce_file;
5063 return fileno (ce -> ce_fp);
5066 free_encoding (ct, 0);
5072 static int Init7Bit (ct)
5075 if (init_encoding (ct, open7Bit) == NOTOK)
5077 ct -> c_cesizefnx = NULL;
5084 static int openExternal (ct, cb, ce, file, fd)
5091 char cachefile[BUFSIZ];
5094 (void) fseek (ce -> ce_fp, 0L, 0);
5097 *file = ce -> ce_file, *fd = fileno (ce -> ce_fp);
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");
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);
5117 admonish (cachefile, "unable to fopen for reading");
5125 static int openFile (ct, file)
5131 char cachefile[BUFSIZ];
5132 register struct exbody *e = (struct exbody *) ct -> c_ctextern;
5133 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5135 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5146 if (!e -> eb_name) {
5147 content_error (NULLCP, ct, "missing name parameter");
5151 ce -> ce_unlink = 0;
5152 if ((ce -> ce_fp = fopen (ce -> ce_file = getcpy (e -> eb_name), "r"))
5154 content_error (ce -> ce_file, ct, "unable to fopen for reading");
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) {
5164 mask = umask (cachetype ? ~m_gmprot () : 0222);
5165 if (fp = fopen (cachefile, "w")) {
5167 char buffer[BUFSIZ];
5168 FILE *gp = ce -> ce_fp;
5170 (void) fseek (gp, 0L, 0);
5172 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5174 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5178 admonish (ce -> ce_file, "error reading");
5179 (void) unlink (cachefile);
5183 admonish (cachefile, "error writing");
5184 (void) unlink (cachefile);
5188 (void) umask (mask);
5191 (void) fseek (ce -> ce_fp, 0L, 0);
5192 *file = ce -> ce_file;
5193 return fileno (ce -> ce_fp);
5198 static int openFTP (ct, file)
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;
5216 (void) sprintf (buffer, "%s-access-ftp", invo_name);
5217 if ((ftp = m_find (buffer)) && !*ftp)
5223 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5234 if (!e -> eb_name || !e -> eb_site) {
5235 content_error (NULLCP, ct, "missing %s parameter",
5236 e -> eb_name ? "site": "name");
5243 (void) pidcheck (pidwait (xpid, NOTOK));
5248 (void) sprintf (bp, "Retrieve %s", e -> eb_name);
5250 if (e -> eb_partno) {
5251 (void) sprintf (bp, " (content %s)", e -> eb_partno);
5254 (void) sprintf (bp, "\n using %sFTP from site %s",
5255 e -> eb_flags ? "anonymous " : "", e -> eb_site);
5257 if (e -> eb_size > 0) {
5258 (void) sprintf (bp, " (%lu octets)", e -> eb_size);
5261 (void) sprintf (bp, "? ");
5262 if (!getanswer (buffer))
5265 if (e -> eb_flags) {
5267 (void) sprintf (pass = buffer, "%s@@%s", getusr (), LocalName ());
5270 ruserpass (e -> eb_site, &username, &password);
5271 user = username, pass = password;
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;
5284 if ((ce -> ce_fp = fopen (ce -> ce_file =
5286 : caching ? cachefile
5287 : m_scratch ("", tmp),
5290 content_error (ce -> ce_file, ct,
5291 "unable to fopen for writing and reading");
5305 vec[vecp++] = r1bindex (ftp, '/');
5306 vec[vecp++] = e -> eb_site;
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";
5316 (void) fflush (stdout);
5318 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
5322 adios ("fork", "unable to");
5326 (void) close (fileno (ce -> ce_fp));
5327 (void) execvp (ftp, vec);
5328 fprintf (stderr, "unable to exec ");
5334 if (pidXwait (child_id, NULLCP)) {
5338 username = password = NULL;
5339 ce -> ce_unlink = 1;
5347 if (ftp_get (e -> eb_site, user, pass, e -> eb_dir, e -> eb_name,
5349 !e -> eb_mode || uleq (e -> eb_mode, "ascii"), 0)
5356 (void) chmod (cachefile, cachetype ? m_gmprot () : 0444);
5361 mask = umask (cachetype ? ~m_gmprot () : 0222);
5362 if (fp = fopen (cachefile, "w")) {
5364 FILE *gp = ce -> ce_fp;
5366 (void) fseek (gp, 0L, 0);
5368 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5370 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5374 admonish (ce -> ce_file, "error reading");
5375 (void) unlink (cachefile);
5379 admonish (cachefile, "error writing");
5380 (void) unlink (cachefile);
5384 (void) umask (mask);
5387 (void) fseek (ce -> ce_fp, 0L, 0);
5388 *file = ce -> ce_file;
5389 return fileno (ce -> ce_fp);
5394 static int openMail (ct, file)
5405 register struct exbody *e = (struct exbody *) ct -> c_ctextern;
5406 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5408 switch (openExternal (e -> eb_parent, e -> eb_content, ce, file, &fd)) {
5419 if (!e -> eb_server) {
5420 content_error (NULLCP, ct, "missing server parameter");
5427 (void) pidcheck (pidwait (xpid, NOTOK));
5432 (void) sprintf (bp, "Retrieve content");
5434 if (e -> eb_partno) {
5435 (void) sprintf (bp, " %s", e -> eb_partno);
5438 (void) sprintf (bp, " by asking %s\n\n%s\n? ",
5440 e -> eb_subject ? e -> eb_subject : e -> eb_body);
5441 if (!getanswer (buffer))
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;
5453 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
5457 advise ("fork", "unable to");
5461 (void) execvp (mailproc, vec);
5462 fprintf (stderr, "unable to exec ");
5468 if (pidXwait (child_id, NULLCP) == OK)
5469 advise (NULLCP, "request sent");
5473 ce -> ce_unlink = *file == NULL;
5474 if ((ce -> ce_fp = fopen (ce -> ce_file =
5475 add (*file ? *file : m_scratch ("", tmp),
5478 content_error (ce -> ce_file, ct,
5479 "unable to fopen for writing and reading");
5482 if (ct -> c_showproc)
5483 free (ct -> c_showproc);
5484 ct -> c_showproc = add ("true", NULLCP);
5486 (void) fseek (ce -> ce_fp, 0L, 0);
5487 *file = ce -> ce_file;
5488 return fileno (ce -> ce_fp);
5493 static int find_cache (ct, policy, writing, id, buffer)
5507 fprintf (stderr, "find_cache %s(%d) %s %s\n",
5508 caches[policy].sw, policy, writing ? "writing" : "reading",
5520 && find_cache_aux (writing ? 2 : 0, cache_private, id,
5522 if (access (buffer, 04) != NOTOK) {
5532 && find_cache_aux (writing ? 1 : 0, cache_public, id,
5534 if (writing || access (buffer, 04) != NOTOK) {
5544 && find_cache_aux (writing ? 2 : 0, cache_private, id,
5546 if (writing || access (buffer, 04) != NOTOK)
5553 if (status == OK && policy == CACHE_ASK) {
5560 (void) pidcheck (pidwait (xpid, NOTOK));
5566 (void) sprintf (bp, "Make cached, publically-accessible copy");
5570 (void) sprintf (bp, "Use cached copy");
5572 if (ct -> c_partno) {
5573 (void) sprintf (bp, " of content %s", ct -> c_partno);
5576 (void) stat (buffer, &st);
5577 (void) sprintf (bp, " (size %lu octets)",
5578 (unsigned long) st.st_size);
5581 (void) sprintf (bp, "\n in file %s? ", buffer);
5582 if (!getanswer (query))
5585 if (status == OK && writing) {
5586 if (*writing && index (buffer, '/'))
5587 (void) make_intermediates (buffer);
5588 (void) unlink (buffer);
5597 static int find_cache_aux (writing, directory, id, buffer)
5605 int usemap = index (id, '/') ? 1 : 0;
5609 char mapfile[BUFSIZ],
5614 static long clock = 0L;
5617 fprintf (stderr, "find_cache_aux %s usemap=%d\n", directory, usemap);
5619 (void) sprintf (mapfile, "%s/cache.map", directory);
5620 if (find_cache_aux2 (mapfile, id, mapname) == OK)
5628 (void) sprintf (buffer, "%s/%s", directory, id);
5632 if (!usemap && access (mapfile, 02) == NOTOK)
5645 (void) time (&clock);
5650 clock++, partno = 0;
5652 (void) sprintf (mapname, "%08x%04x%02x", clock & 0xffffffff,
5653 pid & 0xffff, partno++ & 0xff);
5655 fprintf (stderr, "creating mapping %s -> %s\n", mapname, id);
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);
5664 fp = lkfopen (mapfile, "a");
5667 (void) umask (mask);
5670 fprintf (fp, "%s: %s\n", mapname, id);
5671 (void) lkfclose (fp, mapfile);
5674 if (*mapname == '/')
5675 (void) strcpy (buffer, mapname);
5677 (void) sprintf (buffer, "%s/%s", directory, mapname);
5679 fprintf (stderr, "use %s\n", buffer);
5686 static int find_cache_aux2 (mapfile, id, mapname)
5696 if (!(fp = lkfopen (mapfile, "r")))
5699 for (state = FLD;;) {
5704 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
5708 (void) strcpy (mapname, name);
5709 if (state != FLDPLUS)
5712 cp = add (buf, NULLCP);
5713 while (state == FLDPLUS) {
5714 state = m_getfld (state, name, buf, sizeof buf, fp);
5722 fprintf (stderr, "compare %s to %s <- %s\n", id, dp,
5724 result = strcmp (id, dp);
5727 (void) lkfclose (fp, mapfile);
5730 if (state != FLDEOF)
5743 (void) lkfclose (fp, mapfile);
5749 static int cache_content (ct)
5755 register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
5758 advise (NULLCP, "no %s: field in %s", ID_FIELD, ct -> c_file);
5763 advise (NULLCP, "unable to decode %s", ct -> c_file);
5767 if (ct -> c_ceopenfnx == openMail) {
5768 advise (NULLCP, "a radish may no know Greek, but I do...");
5772 if (find_cache (NULLCT, wcachesw != CACHE_NEVER ? wcachesw : CACHE_ASK,
5773 &cachetype, ct -> c_id, cachefile)
5775 advise (NULLCP, "unable to cache %s's contents", ct -> c_file);
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,
5784 if (ce -> ce_file) {
5785 int mask = umask (cachetype ? ~m_gmprot () : 0222);
5789 fprintf (stderr, "caching by copying %s...\n", ce -> ce_file);
5792 if ((*ct -> c_ceopenfnx) (ct, &file) == NOTOK)
5795 if (fp = fopen (cachefile, "w")) {
5797 char buffer[BUFSIZ];
5798 FILE *gp = ce -> ce_fp;
5800 (void) fseek (gp, 0L, 0);
5802 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, gp))
5804 (void) fwrite (buffer, sizeof *buffer, cc, fp);
5808 admonish (ce -> ce_file, "error reading");
5809 (void) unlink (cachefile);
5813 admonish (cachefile, "error writing");
5814 (void) unlink (cachefile);
5819 content_error (cachefile, ct, "unable to fopen for writing");
5821 (void) umask (mask);
5825 fprintf (stderr, "in place caching...\n");
5828 if ((*ct -> c_ceopenfnx) (ct, &file) != NOTOK)
5829 (void) chmod (cachefile, cachetype ? m_gmprot () : 0444);
5833 /*
\f COMPOSITION */
5835 static char prefix[] = "----- =_aaaaaaaaaa";
5837 static char *free_file = NULL;
5838 static CT free_ct = NULL;
5841 static void build_comp (file)
5850 struct multipart *m;
5851 register struct part **pp;
5856 if ((in = fopen (file, "r")) == NULL)
5857 adios (file, "unable to open for reading");
5859 (void) umask (~m_gmprot ());
5861 (void) strcpy (tmpfil, m_scratch (file, invo_name));
5862 if ((out = fopen (tmpfil, "w")) == NULL)
5863 adios (tmpfil, "unable to open for writing");
5866 for (compnum = 1, state = FLD;;) {
5867 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
5873 if (uleq (name, VRSN_FIELD))
5874 adios (NULLCP, "draft shouldn't contain %s: field",
5877 if (uleq (name, TYPE_FIELD)) {
5878 while (state == FLDPLUS)
5879 state = m_getfld (state, name, buf, sizeof buf, in);
5883 if (uleq (name, ENCODING_FIELD))
5884 adios (NULLCP, "draft shouldn't contain %s: field",
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);
5893 if (state != FLDEOF)
5898 adios (NULLCP, "draft has empty body -- no directives!");
5903 (void) fseek (in, (long) (-strlen (buf)), 1);
5908 adios (NULLCP, "message format error in component #%d",
5912 adios (NULLCP, "getfld() returned %d", state);
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)
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);
5927 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
5928 adios (NULLCP, "out of memory");
5929 ct -> c_ctparams = (caddr_t) m;
5931 pp = &m -> mp_parts;
5932 while (fgetstr (buf, sizeof buf - 1, in)) {
5933 register struct part *part;
5936 if (user_content (in, file, buf, &p) == DONE) {
5937 admonish (NULLCP, "ignoring spurious #end");
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;
5952 adios (NULLCP, "no content directives found");
5953 if (!m -> mp_parts -> mp_next) {
5954 CT p = m -> mp_parts -> mp_part;
5956 m -> mp_parts -> mp_part = NULL;
5963 if ((cp = index (prefix, 'a')) == NULL)
5964 adios (NULLCP, "internal error(4)");
5966 while (compose_content (ct) == NOTOK)
5972 "giving up trying to find a unique delimiter string");
5976 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
5977 (void) output_content (ct, out);
5980 adios (tmpfil, "error writing to");
5982 (void) fclose (out);
5984 if (listsw && ct -> c_ctlistfnx) {
5988 printf (LSTFMT1, "msg", "part", "type/subtype", "size",
5992 savfile = ct -> c_file, ct -> c_file = file;
5993 (*ct -> c_ctlistfnx) (ct, 1);
5994 ct -> c_file = savfile;
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);
6015 static char *fgetstr (s, n, stream)
6023 for (ep = (cp = s) + n; cp < ep; ) {
6026 if (!fgets (cp, n, stream))
6027 return (cp != s ? s : NULL);
6028 if (cp == s && *cp != '#')
6031 cp += (i = strlen (cp)) - 1;
6032 if (i <= 1 || *cp-- != '\n' || *cp != '\\')
6034 *cp = 0, n -= (i - 2);
6042 static int user_content (in, file, buf, ctp)
6052 char buffer[BUFSIZ];
6053 struct multipart *m;
6054 register struct part **pp;
6056 register struct str2init *s2i;
6060 if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) {
6065 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
6066 adios (NULLCP, "out of memory");
6068 ci = &ct -> c_ctinfo;
6069 ct -> c_ctlistfnx = list_content;
6072 if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
6076 char content[BUFSIZ];
6079 ct -> c_file = add (m_tmpfil (invo_name), NULLCP);
6082 if ((out = fopen (ct -> c_file, "w")) == NULL)
6083 adios (ct -> c_file, "unable to open for writing");
6085 if (buf[0] == '#' && buf[1] == '<') {
6086 (void) strcpy (content, buf + 2);
6093 (void) strcpy (content, "text/plain");
6095 (void) strcpy (buffer, buf[0] != '#' ? buf : buf + 1);
6100 && uprf (buffer, DESCR_FIELD)
6101 && buffer[i = strlen (DESCR_FIELD)] == ':') {
6105 ct -> c_descr = add (buffer + i + 1, ct -> c_descr);
6106 if (!fgetstr (buffer, sizeof buffer - 1, in))
6108 "end-of-file after %s: field in plaintext",
6110 switch (buffer[0]) {
6118 "#-directive after %s: field in plaintext",
6127 if (headers != 1 || buffer[0] != '\n')
6128 (void) fputs (buffer, out);
6133 if ((cp = fgetstr (buffer, sizeof buffer - 1, in)) == NULL)
6135 if (buffer[0] == '#') {
6138 if (buffer[1] != '#')
6140 for (cp = (bp = buffer) + 1; *cp; cp++)
6147 ct -> c_end = ftell (out);
6148 (void) fclose (out);
6150 if (get_ctinfo (content, ct, inlineD) == NOTOK)
6152 for (s2i = str2cts; s2i -> si_key; s2i++)
6153 if (uleq (ci -> ci_type, s2i -> si_key))
6155 if (!s2i -> si_key && !uprf (ci -> ci_type, "X-"))
6157 switch (ct -> c_type = s2i -> si_val) {
6159 if (uleq (ci -> ci_subtype, "rfc822")) {
6160 ct -> c_encoding = CE_7BIT; /* XXX */
6166 "it makes sense to define a in-line %s content... NOT!",
6167 ct -> c_type == CT_MESSAGE ? "message" : "multipart");
6172 if (ct -> c_ctinitfnx = s2i -> si_init)
6173 (void) (*ct -> c_ctinitfnx) (ct);
6178 (void) fseek (in, pos, 0);
6182 extrnal = buf[1] == '@@';
6183 if (get_ctinfo (buf + (extrnal ? 2 : 1), ct, 1) == NOTOK)
6186 for (s2i = str2cts; s2i -> si_key; s2i++)
6187 if (uleq (ci -> ci_type, s2i -> si_key))
6189 if (s2i -> si_key) { /* type/subtype [file] */
6190 if (!ci -> ci_subtype)
6191 adios (NULLCP, "missing subtype in \"#%s\"", ci -> ci_type);
6193 switch (ct -> c_type = s2i -> si_val) {
6195 adios (NULLCP, "use \"#begin ... #end\" instead of \"#%s/%s\"",
6196 ci -> ci_type, ci -> ci_subtype);
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);
6208 "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"",
6209 ci -> ci_type, ci -> ci_subtype);
6213 if (ct -> c_ctinitfnx = s2i -> si_init)
6214 (void) (*ct -> c_ctinitfnx) (ct);
6219 register struct exbody *e;
6222 if (!ci -> ci_magic)
6223 adios (NULLCP, "need external information for \"#@@%s/%s\"",
6224 ci -> ci_type, ci -> ci_subtype);
6227 (void) sprintf (buffer, "message/external-body; %s",
6229 free (ci -> ci_magic), ci -> ci_magic = NULL;
6231 if ((ct = (CT) calloc (1, sizeof *ct)) == NULL)
6232 adios (NULLCP, "out of memory");
6234 ci = &ct -> c_ctinfo;
6235 ct -> c_ctlistfnx = list_content;
6236 if (get_ctinfo (buffer, ct, 0) == NOTOK)
6238 ct -> c_type = CT_MESSAGE;
6239 ct -> c_subtype = MESSAGE_EXTERNAL;
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;
6246 e -> eb_parent = ct;
6247 e -> eb_content = p;
6248 p -> c_ctextern = (caddr_t) e;
6250 ct -> c_ctlistfnx = list_external;
6252 if (params_external (ct, 1) == NOTOK)
6258 if (ci -> ci_magic) {
6259 if (*ci -> ci_magic == '|' || *ci -> ci_magic == '!') {
6260 for (cp = ci -> ci_magic + 1; isspace (*cp); cp++)
6263 adios (NULLCP, "empty pipe command for #%s directive",
6265 cp = add (cp, NULLCP);
6266 free (ci -> ci_magic);
6267 ci -> ci_magic = cp;
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;
6279 (void) sprintf (buffer, "%s-compose-%s/%s", invo_name, ci -> ci_type,
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");
6289 ci -> ci_magic = add (cp, NULLCP);
6294 adios (NULLCP, "externally definition not allowed for \"#%s\"",
6297 if (uleq (ci -> ci_type, "forw")) { /* #forw [+folder] [msgs] */
6300 *arguments[MAXARGS];
6303 if (ci -> ci_magic) {
6304 ap = brkstring (ci -> ci_magic, " ", "\n");
6305 ap = copyip (ap, arguments);
6308 arguments[0] = "cur", arguments[1] = NULL;
6311 for (ap = arguments; cp = *ap; ap++)
6312 if (*cp == '+' || *cp == '@@')
6314 adios (NULLCP, "only one folder per #forw directive");
6316 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
6318 folder = add (m_getfolder (), NULLCP);
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))
6329 if (mp -> numsel > 1) {
6330 if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK)
6332 ct -> c_type = CT_MULTIPART;
6333 ct -> c_subtype = MULTI_DIGEST;
6334 ct -> c_ctlistfnx = list_multi;
6335 ct -> c_ctfreefnx = free_multi;
6337 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
6338 adios (NULLCP, "out of memory");
6339 ct -> c_ctparams = (caddr_t) m;
6341 pp = &m -> mp_parts;
6345 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
6346 if (mp -> msgstats[msgnum] & SELECTED) {
6347 register struct part *part;
6350 if ((p = (CT) calloc (1, sizeof *p)) == NULL)
6351 adios (NULLCP, "out of memory");
6352 if (get_ctinfo ("message/rfc822", p, 0) == NOTOK)
6354 p -> c_type = CT_MESSAGE;
6355 p -> c_subtype = MESSAGE_RFC822;
6356 p -> c_ctlistfnx = list_content;
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;
6363 if (mp -> numsel > 1) {
6364 if ((part = (struct part *) calloc (1, sizeof *part))
6366 adios (NULLCP, "out of memory");
6367 *pp = part, pp = &part -> mp_next;
6368 part -> mp_part = p;
6379 if (uleq (ci -> ci_type, "end")) {
6385 if (!uleq (ci -> ci_type, "begin"))
6386 adios (NULLCP, "unknown directive \"#%s\"", ci -> ci_type);
6388 /* #begin [ alternative | parallel ] */
6389 if (!ci -> ci_magic)
6390 cp = SubMultiPart[(vrsn = MULTI_MIXED) - 1].kv_key;
6392 if (uleq (ci -> ci_magic, "alternative"))
6393 cp = SubMultiPart[(vrsn = MULTI_ALTERNATE) - 1].kv_key;
6395 if (uleq (ci -> ci_magic, "parallel"))
6396 cp = SubMultiPart[(vrsn = MULTI_PARALLEL) - 1].kv_key;
6398 if (uprf (ci -> ci_magic, "digest"))
6401 cp = ci -> ci_magic, vrsn = MULTI_UNKNOWN;
6403 (void) sprintf (buffer, "multipart/%s", cp);
6404 if (get_ctinfo (buffer, ct, 0) == NOTOK)
6406 ct -> c_type = CT_MULTIPART;
6407 ct -> c_subtype = vrsn;
6408 ct -> c_ctlistfnx = list_multi;
6409 ct -> c_ctfreefnx = free_multi;
6411 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
6412 adios (NULLCP, "out of memory");
6413 ct -> c_ctparams = (caddr_t) m;
6415 pp = &m -> mp_parts;
6416 while (fgetstr (buffer, sizeof buffer - 1, in)) {
6417 register struct part *part;
6420 if (user_content (in, file, buffer, &p) == DONE) {
6422 adios (NULLCP, "empty \"#begin ... #end\" sequence");
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;
6433 admonish (NULLCP, "premature end-of-file, missing #end");
6439 static void set_id (ct, top)
6445 static long clock = 0L;
6446 static char *msgfmt;
6449 (void) time (&clock);
6450 (void) sprintf (msgid, "<%d.%ld.%%d@@%s>\n", getpid (), clock,
6453 msgfmt = getcpy (msgid);
6455 (void) sprintf (msgid, msgfmt, top ? 0 : ++partno);
6456 ct -> c_id = getcpy (msgid);
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
6496 static int compose_content (ct)
6500 char buffer[BUFSIZ];
6501 register CI ci = &ct -> c_ctinfo;
6503 if (ct -> c_type == CT_MESSAGE && ct -> c_subtype == MESSAGE_EXTERNAL)
6506 switch (ct -> c_type) {
6511 char partnam[BUFSIZ];
6512 struct multipart *m = (struct multipart *) ct -> c_ctparams;
6513 register struct part *part;
6515 if (ct -> c_partno) {
6516 (void) sprintf (partnam, "%s.", ct -> c_partno);
6517 pp = partnam + strlen (partnam);
6522 for (part = m -> mp_parts, partnum = 1;
6524 part = part -> mp_next, partnum++) {
6525 register CT p = part -> mp_part;
6527 (void) sprintf (pp, "%d", partnum);
6528 p -> c_partno = add (partnam, NULLCP);
6530 if (compose_content (p) == NOTOK)
6534 if (rfc934sw && ct -> c_subtype == MULTI_DIGEST) {
6537 for (part = m -> mp_parts; part; part = part -> mp_next) {
6538 register CT p = part -> mp_part;
6540 if (p -> c_subtype != MESSAGE_RFC822) {
6546 ct -> c_rfc934 = is934;
6547 for (part = m -> mp_parts; part; part = part -> mp_next) {
6548 register CT p = part -> mp_part;
6550 if (p -> c_rfc934 = is934)
6556 ct -> c_end = (partnum = strlen (prefix) + 2) + 2;
6560 for (part = m -> mp_parts; part; part = part -> mp_next)
6561 ct -> c_end += part -> mp_part -> c_end + partnum;
6568 if (!ct -> c_file) {
6577 if (!(cp = ci -> ci_magic))
6578 adios (NULLCP, "internal error(5)");
6580 ct -> c_file = add (m_tmpfil (invo_name), NULLCP);
6585 for (bp = buffer; *cp; cp++)
6588 case 'a': /* additional arguments */
6593 for (ap = ci -> ci_attrs, ep = ci -> ci_values;
6596 (void) sprintf (bp, "%s%s=\"%s\"", s,
6604 case 'F': /* %f, and stdout is not-redirected */
6607 case 'f': /* filename */
6608 (void) sprintf (bp, "%s", ct -> c_file);
6611 case 's': /* subtype */
6612 (void) strcpy (bp, ci -> ci_subtype);
6631 printf ("composing content %s/%s from command\n\t%s\n",
6632 ci -> ci_type, ci -> ci_subtype, buffer);
6633 (void) fflush (stdout);
6640 if ((out = fopen (ct -> c_file, "w")) == NULL)
6641 adios (ct -> c_file, "unable to open for writing");
6643 for (i = 0; (child_id = vfork ()) == NOTOK && i > 5; i++)
6647 adios ("fork", "unable to fork");
6652 (void) dup2 (fileno (out), 1);
6653 (void) close (fileno (out));
6654 (void) execvp ("/bin/sh", vec);
6655 fprintf (stderr, "unable to exec ");
6661 (void) fclose (out);
6662 if (pidXwait (child_id, NULLCP))
6667 if (listsw && ct -> c_end == 0L) {
6670 if (stat (ct -> c_file, &st) != NOTOK)
6671 ct -> c_end = (long) st.st_size;
6673 if (ct -> c_type != CT_TEXT && ct -> c_type != CT_APPLICATION)
6685 if ((in = fopen (ct -> c_file, "r")) == NULL)
6686 adios (ct -> c_file, "unable to open for reading");
6688 len = strlen (prefix);
6690 switch (ct -> c_type) {
6692 charset = ct -> c_ctparams ? 0 : -1;
6693 linelen = ct -> c_subtype == TEXT_PLAIN ? 0 : -1;
6696 case CT_APPLICATION:
6697 charset = linelen = ct -> c_encoding ? 0 : -1;
6701 charset = linelen = 0;
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;
6713 && !ebcdicsafe[*cp & 0xff])
6716 if ((linelen == -1) && (cp - buffer > CPERLIN + 1))
6718 if (result == NOTOK)
6722 if ((linelen == -1) && (strlen (buffer) > CPERLIN + 1))
6724 if (result == NOTOK)
6727 if (linelen == -1) {
6728 if ((cp = buffer + strlen (buffer) - 2) > buffer
6732 if ((*(cp = buffer) == '.')
6733 || (strncmp (cp, "From ",
6734 sizeof "From " -1) == 0))
6738 if (buffer[0] == '-' && buffer[1] == '-') {
6739 for (cp = buffer + strlen (buffer) - 1;
6745 if (strncmp (buffer + 2, prefix, len) == 0
6746 && isdigit (buffer[2 + len])) {
6748 if (charset != -1 && linelen != -1)
6753 if (ct -> c_type == CT_APPLICATION && !ct -> c_encoding)
6754 ct -> c_encoding = linelen == -1
6755 && charset != CHARSET_UNKNOWN
6758 != APPLICATION_POSTSCRIPT
6759 ? CE_BASE64 : CE_QUOTED;
6760 if (ct -> c_type == CT_TEXT && !ct -> c_ctparams) {
6763 register struct text *t;
6765 if (charset == CHARSET_UNKNOWN && mm_charset)
6769 charset = CHARSET_USASCII;
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;
6778 switch (t -> tx_charset = charset) {
6779 case CHARSET_USASCII:
6780 *ap = add ("charset=us-ascii", NULLCP);
6783 case CHARSET_UNKNOWN:
6785 *ap = add ("charset=x-unknown", NULLCP);
6789 *ap = concat ("charset=", mm_charset, NULLCP);
6792 cp = index (*ap++, '=');
6797 if (ct -> c_type == CT_TEXT && ct -> c_subtype != TEXT_PLAIN)
6798 ct -> c_encoding = linelen == -1 ? CE_7BIT : CE_QUOTED;
6811 static int output_content (ct, out)
6820 char buffer[BUFSIZ];
6821 register CI ci = &ct -> c_ctinfo;
6823 if (ct -> c_type == CT_MULTIPART) {
6825 static int encl = 0;
6827 ap = ci -> ci_attrs, ep = ci -> ci_values;
6829 (void) sprintf (buffer, "boundary=%s%d", prefix, encl++);
6830 cp = index (*ap++ = add (buffer, NULLCP), '=');
6836 if (ct -> c_type == CT_MESSAGE && ct -> c_rfc934)
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"))
6850 (void) putc (';', out);
6853 (void) sprintf (buffer, "%s=\"%s\"", *ap, *ep);
6855 if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
6856 (void) fputs ("\n\t", out);
6860 (void) putc (' ', out);
6863 fputs (buffer, out);
6866 if (ci -> ci_comment) {
6867 if (len + 1 + (cc = 2 + strlen (ci -> ci_comment)) >= CPERLIN) {
6868 (void) fputs ("\n\t", out);
6872 (void) putc (' ', out);
6875 fprintf (out, "(%s)", ci -> ci_comment);
6878 (void) putc ('\n', out);
6880 fprintf (out, "%s: %s", ID_FIELD, ct -> c_id);
6882 fprintf (out, "%s: %s", DESCR_FIELD, ct -> c_descr);
6885 if (ct -> c_ctextern)
6887 switch (ct -> c_type) {
6890 struct multipart *m = (struct multipart *) ct -> c_ctparams;
6891 register struct part *part;
6894 (void) putc ('\n', out);
6896 for (part = m -> mp_parts; part; part = part -> mp_next) {
6897 register CT p = part -> mp_part;
6899 fprintf (out, "\n--%s\n", ci -> ci_values[0]);
6900 (void) output_content (p, out);
6903 fprintf (out, "\n--%s--\n", ci -> ci_values[0]);
6908 if (ct -> c_ctparams
6909 && ((struct text *) ct -> c_ctparams) -> tx_charset
6910 != CHARSET_USASCII) {
6913 writeDigest (ct, out, 1);
6914 fprintf (out, "%s: %s\n\n", ENCODING_FIELD,
6915 "quoted-printable");
6916 (void) writeQuoted (ct, out);
6919 if ((ct -> c_subtype != TEXT_PLAIN && ct -> c_encoding != CE_7BIT)
6921 goto quoted_printable;
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;
6931 (void) output_content (e -> eb_content, out);
6936 for (cp = e -> eb_body; *cp; cp++) {
6937 CT ct2 = e -> eb_content;
6938 CI ci2 = &ct2 -> c_ctinfo;
6944 char *dp = trimcpy (ct2 -> c_id);
6946 (void) fputs (dp, out);
6952 for (ap = ci2 -> ci_attrs,
6953 ep = ci2 -> ci_values;
6956 if (uleq (*ap, "name")) {
6957 fprintf (out, "%s", *ep);
6963 fprintf (out, "%s/%s", ci2 -> ci_type,
6965 for (ap = ci2 -> ci_attrs,
6966 ep = ci2 -> ci_values;
6969 fprintf (out, "; %s=\"%s\"", *ap, *ep);
6973 (void) putc ('\n', out);
6977 (void) putc ('\t', out);
6989 (void) putc ('\\', out);
6993 (void) putc (*cp, out);
6999 (void) write7Bit (ct, out);
7002 case CT_APPLICATION:
7003 switch (ct -> c_encoding) {
7008 goto quoted_printable;
7017 writeDigest (ct, out, 0);
7018 fprintf (out, "%s: %s\n\n", ENCODING_FIELD, "base64");
7019 (void) writeBase64 (ct, out);
7028 static int write7Bit (ct, out)
7036 if ((in = fopen (ct -> c_file, "r")) == NULL)
7037 adios (ct -> c_file, "unable to open for reading");
7040 while (fgets (buffer, sizeof buffer - 1, in)) {
7041 c = buffer[strlen (buffer) - 1];
7042 (void) fputs (buffer, out);
7045 (void) putc ('\n', out);
7054 static int writeQuoted (ct, out)
7063 if ((in = fopen (ct -> c_file, "r")) == NULL)
7064 adios (ct -> c_file, "unable to open for reading");
7066 while (fgets (buffer, sizeof buffer - 1, in)) {
7069 cp = buffer + strlen (buffer) - 1;
7070 if ((c = *cp) == '\n')
7073 if ((*(cp = buffer) == '.')
7074 || (strncmp (cp, "From ", sizeof "From " - 1) == 0)) {
7075 (void) fprintf (out, "=%02X", *cp++ & 0xff);
7081 if (n > CPERLIN - 3) {
7082 (void) fputs ("=\n", out);
7089 (void) putc (*cp, out);
7096 || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
7098 (void) putc (*cp, out);
7104 (void) fprintf (out, "=%02X", *cp & 0xff);
7111 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
7112 (void) fputs ("=\n", out);
7114 (void) putc ('\n', out);
7117 (void) fputs ("=\n", out);
7127 static char nib2b64[0x40+1] =
7128 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7131 static int writeBase64 (ct, out)
7138 if ((in = fopen (ct -> c_file, "r")) == NULL)
7139 adios (ct -> c_file, "unable to open for reading");
7141 result = writeBase64aux (in, out);
7149 static int writeBase64aux (in, out)
7158 while ((cc = fread (inbuf, sizeof *inbuf, sizeof inbuf, in)) > 0) {
7163 if (cc < sizeof inbuf) {
7165 if (cc < sizeof inbuf - 1)
7168 bits = (inbuf[0] & 0xff) << 16;
7169 bits |= (inbuf[1] & 0xff) << 8;
7170 bits |= inbuf[2] & 0xff;
7172 for (bp = outbuf + sizeof outbuf; bp > outbuf; bits >>= 6)
7173 *--bp = nib2b64[bits & 0x3f];
7174 if (cc < sizeof inbuf) {
7176 if (cc < sizeof inbuf - 1)
7180 (void) fwrite (outbuf, sizeof *outbuf, sizeof outbuf, out);
7182 if (cc < sizeof inbuf) {
7183 (void) putc ('\n', out);
7189 (void) putc ('\n', out);
7193 (void) putc ('\n', out);
7200 static int writeDigest (ct, out, asciiP)
7206 char buffer[BUFSIZ];
7207 register unsigned char *dp;
7208 unsigned char digest[16];
7212 if ((in = fopen (ct -> c_file, "r")) == NULL)
7213 adios (ct -> c_file, "unable to open for reading");
7215 MD5Init (&mdContext);
7217 while (fgets (buffer, sizeof buffer - 1, in)) {
7221 cp = buffer + strlen (buffer) - 1;
7222 if ((c = *cp) == '\n')
7225 MD5Update (&mdContext, (unsigned char *) buffer,
7226 (unsigned int) strlen (buffer));
7229 MD5Update (&mdContext, (unsigned char *) "\r\n", 2);
7233 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, in)) > 0)
7234 MD5Update (&mdContext, (unsigned char *) buffer,
7236 MD5Final (digest, &mdContext);
7240 fprintf (stderr, "MD5 digest=");
7241 for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
7244 fprintf (stderr, "%02x", *dp & 0xff);
7245 fprintf (stderr, "\n");
7250 fprintf (out, "%s: ", MD5_FIELD);
7251 for (dp = digest, cc = sizeof digest / sizeof digest[0]; cc > 0; cc -= 3) {
7256 bits = (*dp++ & 0xff) << 16;
7258 bits |= (*dp++ & 0xff) << 8;
7260 bits |= *dp++ & 0xff;
7263 for (bp = outbuf + sizeof outbuf; bp > outbuf; bits >>= 6)
7264 *--bp = nib2b64[bits & 0x3f];
7271 (void) fwrite (outbuf, sizeof *outbuf, sizeof outbuf, out);
7273 fprintf (out, "\n");
7278 static int readDigest (ct, cp)
7286 register unsigned char *dp;
7287 unsigned char value,
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];
7294 bitno = 18, bits = 0L, skip = 0;
7295 for (ep = (dp = ct -> c_digest)
7296 + sizeof ct -> c_digest / sizeof ct -> c_digest[0];
7303 || (value = b642nib[*cp & 0x7f]) > 0x3f) {
7305 fprintf (stderr, "invalid BASE64 encoding\n");
7309 bits |= value << bitno;
7311 if ((bitno -= 6) < 0) {
7312 if (dp + (3 - skip) > ep)
7313 goto invalid_digest;
7320 bitno = 18, bits = 0L, skip = 0;
7326 goto self_delimiting;
7331 fprintf (stderr, "premature ending (bitno %d)\n", bitno);
7341 fprintf (stderr, "invalid MD5 digest (got %d octets)\n",
7349 fprintf (stderr, "MD5 digest=");
7350 for (dp = ct -> c_digest; dp < ep; dp++)
7351 fprintf (stderr, "%02x", *dp & 0xff);
7352 fprintf (stderr, "\n");
7360 #include "../zotnet/tws.h"
7363 static int via_mail (mailsw, subjsw, parmsw, descsw, cmntsw, slowsw, fromsw)
7377 char tmpfil[BUFSIZ];
7381 (void) umask (~m_gmprot ());
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);
7388 if (!index (mailsw, '@@'))
7389 mailsw = concat (mailsw, "@@", LocalName (), NULLCP);
7390 fprintf (fp, "To: %s\n", mailsw);
7393 fprintf (fp, "Subject: %s\n", subjsw), nlines++;
7395 if (!index (fromsw, '@@'))
7396 fromsw = concat (fromsw, "@@", LocalName (), NULLCP);
7397 fprintf (fp, "From: %s\n", fromsw), nlines++;
7399 fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE), nlines++;
7400 offset = ftell (fp);
7401 fprintf (fp, "%s: application/octet-stream", TYPE_FIELD);
7403 fprintf (fp, "; %s", parmsw);
7405 fprintf (fp, "\n\t(%s)", cmntsw), nlines++;
7407 fprintf (fp, "\n%s: %s", DESCR_FIELD, descsw), nlines++;
7408 fprintf (fp, "\n%s: %s\n\n", ENCODING_FIELD, "base64"), nlines += 2;
7410 adios (tmpfil, "error writing to");
7413 (void) writeBase64aux (stdin, fp);
7415 adios (tmpfil, "error writing to");
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;
7423 status = via_post (tmpfil, 0);
7427 char buffer[BUFSIZ],
7431 printf ("sending binary image as %d partial messages\n", nparts);
7432 (void) fflush (stdout);
7435 (void) time (&clock);
7436 (void) sprintf (msgid, "<%d.%ld@@%s>", getpid (), clock, LocalName ());
7438 (void) fseek (fp, offset, 0);
7439 for (partno = 1; partno <= nparts; partno++) {
7441 char tmpdrf[BUFSIZ];
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);
7449 fprintf (out, "To: %s\n", mailsw);
7451 fprintf (out, "Subject: %s\n", subjsw);
7452 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
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,
7460 fprintf (out, "Message-ID: %s\n", msgid);
7462 for (lineno = LPERMSG; lineno > 0; lineno--) {
7463 if (!fgets (buffer, sizeof buffer, fp)) {
7464 if (partno == nparts)
7466 adios (NULLCP, "premature eof");
7469 (void) fputs (buffer, out);
7471 offset = ftell (fp);
7474 adios (tmpdrf, "error writing to");
7476 (void) fclose (out);
7478 status = via_post (tmpdrf, slowsw == 0);
7479 (void) unlink (tmpdrf);
7483 if (slowsw > 0 && partno < nparts) {
7485 printf ("pausing %d seconds before sending part %d...\n",
7486 slowsw, partno + 1);
7487 (void) fflush (stdout);
7490 sleep ((unsigned) slowsw);
7496 (void) unlink (tmpfil);
7498 done (status ? 1 : 0);
7503 static int via_post (file, queued)
7510 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
7514 adios ("fork", "unable to");
7518 (void) execlp (postproc, r1bindex (postproc, '/'), file,
7519 queued ? "-queued" : NULLCP, NULLCP);
7520 fprintf (stderr, "unable to exec ");
7526 return pidXwait (child_id, postproc);
7539 free_content (*ctp);
7541 free_content (free_ct);
7543 (void) unlink (free_file);
7549 static int pidcheck (status)
7552 if ((status & 0xff00) == 0xff00 || (status & 0x007f) != SIGQUIT)
7555 (void) unlink ("core");
7557 (void) fflush (stdout);
7559 (void) fflush (stderr);
7574 static char ident[] = "@@(#)$Id: mhn.c,v 2.40 1995/12/06 21:03:37 jromine Exp jromine $";
7580 ct -> c_type = s2i -> si_value;
7583 ct -> c_encoding = s2i -> si_value;
7586 e -> eb_flags = s2i -> si_value;
7589 switch (ct -> c_type = s2i -> si_value) {
7592 switch (ct -> c_type = s2i -> si_value) {
7603 static char ident[] = "@@(#)$Id: mhn.c,v 2.39 1995/12/06 21:02:05 jromine Exp jromine $";
7613 @enhancements for quoted-printable from mtr
7618 static char ident[] = "@@(#)$Id: mhn.c,v 2.38 1995/12/06 20:55:31 jromine Exp jromine $";
7621 if (ct -> c_subtype == MULTI_ALTERNATE && m -> mp_parts -> mp_next) {
7632 static char ident[] = "@@(#)$Id: mhn.c,v 2.37 1995/12/06 19:20:22 jromine Exp jromine $";
7636 && (cp = buffer + strlen (buffer) - 2) > buffer
7641 if (strncmp (cp = buffer, "From ", sizeof "From " - 1) == 0) {
7652 static char ident[] = "@@(#)$Id: mhn.c,v 2.36 1994/04/21 19:23:38 jromine Exp jromine $";
7654 if (p -> c_type == CT_MESSAGE
7655 && p -> c_subtype != MESSAGE_EXTERNAL
7657 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
7668 static char ident[] = "@@(#)$Id: mhn.c,v 2.35 1993/10/26 22:17:44 jromine Exp jromine $";
7675 e -> eb_mode && uleq (e -> eb_mode, "ascii"), 0)
7681 @change to re-sync with mtr's version
7686 static char ident[] = "@@(#)$Id: mhn.c,v 2.34 1993/10/26 20:15:00 jromine Exp jromine $";
7710 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7713 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7716 if (autosw && !ct -> c_storeproc && uleq (*ap, "x-name")) {
7719 if ((cp = getenv ("MM_NOASK")) && strcmp (cp, "1") == 0)
7720 nolist = 1, listsw = pausesw = 0;
7723 if (ct -> c_type != CT_TEXT
7724 && !(ct -> c_type == CT_APPLICATION
7725 && ct -> c_subtype == APPLICATION_POSTSCRIPT))
7728 ? CE_7BIT : CE_QUOTED;
7731 if (ct -> c_subtype == APPLICATION_POSTSCRIPT) {
7732 if (ct -> c_encoding == CE_7BIT)
7735 goto quoted_printable;
7741 @fixes from mtr -- content-id?
7746 static char ident[] = "@@(#)$Id: mhn.c,v 2.33 1993/10/26 20:11:27 jromine Exp jromine $";
7750 for (cp = file; cp = index (cp, '/'); cp++) {
7758 content_error (NULLCP, ct,
7759 "empty body for access-type=mail-server");
7765 && find_cache_aux (writing, cache_private, id,
7768 && find_cache_aux (writing, cache_public, id,
7771 && find_cache_aux (writing, cache_private, id,
7779 (void) sprintf (mapname, "%s/%s", directory, invo_name);
7780 (void) strcpy (mapname, r1bindex (m_scratch (mapname, invo_name), '/'));
7784 if (!(fp = fopen (mapfile, "a")))
7790 if (!(fp = fopen (mapfile, "r")))
7801 if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK)
7803 ct -> c_type = CT_MULTIPART;
7804 ct -> c_subtype = MULTI_DIGEST;
7805 ct -> c_ctlistfnx = list_multi;
7806 ct -> c_ctfreefnx = free_multi;
7809 if ((m = (struct multipart *) calloc (1, sizeof *m)) == NULL)
7810 adios (NULLCP, "out of memory");
7811 ct -> c_ctparams = (caddr_t) m;
7814 pp = &m -> mp_parts;
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;
7828 @minor fixup in DESCR/ID_FIELD
7833 static char ident[] = "@@(#)$Id: mhn.c,v 2.32 1993/10/26 15:56:01 jromine Exp jromine $";
7839 fprintf (out, "%s", buffer);
7842 fprintf (out, "\n");
7845 fprintf (out, "\n");
7848 if (ct -> c_subtype != TEXT_PLAIN && ct -> c_encoding != CE_7BIT)
7851 goto quoted_printable;
7854 fprintf (out, "\n");
7858 fprintf (out, "\n%s\n", e -> eb_body);
7864 @formatting fixup (part 2)
7869 static char ident[] = "@@(#)$Id: mhn.c,v 2.28 1993/10/25 19:58:19 jromine Exp jromine $";
7872 fprintf (ce -> ce_fp, "%s: %s", ID_FIELD, ct -> c_id);
7875 fprintf (ce -> ce_fp, "%s: %s", DESCR_FIELD, ct -> c_descr);
7888 (void) umask (mask);
7895 @cache changes (part 2)
7900 ce -> ce_unlink = 0;
7914 if (fp = fopen (cachefile, "w")) {
7918 (void) fseek (gp, 0L, 0);
7921 (void) fwrite (buffer, sizeof *buffer, cc, fp);
7926 admonish (ce -> ce_file, "error reading");
7927 (void) unlink (cachefile);
7931 if (*file == NULL) {
7932 ce -> ce_unlink = 0;
7939 admonish (cachefile, "error writing");
7940 (void) unlink (cachefile);
7947 @add -nocache, -rcache, -wcache
7952 #define CACHE_ALWAYS 0
7956 #define CACHE_NEVER 2
7960 static int cachesw = CACHE_ASK;
7974 switch (cachesw = smatch (cp, caches)) {
7977 cache = cachesw != CACHE_NEVER ? m_find (buf) : NULLCP;
7981 if (!listsw && !showsw && !storesw)
7990 list_content (ct, -1);
7994 if ((len = ct -> c_end - ct -> c_begin) < 0)
7995 adios (NULLCP, "internal error(3)");
8009 (void) pidcheck (pidwait (xpid, NOTOK));
8013 if (cache && (id = cb -> c_id)) {
8014 char buffer[BUFSIZ];
8016 (void) sprintf (buffer, "%s/%s", cache, id = trimcpy (id));
8019 id = getcpy (buffer);
8020 if (ce -> ce_fp = fopen (id, "r")) {
8024 if (cachesw == CACHE_ALWAYS)
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);
8032 if (ct -> c_partno) {
8033 (void) sprintf (bp, " (content %s)", ct -> c_partno);
8036 (void) sprintf (bp, "? ");
8037 if (getanswer (buffer)) {
8045 (void) fclose (ce -> ce_fp), ce -> ce_fp = NULL;
8056 && (id = e -> eb_content -> c_id)
8057 && (!e -> eb_permission
8058 || !uleq (e -> eb_permission, "read-write"))) {
8059 char buffer[BUFSIZ];
8061 (void) sprintf (buffer, "Make cached, publically-accessible copy of %s? ",
8063 if (cachesw == CACHE_ALWAYS || getanswer (buffer)) {
8065 char cachefile[BUFSIZ];
8068 (void) sprintf (cachefile, "%s/%s", cache, id = trimcpy (id));
8071 mask = umask (0022);
8074 register FILE *gp = ce -> ce_fp;
8077 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer,
8093 (void) sprintf (buffer,
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);
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));
8117 (void) chmod (cachefile, 0644);
8123 mask = umask (0022);
8126 register FILE *gp = ce -> ce_fp;
8129 while (fgets (buffer, sizeof buffer - 1, gp))
8130 (void) fputs (buffer, fp);
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? ",
8144 result = getanswer (bp);
8151 if (e -> eb_subject)
8152 vec[vecp++] = "mail-server request";
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,
8162 vec[vecp++] = buffer;
8165 vec[vecp++] = "mail-server request";
8172 @fixes from mtr (20-sep-93)
8177 static char ident[] = "@@(#)$Id: mhn.c,v 2.27 1993/10/25 19:32:05 jromine Exp jromine $";
8198 #define FILESW 8 /* interface from show */
8234 #define NRFC934SW 20
8240 #define NSERIALSW 22
8304 @fixes from mtr: add MHN_SILENT, changes something in printing
8310 static char ident[] = "@@(#)$Id: mhn.c,v 2.26 1993/09/09 22:38:43 jromine Exp jromine $";
8319 vec[vecp++] = r1bindex (mhlproc, '/');
8320 vec[vecp++] = "-form";
8321 vec[vecp++] = formsw;
8322 vec[vecp++] = "-nobody";
8323 vec[vecp++] = ct -> c_file;
8325 vec[vecp++] = "-nomoreproc";
8328 vec[vecp++] = "-moreproc";
8329 vec[vecp++] = progsw;
8334 (void) fflush (stdout);
8336 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
8340 adios ("fork", "unable to");
8345 (void) execvp (mhlproc, vec);
8346 fprintf (stderr, "unable to exec ");
8359 if (getenv ("MHN_SILENT"))
8370 static char ident[] = "@@(#)$Id: mhn.c,v 2.25 1993/09/01 21:46:58 jromine Exp jromine $";
8377 (*ct -> c_ctlistfnx) (ct, -1);
8388 @fix from mrose for quoted-printable 8-bit chars
8393 static char ident[] = "@@(#)$Id: mhn.c,v 2.24 1993/09/01 20:50:03 jromine Exp jromine $";
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 ();
8402 static int init_encoding(), type_ok(), copy_some_headers(), set_endian();
8405 static int write7Bit(), writeQuoted(), writeBase64(), writeBase64aux();
8408 static int via_mail(), via_post(), pidcheck();
8414 if (type_ok (ct) && ct -> c_ctlistfnx) {
8417 if (type_ok (ct) && ct -> c_ctstorefnx) {
8420 if (type_ok (ct) && ct -> c_ctlistfnx) {
8426 static int show_content_aux ();
8437 exec[BUFSIZ + sizeof "exec "];
8444 (void) (*ct -> c_ceclosefnx) (ct);
8450 (void) fflush (stdout);
8452 fprintf (stderr, "storing message %s", ct -> c_file);
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] != '/'
8459 : ct -> c_storage + cwdlen + 1);
8466 static int part_ok (ct)
8470 if (ct -> c_type == CT_MULTIPART || npart == 0)
8473 static int type_ok (ct)
8477 if (ct -> c_type == CT_MULTIPART || ntype == 0)
8480 if (part_ok (p) && type_ok (p) && p -> c_ctlistfnx)
8488 && p -> c_ctshowfnx) {
8489 switch ((*p -> c_ctshowfnx) (p, nowserial, nowalternate)) {
8501 ct -> c_ctshowfnx = show_multi;
8515 static long clock = 0L;
8516 static char *msgfmt;
8519 (void) time (&clock);
8520 (void) sprintf (msgid, "<%d.%ld.%%d@@%s>\n", getpid (), clock,
8523 msgfmt = getcpy (msgid);
8526 (void) sprintf (msgid, msgfmt, ++partno);
8527 p -> c_id = getcpy (msgid);
8531 vrsn = !ci -> ci_magic ? MULTI_MIXED
8532 : uprf (ci -> ci_magic, "alt") ? MULTI_ALTERNATE
8536 (void) sprintf (buffer, "multipart/%s", SubMultiPart[vrsn - 1].kv_key);
8548 static char ident[] = "@@(#)$Id: mhn.c,v 2.23 1993/08/25 17:26:22 jromine Exp jromine $";
8551 if (ebcdicsw && !ebcdicsafe[*cp & 0xff])
8557 @off_t fixes for BSD44
8562 static char ident[] = "@@(#)$Id: mhn.c,v 2.22 1993/08/20 15:52:01 jromine Exp jromine $";
8598 #define NRFC934SW 19
8604 #define NSERIALSW 21
8643 #define FILESW 34 /* interface from show */
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)
8659 static char ident[] = "@@(#)$Id: mhn.c,v 2.21 1992/12/15 00:20:22 jromine Exp jromine $";
8667 return stat (ce -> ce_file, &st) != NOTOK ? st.st_size : 0L;
8670 size = fstat (fd, &st) != NOTOK ? st.st_size : 0L;
8673 (void) lseek (fd = fileno (ct -> c_fp), ct -> c_begin, 0);
8676 lseek (fd, 0L, 1) - (ep - cp),
8679 (void) lseek (fd = fileno (ct -> c_fp), ct -> c_begin, 0);
8682 ct -> c_end = st.st_size;
8685 p -> c_end = st.st_size;
8688 ct -> c_end = st.st_size;
8691 nlines += ((st.st_size - pos) + CPERLIN) / (CPERLIN + 1);
8702 static char ident[] = "@@(#)$Id: mhn.c,v 2.20 1992/12/14 17:10:25 jromine Exp jromine $";
8747 #define NRFC934SW 14
8753 #define NSERIALSW 16
8792 #define FILESW 29 /* interface from show */
8819 char *c_storeproc; /* default, if not in profile */
8827 if (f2 || f3 || f4 || f5 || f6)
8830 cache = m_find (buf);
8836 static int InitApplication (), InitMessage (), InitMultiPart (), InitText ();
8839 "audio", CT_AUDIO, NULL,
8840 "image", CT_IMAGE, NULL,
8843 "video", CT_VIDEO, NULL,
8848 char *dp = trimcpy (cp);
8852 ct -> c_file, VRSN_FIELD, dp);
8858 c = *dp, *dp = NULL;
8859 if (!uleq (cp, VRSN_VALUE)) {
8863 "message %s has unsupported value for %s: field (%s)",
8872 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8875 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8878 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8881 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8884 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8887 if (*cp == '(' && get_comment (ct, &cp) == NOTOK)
8890 static int get_comment (ct, ap)
8894 ct -> c_file, TYPE_FIELD);
8897 if (dp = ci -> ci_comment) {
8898 ci -> ci_comment = concat (dp, " ", buffer, NULLCP);
8902 ci -> ci_comment = add (buffer, NULLCP);
8905 fprintf (stderr, " %s:%s", VRSN_FIELD, ct -> c_vrsn);
8916 if (uprf (name, XXX_FIELD_PRF) || uleq (name, "Message-ID")) {
8921 if (uleq (*ap, "charset")) {
8932 #define APPLICATION_ODA 0x02
8933 #define APPLICATION_POSTSCRIPT 0x03
8935 "oda", APPLICATION_ODA,
8938 if (autosw && !ct -> c_storeproc)
8939 for (ap = ci -> ci_attrs, ep = ci -> ci_values; *ap; ap++, ep++)
8940 if (uleq (*ap, "name")) {
8944 if (*(cp = *ep) != '/'
8948 && !index (cp, '%'))
8949 ct -> c_storeproc = add (cp, NULLCP);
8954 if (uleq (*ap, "conversions")
8974 static int openExternal (ct, ce, file, fd)
8979 if (cache && (id = ct -> c_id)) {
8984 (void) sprintf (buffer,
8985 "Use cached copy %s of size %lu octets (content %s)? ",
8986 id, (unsigned long) st.st_size,
8991 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
8994 && (id = e -> eb_parent -> c_id)
8997 if (getanswer (buffer)) {
9001 while (fgets (buffer, sizeof buffer - 1, gp))
9002 (void) fputs (buffer, fp);
9005 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
9008 && (id = e -> eb_parent -> c_id)
9011 if (getanswer (buffer)) {
9014 switch (openExternal (e -> eb_parent, ce, file, &fd)) {
9017 e -> eb_server, "\n\n", e -> eb_body, "\n? ", NULLCP);
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,
9029 vec[vecp++] = buffer;
9032 vec[vecp++] = "mail-server request";
9035 ct -> c_id = getcpy (msgid);
9042 for (cp = buffer; *cp; cp++)
9048 if (ct -> c_subtype != TEXT_PLAIN
9049 || (ct -> c_ctparams
9052 != CHARSET_USASCII)) {
9065 if (('!' <= *cp && *cp <= '$')
9066 || ('[' <= *cp && *cp <= '^')
9067 || ('{' <= *cp && *cp <= '~')) {
9073 if ('%' <= *cp && *cp <= 'z')
9078 static char nib2b64[0x40f] =
9084 status = via_post (tmpfil);
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");
9098 if (slowsw > 0 && 1 < partno && partno < nparts) {
9104 status = via_post (tmpdrf);
9105 (void) unlink (tmpdrf);
9110 static int via_post (file)
9114 (void) execlp (postproc, r1bindex (postproc, '/'), file, NULLCP);
9125 static char ident[] = "@@(#)$Id: mhn.c,v 2.19 1992/12/10 22:27:15 jromine Exp jromine $";
9137 static char ident[] = "@@(#)$Id: mhn.c,v 2.18 1992/12/09 19:23:22 jromine Exp jromine $";
9149 (void) pidcheck (status.w_status);
9161 (void) pidcheck (status.w_status);
9172 static char ident[] = "@@(#)$Id: mhn.c,v 2.17 1992/12/03 21:58:18 jromine Exp jromine $";
9180 @ignore return value of vsprintf()
9185 static char ident[] = "@@(#)$Id: mhn.c,v 2.16 1992/12/02 18:50:39 jromine Exp jromine $";
9197 static char ident[] = "@@(#)$Id: mhn.c,v 2.15 1992/11/24 18:21:54 jromine Exp jromine $";
9200 bp += vsprintf (bp, fmt, arglist);
9211 static char ident[] = "@@(#)$Id: mhn.c,v 2.14 1992/11/24 17:18:52 jromine Exp jromine $";
9214 register CI ci = &ct -> c_ctinfo;
9226 static char ident[] = "@@(#)$Id: mhn.c,v 2.13 1992/11/24 17:18:04 jromine Exp jromine $";
9231 extern int openFile ();
9232 extern int openFTP ();
9233 extern int openMail ();
9239 @messed up ifdefs for VSPRINTF & __STDC__
9244 static char ident[] = "@@(#)$Id: mhn.c,v 2.12 1992/11/23 19:07:08 jromine Exp jromine $";
9247 "8bit", CE_8BIT, NULL,
9258 static char ident[] = "@@(#)$Id: mhn.c,v 2.11 1992/11/23 19:05:18 jromine Exp jromine $";
9280 static char ident[] = "@@(#)$Id: mhn.c,v 2.10 1992/11/23 19:04:27 jromine Exp jromine $";
9283 if (p -> c_end < p -> c_begin) {
9284 p -> c_begin = p -> c_end;
9291 @fix '-moreproc' -- from mtr
9296 static char ident[] = "@@(#)$Id: mhn.c,v 2.9 1992/11/11 17:57:04 jromine Exp jromine $";
9299 (void) sprintf (buffer, "Make cached, publically-accessible copy? ");
9310 static char ident[] = "@@(#)$Id: mhn.c,v 2.8 1992/11/09 17:46:01 jromine Exp jromine $";
9313 moreproc && *moreproc ? moreproc : "more");
9319 @fixup varargs include
9324 static char ident[] = "@@(#)$Id: mhn.c,v 2.7 1992/11/09 17:45:19 jromine Exp jromine $";
9327 : m_maildir (invo_name);
9333 @charset changes via MTR
9338 static char ident[] = "@@(#)$Id: mhn.c,v 2.6 1992/11/06 03:24:40 jromine Exp jromine $";
9346 @AUX fixups - varargs
9351 static char ident[] = "@@(#)$Id: mhn.c,v 2.5 1992/11/04 00:47:59 jromine Exp jromine $";
9355 (*p -> c_ctstorefnx) (p, NULLCP);
9362 charset = CHARSET_USASCII;
9366 add ((t -> tx_charset = charset)
9368 ? "charset=us-ascii"
9369 : "charset=x-unknown", NULLCP),
9378 isupper with isalpha
9383 static char ident[] = "@@(#)$Id: mhn.c,v 2.4 1992/11/02 17:01:08 jromine Exp jromine $";
9386 #if defined(VSPRINTF) && !defined(hpux)
9389 #if defined(VSPRINTF) && !defined(hpux)
9405 static char ident[] = "@@(#)$Id: mhn.c,v 2.3 1992/10/26 16:58:47 jromine Exp jromine $";
9409 static int pipeser ();
9413 static int pipeser (i)
9425 static int intrser (i)
9431 @add single quotes areound %f
9436 static char ident[] = "@@(#)$Id: mhn.c,v 2.2 1992/10/20 20:30:08 jromine Exp jromine $";
9447 if (part_ok (p) && type_ok (p) && p -> c_ctstorefnx)
9448 (void) (*p -> c_ctstorefnx) (p, NULLCP);
9458 "local-file", 0, openFile,
9462 "anon-ftp", 1, openFTP,
9466 size = ct -> c_end - p -> c_begin;
9476 if (ftp_get (e -> eb_site, user, pass, e -> eb_dir, e -> eb_name,
9478 e -> eb_mode && uleq (e -> eb_mode, "ascii"), 0)
9480 username = password = NULL;
9496 static char ident[] = "@@(#)$Id: mhn.c,v 2.1 1992/10/20 16:26:29 jromine Exp jromine $";
9499 (void) sprintf (buffer, "%%p%s %%F",
9502 ct -> c_showproc = add ("%pshow -file %F", NULLCP);
9513 static char ident[] = "@@(#)$Id: mhn.c,v 1.5 1992/02/18 17:36:22 jromine Exp $";
9517 if (!(cp = *argp++) || *cp == '-')
9520 file = path (cp, TFILE);
9523 cwd = getcpy (pwd ());
9527 if ((fp = fopen (file, "r")) == NULL)
9528 adios (file, "unable to read");
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);
9537 fprintf (stderr, " as file %s\n", ct -> c_storage);
9540 size = ct -> c_end - p -> c_begin;
9543 (void) sprintf (buffer, "mail-server request (cache as %s/%s)", cache,
9549 @new version from /mtr - MIME/update9
9566 ce -> ce_unlink = *file == NULL, caching = 0, cachefile[0] = NULL;
9569 *cp = NULL, n -= (i - 2);
9580 static char ident[] = "@@(#)$Id: mhn.c,v 1.6 1992/03/03 17:13:54 jromine Exp jromine $";
9594 via_mail (f1, f2, f3, f4, f5, f6);
9597 if (fp = fopen (cp = libpath ("mhn_profile"), "r")) {
9601 dir = getcpy ((cp = m_find (buf)) ? cp : cwd);
9606 if (storesw || showsw)
9607 for (ctp = cts; ct = *ctp; ctp++)
9608 if (type_ok (ct) && (ct -> c_ctstorefnx || ct -> c_ctshowfnx)) {
9612 ct -> c_umask = ~(stat (ct -> c_file, &st) != NOTOK
9613 ? (st.st_mode & 0777) : m_gmprot ());
9622 (void) umask (ct -> c_umask);
9627 while (wait (&status) != NOTOK)
9640 advise (NULLCP, "message %s has multiple %s: fields",
9641 ct -> c_file, VRSN_FIELD);
9647 if (ct -> c_ctline) {
9648 advise (NULLCP, "message %s has multiple %s: fields",
9649 ct -> c_file, TYPE_FIELD);
9655 if (ct -> c_celine) {
9656 advise (NULLCP, "message %s has multiple %s: fields",
9657 ct -> c_file, ENCODING_FIELD);
9665 advise (NULLCP, "invalid %s: field in message %s (empty type)",
9675 "invalid %s: field in message %s (missing subtype for \"%s\")",
9676 TYPE_FIELD, ct -> c_file, ci -> ci_type);
9679 ci -> ci_subtype = add ("", NULLCP);
9689 "invalid parameter in message %s's %s: field (%s)",
9690 ct -> c_file, TYPE_FIELD, cp);
9693 vp = (*ap = add (cp, NULLCP)) + (dp - cp);
9695 ci -> ci_values[ap - ci -> ci_attrs] = vp;
9699 "invalid quoted-string in message %s's %s: field (parameter %s)",
9700 ct -> c_file, TYPE_FIELD, *ap);
9705 "invalid parameter in message %s's %s: field (parameter %s)",
9706 ct -> c_file, TYPE_FIELD, *ap);
9709 advise (NULLCP, "invalid description in message %s's %s: field",
9710 ct -> c_file, TYPE_FIELD);
9713 "extraneous information in message %s's %s: field (%s)",
9714 ct -> c_file, TYPE_FIELD, cp);
9719 (void) sprintf (bp, " (content %s/%s", ci -> ci_type, ci -> ci_subtype);
9723 if ((cp = m_find (buffer)) == NULL) {
9726 if ((cp = m_find (buffer)) == NULL
9734 xlist = xstdin = xtty = 0;
9742 fprintf (stderr, "%s msg %s", cracked ? "store" : "show",
9745 fprintf (stderr, " using command %s\n", buffer);
9747 (void) fflush (stdout);
9751 (void) pidwait (xpid, NOTOK);
9754 if (xlist && ct -> c_ctlistfnx)
9755 (*ct -> c_ctlistfnx) (ct, -1);
9763 (void) pidXwait (child_id, NULLCP);
9766 (void) sprintf (buffer, "%s-store-%s/%s", invo_name, ci -> ci_type,
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";
9776 (void) sprintf (bp = buffer, "%s/", dir[1] ? dir : "");
9780 return show_content_aux (ct, 1, 0, buffer + 1, dir);
9787 file = appending ? NULLCP : ct -> c_storage;
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);
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");
9805 if (append && !*append)
9810 fprintf (out, "%s: %s", name, buf);
9819 (void) sprintf (buffer, "%s %%F",
9823 register struct text *t;
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;
9830 t -> tx_charset = kv -> kv_value;
9838 while (kids > 0 && (pid = wait (&status)) != NOTOK)
9842 ci -> ci_type, ci -> ci_subtype);
9855 static int params_external (ct)
9861 if (!e -> eb_access || !e -> eb_name || !e -> eb_site) {
9864 printf ("\t retrieve %s ", e -> eb_name);
9867 printf ("in directory %s ", e -> eb_dir);
9868 printf ("\n\t\t from %s\n\t\tusing %s", e -> eb_site,
9872 if (!e -> eb_didone) {
9878 if ((*p -> c_ceopenfnx) (p, &file) == NOTOK)
9880 (void) (*p -> c_ceclosefnx) (p);
9882 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK)
9887 if (!e -> eb_didone) {
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)
9896 (void) (*p -> c_ceclosefnx) (p);
9898 if (p -> c_ctinitfnx && (*p -> c_ctinitfnx) (p) == NOTOK)
9905 ci -> ci_type, ci -> ci_subtype);
9909 ct -> c_showproc = add ("show -file %F", NULLCP);
9913 p -> c_end = p -> c_begin;
9919 if (params_external (ct) == NOTOK)
9931 if (uleq (*ap, "conversions") && uleq (*ep, "compress")) {
9934 if (autosw && !ct -> c_storeproc && uleq (*ap, "file")) {
9937 if (*(cp = *ep) != '/' && *cp != '+' && *cp != '@@')
9938 ct -> c_storeproc = add (cp, NULLCP);
9942 unsigned char *b = (unsigned char *) &bits;
9945 unsigned char value;
9950 m_maildir (invo_name)),
9956 fprintf (stderr, "*cp=0x%x pos=%ld\n", *cp,
9957 lseek (fd, 0L, 1) - (ep - cp));
9960 "invalid BASE64 encoding (char 0x%x at position %ld) -- continuing",
9962 lseek (fd, 0L, 1) - (ep - cp));
9965 #if defined(i386) || defined(vax)
9966 (void) putc (b[2], ce -> ce_fp);
9969 (void) putc (b[1], ce -> ce_fp);
9972 (void) putc (b[0], ce -> ce_fp);
9976 (void) putc (b[1], ce -> ce_fp);
9978 (void) putc (b[2], ce -> ce_fp);
9980 (void) putc (b[3], ce -> ce_fp);
9994 "unaligned ',' (bitno %d)\n",
9997 goto invalid_encoding;
9999 (void) putc ('\n', ce -> ce_fp);
10004 invalid_encoding: ;
10012 m_maildir (invo_name)),
10019 m_maildir (invo_name)),
10028 static char *password = NULL;
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");
10040 *file = ce -> ce_file;
10041 return fileno (ce -> ce_fp);
10045 user = "anonymous", pass = "guest";
10048 (void) pidwait (xpid, NOTOK);
10054 ce -> ce_unlink = *file == NULL;
10058 m_maildir (invo_name)),
10061 printf ("Retrieving %s using %sFTP from site %s\n",
10062 e -> eb_name, e -> eb_flags ? "Anonymous " : "", e -> eb_site);
10070 fprintf (out, "%s: %s", name, buf);
10073 while (fgets (buf, sizeof buf - 1, in)) {
10080 if (buf[0] != '#' || buf[1] == '#') {
10085 if (!fgets (buffer, sizeof buffer - 1, in))
10089 if ((cp = fgets (buffer, sizeof buffer - 1, in)) == NULL)
10092 if (get_ctinfo ("text/plain", ct, 0) == NOTOK)
10095 ct -> c_type = CT_TEXT;
10096 ct -> c_ctinitfnx = InitText;
10097 (void) (*ct -> c_ctinitfnx) (ct);
10100 (void) fseek (in, (long) (-strlen (cp)), 1);
10106 if (params_external (ct) == NOTOK)
10110 if ((cp = m_find (buffer)) == NULL) {
10113 if ((cp = m_find (buffer)) == NULL) {
10116 while (fgets (buffer, sizeof buffer - 1, in)) {
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
10140 ct -> c_end += 1 /* notdef 2 */;
10143 if (pidXwait (child_id, NULLCP) & 0377)
10146 if (ct -> c_type != CT_TEXT)
10150 charset = ct -> c_type != CT_TEXT || ct -> c_ctparams ? 0 : -1;
10153 if (!isascii (*cp) || !asciiP[*cp & 0x7f]) {
10154 charset = CHARSET_UNKNOWN;
10164 : "charset=iso8859-1", NULLCP),
10168 if (!ci -> ci_comment && ct -> c_rfc934)
10169 ci -> ci_comment = add ("RFC 934 compatible encapsulation",
10177 if (ct -> c_subtype == APPLICATION_POSTSCRIPT)
10182 for (cp = buffer; *cp; cp++) {
10192 #if defined(i386) || defined(vax)
10193 for (bp = outbuf; bp < outbuf + sizeof outbuf; bits >>= 6)
10194 *bp++ = nib2b64[bits & 0x3f];
10200 static int via_mail (mailsw, subjsw, parmsw, descsw, cmntsw, slowsw)
10207 fprintf (fp, "Subject: %s\n", subjsw);
10208 fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
10211 fprintf (fp, "\n\t(%s)", cmntsw);
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);
10229 static char ident[] = "@@(#)$Id: mhn.c,v 1.5 1992/02/18 17:36:22 jromine Exp jromine $";
10240 int list_content (), show_content (), store_content ();
10241 void free_content (), content_error (), flush_errors ();
10245 int InitApplication (), InitMessage (), InitMultiPart (), InitText ();
10248 int InitBase64 (), InitQuoted (), Init7Bit ();
10251 c = *dp, *dp = NULL;
10257 c = *dp, *dp = NULL;
10260 c = *dp, *dp = NULL;
10269 if ((c = *cp++) == NULL)
10278 c = *dp, *dp = NULL;
10284 if ((c = *cp++) == NULL)
10325 buffer[diff] = NULL;
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,
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
10350 static int build_comp (file)
10385 static char ident[] = "@@(#)$Id: mhn.c,v 1.4 1992/02/14 16:22:17 jromine Exp jromine $";
10388 if (uprf (name, XXX_FIELD_PRF)) {
10399 static char ident[] = "@@(#)$Id: mhn.c,v 1.3 1992/02/07 16:07:46 jromine Exp jromine $";
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,
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,
10424 static char ident[] = "@@(#)$Id: mhn.c,v 1.2 1992/02/07 03:44:12 jromine Exp jromine $";
10427 if (ct -> c_celine) {
10430 if (ct -> c_celine) {
10433 for (ep = (cp = buffer) + cc - 2; cp <= ep; ep--)
10444 static char ident[] = "@@(#)$Id: mhn.c,v 1.1 1992/01/31 16:28:15 jromine Exp jromine $";
10447 (void) sprintf (buffer, "%s %%F", moreproc);
10458 static char ident[] = "@@(#)$Id$";