nmh-workers
[Top] [All Lists]

mhn extension

1996-12-16 08:22:49

This is a patch to mhn in the 6.8.4 distribution, to support external
Content-Transfer-Encoding types. For an encoding type "x-typename" it
searches the profile for "mhn-decode-typename" which is expected to be
a commandline that takes input on stdin. Since I mainly added it to
support uudecode, which always creates an output file by itself, the code
also assumes that the output file will be created by the external program.
But just to cover all bases, the external program's stdout is also set
to the output file. I also expect that the desired filename is present
in the content attributes, but will generate a tempname if not.

Oh, I also added a definition for multipart/report, the crap that some
mailer daemons send for bounced email. This may not have been the proper
treatment, but it was annoying and I did it in a hurry.

Howard Chu                              Principal Member of Technical Staff
hyc(_at_)locus(_dot_)com                                PLATINUM technology, 
Los Angeles Lab

*** /tmp/T0ipoB4o       Sun Dec 15 21:45:49 1996
--- mhn.c       Sun Dec 15 21:42:30 1996
***************
*** 195,200 ****
--- 195,201 ----
  static        char   *dir;
  static        char   *errs = NULL;
  static        char   *tmp;
+ static        char   *maildir;


  extern        int     errno;
***************
*** 361,367 ****
           *f7 = NULL,
           *file = NULL,
             *folder = NULL,
-            *maildir,
              buf[100],
            **ap,
            **argp,
--- 362,367 ----
***************
*** 1039,1045 ****
  };


! static int InitBase64 (), InitQuoted (), Init7Bit ();

  static struct str2init str2ces[] = {
      "base64",         CE_BASE64,      InitBase64,
--- 1039,1045 ----
  };


! static int InitBase64 (), InitQuoted (), Init7Bit (), InitExtension ();

  static struct str2init str2ces[] = {
      "base64",         CE_BASE64,      InitBase64,
***************
*** 1048,1054 ****
      "7bit",           CE_7BIT,        Init7Bit,
      "binary",         CE_BINARY,      NULL,

!     NULL,             CE_EXTENSION,   NULL,   /* these two must be last! */
      NULL,             CE_UNKNOWN,     NULL,
  };

--- 1048,1054 ----
      "7bit",           CE_7BIT,        Init7Bit,
      "binary",         CE_BINARY,      NULL,

!     NULL,             CE_EXTENSION,   InitExtension,  /* these two must be 
last! */
      NULL,             CE_UNKNOWN,     NULL,
  };

***************
*** 1186,1192 ****
                        goto out;
                    }

-                   ct -> c_celine = cp;
                    while (isspace (*cp))
                        cp++;
                    for (dp = cp; istoken (*dp); dp++)
--- 1186,1191 ----
***************
*** 1197,1203 ****
                            break;
                    if (!s2i -> si_key && !uprf (cp, "X-"))
                        s2i++;
!                   *dp = c;
                    ct -> c_encoding = s2i -> si_val;
                    if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
                        goto out;
--- 1196,1202 ----
                            break;
                    if (!s2i -> si_key && !uprf (cp, "X-"))
                        s2i++;
!                   ct -> c_celine = cp;
                    ct -> c_encoding = s2i -> si_val;
                    if (s2i -> si_init && (*s2i -> si_init) (ct) == NOTOK)
                        goto out;
***************
*** 2868,2873 ****
--- 2867,2873 ----
  #define       MULTI_ALTERNATE 0x02
  #define       MULTI_DIGEST    0x03
  #define       MULTI_PARALLEL  0x04
+ #define       MULTI_REPORT    0x05


  struct multipart {
***************
*** 3238,3243 ****
--- 3238,3244 ----
      "alternative",  MULTI_ALTERNATE,
      "digest",     MULTI_DIGEST,
      "parallel",           MULTI_PARALLEL,
+     "report",     MULTI_REPORT,

      NULL,         MULTI_UNKNOWN               /* this one must be last! */
  };
***************
*** 3451,3456 ****
--- 3452,3458 ----
  #define       MESSAGE_RFC822   0x01
  #define       MESSAGE_PARTIAL  0x02
  #define       MESSAGE_EXTERNAL 0x03
+ #define       MESSAGE_DELIVERY_STATUS 0x04


  struct partial {
***************
*** 3818,3823 ****
--- 3820,3826 ----
      "rfc822",      MESSAGE_RFC822,
      "partial",             MESSAGE_PARTIAL,
      "external-body", MESSAGE_EXTERNAL,
+     "delivery-status",        MESSAGE_DELIVERY_STATUS,

      NULL,          MESSAGE_UNKNOWN            /* this one must be last! */
  };
***************
*** 3843,3848 ****
--- 3846,3852 ----

      switch (ct -> c_subtype = kv -> kv_value) {
        case MESSAGE_RFC822:
+       case MESSAGE_DELIVERY_STATUS:
            ct -> c_showproc = add ("%pshow -file '%F'", NULLCP);
            break;

***************
*** 4243,4248 ****
--- 4247,4373 ----
      return OK;
  }

+ /*  Extension encoding */
+
+ static int  openExtension (ct, file)
+ register CT   ct;
+ char  **file;
+ {
+     register char  *cp;
+     register struct cefile *ce = (struct cefile *) ct -> c_ceparams;
+     char    buffer[BUFSIZ];
+     char *vec[4];
+     int fds[2], fd, len, child_id, i, cc;
+
+     (void) sprintf (buffer, "%s-decode-%s", invo_name, ct -> c_celine+2);
+     if ((cp = m_find (buffer)) == NULL || *cp == 0) {
+       content_error (NULLCP, ct,
+                              "don't know how to decode content");
+       return NOTOK;
+     }
+
+     if (ce -> ce_fp)
+       goto ready_to_go;
+     if (ce -> ce_file) {
+       if ((ce -> ce_fp = fopen (ce -> ce_file, "r")) == NULL) {
+           content_error (ce -> ce_file, ct, "unable to fopen for reading");
+           return NOTOK;
+       }
+
+       *file = ce -> ce_file;
+       return fileno (ce -> ce_fp);
+     }
+
+     ce -> ce_unlink = *file == NULL;
+     for (i=0; ct->c_ctinfo.ci_attrs[i]; ++i) {
+       if (uprf(ct->c_ctinfo.ci_attrs[i], "name") ||
+           uprf(ct->c_ctinfo.ci_attrs[i], "filename")) {
+           sprintf(buffer, "%s/%s", maildir, ct->c_ctinfo.ci_values[i]);
+           ce -> ce_file = getcpy (buffer);
+           break;
+       }
+     }
+     if (!ce -> ce_file)
+       ce -> ce_file = add (*file ? *file : m_scratch ("", tmp), NULLCP);
+     if ((ce -> ce_fp = fopen (ce -> ce_file, "w+")) == NULL) {
+       content_error (ce -> ce_file, ct,
+                      "unable to fopen for writing and reading");
+       return NOTOK;
+     }
+     if ((len = ct -> c_end - ct -> c_begin) < 0)
+       adios (NULLCP, "internal error(1)");
+
+     if (!ct -> c_fp && (ct -> c_fp = fopen (ct -> c_file, "r")) == NULL) {
+       content_error (ct -> c_file, ct, "unable to open for reading");
+       return NOTOK;
+     }
+
+     (void) lseek (fd = fileno (ct -> c_fp), (off_t)ct -> c_begin, 0);
+
+     (void) sprintf (buffer, "exec %s", cp);
+
+     vec[0] = "/bin/sh";
+     vec[1] = "-c";
+     vec[2] = buffer;
+     vec[3] = NULL;
+
+     if (pipe(fds) == NOTOK)
+     {
+       advise ("pipe", "unable to create");
+       return NOTOK;
+     }
+     for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
+       sleep (5);
+     switch (child_id) {
+       case NOTOK:
+           advise ("fork", "unable to");
+           return NOTOK;
+
+       case OK:
+           dup2(fds[0], 0);
+           dup2 (fileno (ce->ce_fp), 1);
+           close (fds[0]);
+           close (fds[1]);
+           (void) execvp ("/bin/sh", vec);
+           fprintf (stderr, "unable to exec ");
+           perror ("/bin/sh");
+           _exit (-1);
+           /* NOTREACHED */
+
+       default:
+           close(fds[0]);
+           while (len > 0)
+               switch (cc = read (fd, buffer, sizeof buffer)) {
+                   case NOTOK:
+                       content_error (ct -> c_file, ct, "error reading from");
+                       goto clean_up;
+
+                   case OK:
+                       content_error (NULLCP, ct, "premature eof");
+                       goto clean_up;
+
+                   default:
+                       if (cc > len)
+                           cc = len;
+                       len -= cc;
+                       write (fds[1], buffer, cc);
+               }
+           close (fds[1]);
+
+           (void) pidcheck (pidwait (child_id, NOTOK));
+           break;
+     }
+ ready_to_go: ;
+     (void) fseek (ce -> ce_fp, 0L, 0);
+     *file = ce -> ce_file;
+     return fileno (ce -> ce_fp);
+
+ clean_up: ;
+     free_encoding (ct, 0);
+
+     return NOTOK;
+ }
+
  /*    BASE64 */

  static unsigned char b642nib[0x80] = {
***************
*** 4426,4431 ****
--- 4551,4562 ----
      return NOTOK;
  }

+
+ static int  InitExtension (ct)
+ register CT   ct;
+ {
+     return init_encoding (ct, openExtension);
+ }

  static int  InitBase64 (ct)
  register CT   ct;


<Prev in Thread] Current Thread [Next in Thread>
  • mhn extension, Howard Chu <=