* uip/mhlistsbr.c, uip/mhlsbr.c, uip/picksbr.c: cast
[mmh] / uip / whatnowsbr.c
index 0e2a998..5fcba33 100644 (file)
@@ -3,12 +3,48 @@
  * whatnowsbr.c -- the WhatNow shell
  *
  * $Id$
+ *
+ * This code is Copyright (c) 2002, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ *
+ *  Several options have been added to ease the inclusion of attachments
+ *  using the header field name mechanism added to anno and send.  The
+ *  -attach option is used to specify the header field name for attachments.
+ *
+ *  Several commands have been added at the whatnow prompt:
+ *
+ *     cd [ directory ]        This option works just like the shell's
+ *                             cd command and lets the user change the
+ *                             directory from which attachments are
+ *                             taken so that long path names are not
+ *                             needed with every file.
+ *
+ *     ls [ ls-options ]       This option works just like the normal
+ *                             ls command and exists to allow the user
+ *                             to verify file names in the directory.
+ *
+ *     pwd                     This option works just like the normal
+ *                             pwd command and exists to allow the user
+ *                             to verify the directory.
+ *
+ *     attach files            This option attaches the named files to
+ *                             the draft.
+ *
+ *     alist [-ln]             This option lists the attachments on the
+ *                             draft.  -l gets long listings, -n gets
+ *                             numbered listings.
+ *
+ *     detach files            This option removes attachments from the
+ *     detach -n numbers       draft.  This can be done by file name or
+ *                             by attachment number.
  */
 
 #include <h/mh.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <h/mime.h>
+#include <h/utils.h>
 
 static struct swit whatnowswitches[] = {
 #define        DFOLDSW                 0
@@ -27,6 +63,8 @@ static struct swit whatnowswitches[] = {
     { "version", 0 },
 #define        HELPSW                  7
     { "help", 0 },
+#define        ATTACHSW                8
+    { "attach header-field-name", 0 },
     { NULL, 0 }
 };
 
@@ -54,6 +92,18 @@ static struct swit aleqs[] = {
     { "quit [-delete]", 0 },
 #define DELETESW                       9
     { "delete", 0 },
+#define        CDCMDSW                       10
+    { "cd [directory]", 0 },
+#define        PWDCMDSW                      11
+    { "pwd", 0 },
+#define        LSCMDSW                       12
+    { "ls", 0 },
+#define        ATTACHCMDSW                   13
+    { "attach", 0 },
+#define        DETACHCMDSW                   14
+    { "detach [-n]", 2 },
+#define        ALISTCMDSW                    15
+    { "alist [-ln] ", 2 },
     { NULL, 0 }
 };
 
@@ -70,6 +120,11 @@ static int buildfile (char **, char *);
 static int check_draft (char *);
 static int whomfile (char **, char *);
 static int removefile (char *);
+static void writelscmd(char *, int, char **);
+static void writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp);
+static FILE* popen_in_dir(const char *dir, const char *cmd, const char *type);
+static int system_in_dir(const char *dir, const char *cmd);
+
 
 #ifdef HAVE_LSTAT
 static int copyf (char *, char *);
@@ -85,6 +140,13 @@ WhatNow (int argc, char **argv)
     char buf[BUFSIZ], prompt[BUFSIZ];
     char **argp, **arguments;
     struct stat st;
+    char       *attach = (char *)0;    /* attachment header field name */
+    char       cwd[MAXPATHLEN + 1];    /* current working directory */
+    char       file[MAXPATHLEN + 1];   /* file name buffer */
+    char       shell[MAXPATHLEN + 1];  /* shell response buffer */
+    FILE       *f;                     /* read pointer for bgnd proc */
+    char       *l;                     /* set on -l to alist  command */
+    int                n;                      /* set on -n to alist command */
 
     invo_name = r1bindex (argv[0], '/');
 
@@ -94,16 +156,24 @@ WhatNow (int argc, char **argv)
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
 
+    /*
+     * Get the initial current working directory.
+     */
+
+    if (getcwd(cwd, sizeof (cwd)) == (char *)0) {
+       adios("getcwd", "could not get working directory");
+    }
+
     while ((cp = *argp++)) {
        if (*cp == '-') {
            switch (smatch (++cp, whatnowswitches)) {
-           case AMBIGSW: 
+           case AMBIGSW:
                ambigsw (cp, whatnowswitches);
                done (1);
-           case UNKWNSW: 
+           case UNKWNSW:
                adios (NULL, "-%s unknown", cp);
 
-           case HELPSW: 
+           case HELPSW:
                snprintf (buf, sizeof(buf), "%s [switches] [file]", invo_name);
                print_help (buf, whatnowswitches, 1);
                done (1);
@@ -111,7 +181,7 @@ WhatNow (int argc, char **argv)
                print_version(invo_name);
                done (1);
 
-           case DFOLDSW: 
+           case DFOLDSW:
                if (dfolder)
                    adios (NULL, "only one draft folder at a time!");
                if (!(cp = *argp++) || *cp == '-')
@@ -119,23 +189,23 @@ WhatNow (int argc, char **argv)
                dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
                                *cp != '@' ? TFOLDER : TSUBCWF);
                continue;
-           case DMSGSW: 
+           case DMSGSW:
                if (dmsg)
                    adios (NULL, "only one draft message at a time!");
                if (!(dmsg = *argp++) || *dmsg == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                continue;
-           case NDFLDSW: 
+           case NDFLDSW:
                dfolder = NULL;
                isdf = NOTOK;
                continue;
 
-           case EDITRSW: 
+           case EDITRSW:
                if (!(ed = *argp++) || *ed == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                nedit = 0;
                continue;
-           case NEDITSW: 
+           case NEDITSW:
                nedit++;
                continue;
 
@@ -143,6 +213,13 @@ WhatNow (int argc, char **argv)
                if (!(myprompt = *argp++) || *myprompt == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                continue;
+
+           case ATTACHSW:
+               if (attach != (char *)0)
+                   adios(NULL, "only one attachment header field name at a time!");
+               if (!(attach = *argp++) || *attach == '-')
+                   adios (NULL, "missing argument to %s", argp[-2]);
+               continue;
            }
        }
        if (drft)
@@ -196,7 +273,7 @@ WhatNow (int argc, char **argv)
                done (1);
            break;
 
-       case LISTSW: 
+       case LISTSW:
            /* display the draft file */
            showfile (++argp, drft);
            break;
@@ -228,18 +305,219 @@ WhatNow (int argc, char **argv)
                done (1);
            break;
 
-       case SENDSW: 
+       case SENDSW:
            /* Send draft */
            sendfile (++argp, drft, 0);
            break;
 
-       case REFILEOPT: 
+       case REFILEOPT:
            /* Refile the draft */
            if (refile (++argp, drft) == 0)
                done (0);
            break;
 
-       default: 
+       case CDCMDSW:
+           /* Change the working directory for attachments
+            *
+            *  Run the directory through the user's shell so that
+            *  we can take advantage of any syntax that the user
+            *  is accustomed to.  Read back the absolute path.
+            */
+
+           if (*(argp+1) == (char *)0) {
+               (void)sprintf(buf, "$SHELL -c \"cd;pwd\"");
+           }
+           else {
+               writesomecmd(buf, BUFSIZ, "cd", "pwd", argp);
+           }
+           if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) {
+               fgets(cwd, sizeof (cwd), f);
+
+               if (strchr(cwd, '\n') != (char *)0)
+                       *strchr(cwd, '\n') = '\0';
+
+               pclose(f);
+           }
+           else {
+               advise("popen", "could not get directory");
+           }
+
+           break;
+
+       case PWDCMDSW:
+           /* Print the working directory for attachments */
+           printf("%s\n", cwd);
+           break;
+
+       case LSCMDSW:
+           /* List files in the current attachment working directory
+            *
+            *  Use the user's shell so that we can take advantage of any
+            *  syntax that the user is accustomed to.
+            */
+           writelscmd(buf, sizeof(buf), argp);
+           (void)system_in_dir(cwd, buf);
+           break;
+
+       case ALISTCMDSW:
+           /*
+            *  List attachments on current draft.  Options are:
+            *
+            *   -l     long listing (full path names)
+            *   -n     numbers listing
+            */
+
+           if (attach == (char *)0) {
+               advise((char *)0, "can't list because no header field name was given.");
+               break;
+           }
+
+           l = (char *)0;
+           n = 0;
+
+           while (*++argp != (char *)0) {
+               if (strcmp(*argp, "-l") == 0)
+                   l = "/";
+
+               else if (strcmp(*argp, "-n") == 0)
+                   n = 1;
+
+               else if (strcmp(*argp, "-ln") == 0 || strcmp(*argp, "-nl") == 0) {
+                   l = "/";
+                   n = 1;
+               }
+
+               else {
+                   n = -1;
+                   break;
+               }
+           }
+
+           if (n == -1)
+               advise((char *)0, "usage is alist [-ln].");
+
+           else
+               annolist(drft, attach, l, n);
+
+           break;
+
+       case ATTACHCMDSW:
+           /*
+            *  Attach files to current draft.
+            */
+
+           if (attach == (char *)0) {
+               advise((char *)0, "can't attach because no header field name was given.");
+               break;
+           }
+
+           /*
+            *  Build a command line that causes the user's shell to list the file name
+            *  arguments.  This handles and wildcard expansion, tilde expansion, etc.
+            */
+           writelscmd(buf, sizeof(buf), argp);
+
+           /*
+            *  Read back the response from the shell, which contains a number of lines
+            *  with one file name per line.  Remove off the newline.  Determine whether
+            *  we have an absolute or relative path name.  Prepend the current working
+            *  directory to relative path names.  Add the attachment annotation to the
+            *  draft.
+            */
+
+           if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) {
+               while (fgets(shell, sizeof (shell), f) != (char *)0) {
+                   *(strchr(shell, '\n')) = '\0';
+
+                   if (*shell == '/')
+                       (void)annotate(drft, attach, shell, 1, 0, -2, 1);
+                   else {
+                       (void)sprintf(file, "%s/%s", cwd, shell);
+                       (void)annotate(drft, attach, file, 1, 0, -2, 1);
+                   }
+               }
+
+               pclose(f);
+           }
+           else {
+               advise("popen", "could not get file from shell");
+           }
+
+           break;
+
+       case DETACHCMDSW:
+           /*
+            *  Detach files from current draft.
+            */
+
+           if (attach == (char *)0) {
+               advise((char *)0, "can't detach because no header field name was given.");
+               break;
+           }
+
+           /*
+            *  Scan the arguments for a -n.  Mixed file names and numbers aren't allowed,
+            *  so this catches a -n anywhere in the argument list.
+            */
+
+           for (n = 0, arguments = argp + 1; *arguments != (char *)0; arguments++) {
+               if (strcmp(*arguments, "-n") == 0) {
+                       n = 1;
+                       break;
+               }
+           }
+
+           /*
+            *  A -n was found so interpret the arguments as attachment numbers.
+            *  Decrement any remaining argument number that is greater than the one
+            *  just processed after processing each one so that the numbering stays
+            *  correct.
+            */
+
+           if (n == 1) {
+               for (arguments = argp + 1; *arguments != (char *)0; arguments++) {
+                   if (strcmp(*arguments, "-n") == 0)
+                       continue;
+
+                   if (**arguments != '\0') {
+                       n = atoi(*arguments);
+                       (void)annotate(drft, attach, (char *)0, 1, 0, n, 1);
+
+                       for (argp = arguments + 1; *argp != (char *)0; argp++) {
+                           if (atoi(*argp) > n) {
+                               if (atoi(*argp) == 1)
+                                   *argp = "";
+                               else
+                                   (void)sprintf(*argp, "%d", atoi(*argp) - 1);
+                           }
+                       }
+                   }
+               }
+           }
+
+           /*
+            *  The arguments are interpreted as file names.  Run them through the
+            *  user's shell for wildcard expansion and other goodies.  Do this from
+            *  the current working directory if the argument is not an absolute path
+            *  name (does not begin with a /).
+            *
+            * We feed all the file names to the shell at once, otherwise you can't
+            * provide a file name with a space in it.
+            */
+           writelscmd(buf, sizeof(buf), argp);
+           if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) {
+               while (fgets(shell, sizeof (shell), f) != (char *)0) {
+                   *(strchr(shell, '\n')) = '\0';
+                   (void)annotate(drft, attach, shell, 1, 0, 0, 1);
+               }
+               pclose(f);
+           } else {
+               advise("popen", "could not get file from shell");
+           }
+
+           break;
+
+       default:
            /* Unknown command */
            advise (NULL, "say what?");
            break;
@@ -248,6 +526,96 @@ WhatNow (int argc, char **argv)
     /*NOTREACHED*/
 }
 
+
+
+/* Build a command line of the form $SHELL -c "cd 'cwd'; cmd argp ... ; trailcmd". */
+static void
+writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp)
+{
+    char *cp;
+    /* Note that we do not quote -- the argp from the user
+     * is assumed to be quoted as they desire. (We can't treat
+     * it as pure literal as that would prevent them using ~,
+     * wildcards, etc.) The buffer produced by this function
+     * should be given to popen_in_dir() or system_in_dir() so
+     * that the current working directory is set correctly.
+     */
+    int ln = snprintf(buf, bufsz, "$SHELL -c \"%s", cmd);
+    /* NB that some snprintf() return -1 on overflow rather than the
+     * new C99 mandated 'number of chars that would have been written'
+     */
+    /* length checks here and inside the loop allow for the
+     * trailing ';', trailcmd, '"' and NUL
+     */
+    int trailln = strlen(trailcmd) + 3;
+    if (ln < 0 || ln + trailln > bufsz)
+       adios((char *)0, "arguments too long");
+    
+    cp = buf + ln;
+    
+    while (*++argp != (char *)0) {
+       ln = strlen(*argp);
+       /* +1 for leading space */
+       if (ln + trailln + 1 > bufsz - (cp-buf))
+           adios((char *)0, "arguments too long");
+       *cp++ = ' ';
+       memcpy(cp, *argp, ln+1);
+       cp += ln;
+    }
+    if (*trailcmd) {
+       *cp++ = ';';
+       strcpy(cp, trailcmd);
+       cp += trailln - 3;
+    }
+    *cp++ = '"';
+    *cp = 0;
+}
+
+/*
+ * Build a command line that causes the user's shell to list the file name
+ * arguments.  This handles and wildcard expansion, tilde expansion, etc.
+ */
+static void
+writelscmd(char *buf, int bufsz, char **argp)
+{
+    writesomecmd(buf, bufsz, "ls", "", argp);
+}
+
+/* Like system(), but run the command in directory dir.
+ * This assumes the program is single-threaded!
+ */
+static int
+system_in_dir(const char *dir, const char *cmd)
+{
+    char olddir[BUFSIZ];
+    int r;
+    if (getcwd(olddir, sizeof(olddir)) == 0)
+       adios("getcwd", "could not get working directory");
+    if (chdir(dir) != 0)
+       adios("chdir", "could not change working directory");
+    r = system(cmd);
+    if (chdir(olddir) != 0)
+       adios("chdir", "could not change working directory");
+    return r;
+}
+
+/* ditto for popen() */
+static FILE*
+popen_in_dir(const char *dir, const char *cmd, const char *type)
+{
+    char olddir[BUFSIZ];
+    FILE *f;
+    if (getcwd(olddir, sizeof(olddir)) == 0)
+       adios("getcwd", "could not get working directory");
+    if (chdir(dir) != 0)
+       adios("chdir", "could not change working directory");
+    f = popen(cmd, type);
+    if (chdir(olddir) != 0)
+       adios("chdir", "could not change working directory");
+    return f;
+}
+
+
 /*
  * EDIT
  */
@@ -326,12 +694,12 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp,
     fflush (stdout);
 
     switch (pid = vfork ()) {
-       case NOTOK: 
+       case NOTOK:
            advise ("fork", "unable to");
            status = NOTOK;
            break;
 
-       case OK: 
+       case OK:
            if (cwd)
                chdir (cwd);
            if (altmsg) {
@@ -353,7 +721,7 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp,
            perror (*ed);
            _exit (-1);
 
-       default: 
+       default:
            if ((status = pidwait (pid, NOTOK))) {
 #ifdef ATTVIBUG
                if ((cp = r1bindex (*ed, '/'))
@@ -488,9 +856,9 @@ sendfile (char **arg, char *file, int pushsw)
     for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++)
        sleep (5);
     switch (child_id) {
-       case NOTOK: 
+       case NOTOK:
            advise (NULL, "unable to fork, so sending directly...");
-       case OK: 
+       case OK:
            vecp = 0;
            vec[vecp++] = invo_name;
            if (pushsw)
@@ -506,7 +874,7 @@ sendfile (char **arg, char *file, int pushsw)
            perror (sendproc);
            _exit (-1);
 
-       default: 
+       default:
            if (pidwait(child_id, OK) == 0)
                done (0);
            return 1;
@@ -532,8 +900,7 @@ buildfile (char **argp, char *file)
        while (argp[i])
            i++;
     }
-    if ((args = (char **) malloc((i + 2) * sizeof(char *))) == NULL)
-       adios (NULL, "unable to malloc memory");
+    args = (char **) mh_xmalloc((i + 2) * sizeof(char *));
 
     /*
      * For backward compatibility, we need to add -build
@@ -607,6 +974,12 @@ check_draft (char *msgnam)
 }
 
 
+#ifndef CYRUS_SASL
+# define SASLminc(a) (a)
+#else /* CYRUS_SASL */
+# define SASLminc(a)  0
+#endif /* CYRUS_SASL */
+
 static struct swit  sendswitches[] = {
 #define        ALIASW            0
     { "alias aliasfile", 0 },
@@ -671,7 +1044,7 @@ static struct swit  sendswitches[] = {
 #define        CLIESW           30
     { "client host", -6 },
 #define        SERVSW           31
-    { "server host", -6 },
+    { "server host", 6 },
 #define        SNOOPSW          32
     { "snoop", -5 },
 #define SDRFSW           33
@@ -680,6 +1053,18 @@ static struct swit  sendswitches[] = {
     { "draftmessage msg", -6 },
 #define SNDRFSW          35
     { "nodraftfolder", -3 },
+#define SASLSW           36
+    { "sasl", SASLminc(-4) },
+#define SASLMECHSW       37
+    { "saslmech", SASLminc(-5) },
+#define USERSW           38
+    { "user", SASLminc(4) },
+#define SNDATTACHSW       39
+    { "attach file", 6 },
+#define SNDATTACHFORMAT   40
+    { "attachformat", 7 },
+#define PORTSW           41
+    { "port server-port-name/number", 4 },
     { NULL, 0 }
 };
 
@@ -704,6 +1089,9 @@ sendit (char *sp, char **arg, char *file, int pushed)
     char *cp, buf[BUFSIZ], **argp;
     char **arguments, *vec[MAXARGS];
     struct stat st;
+    char       *attach = (char *)0;    /* attachment header field name */
+    int                attachformat = 0;       /* mhbuild format specifier for
+                                          attachments */
 
 #ifndef        lint
     int        distsw = 0;
@@ -761,14 +1149,14 @@ sendit (char *sp, char **arg, char *file, int pushed)
     while ((cp = *argp++)) {
        if (*cp == '-') {
            switch (smatch (++cp, sendswitches)) {
-               case AMBIGSW: 
+               case AMBIGSW:
                    ambigsw (cp, sendswitches);
                    return;
-               case UNKWNSW: 
+               case UNKWNSW:
                    advise (NULL, "-%s unknown\n", cp);
                    return;
 
-               case SHELPSW: 
+               case SHELPSW:
                    snprintf (buf, sizeof(buf), "%s [switches]", sp);
                    print_help (buf, sendswitches, 1);
                    return;
@@ -776,34 +1164,34 @@ sendit (char *sp, char **arg, char *file, int pushed)
                    print_version (invo_name);
                    return;
 
-               case SPSHSW: 
+               case SPSHSW:
                    pushed++;
                    continue;
-               case NSPSHSW: 
+               case NSPSHSW:
                    pushed = 0;
                    continue;
 
-               case SPLITSW: 
+               case SPLITSW:
                    if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) {
                        advise (NULL, "missing argument to %s", argp[-2]);
                        return;
                    }
                    continue;
 
-               case UNIQSW: 
+               case UNIQSW:
                    unique++;
                    continue;
-               case NUNIQSW: 
+               case NUNIQSW:
                    unique = 0;
                    continue;
-               case FORWSW: 
+               case FORWSW:
                    forwsw++;
                    continue;
-               case NFORWSW: 
+               case NFORWSW:
                    forwsw = 0;
                    continue;
 
-               case VERBSW: 
+               case VERBSW:
                    verbsw++;
                    vec[vecp++] = --cp;
                    continue;
@@ -812,32 +1200,36 @@ sendit (char *sp, char **arg, char *file, int pushed)
                    vec[vecp++] = --cp;
                    continue;
 
-               case DEBUGSW: 
+               case DEBUGSW:
                    debugsw++;  /* fall */
-               case NFILTSW: 
-               case FRMTSW: 
-               case NFRMTSW: 
+               case NFILTSW:
+               case FRMTSW:
+               case NFRMTSW:
                case BITSTUFFSW:
                case NBITSTUFFSW:
-               case MIMESW: 
-               case NMIMESW: 
-               case MSGDSW: 
-               case NMSGDSW: 
-               case WATCSW: 
-               case NWATCSW: 
-               case MAILSW: 
-               case SAMLSW: 
-               case SSNDSW: 
-               case SOMLSW: 
-               case SNOOPSW: 
+               case MIMESW:
+               case NMIMESW:
+               case MSGDSW:
+               case NMSGDSW:
+               case WATCSW:
+               case NWATCSW:
+               case MAILSW:
+               case SAMLSW:
+               case SSNDSW:
+               case SOMLSW:
+               case SNOOPSW:
+               case SASLSW:
                    vec[vecp++] = --cp;
                    continue;
 
-               case ALIASW: 
-               case FILTSW: 
-               case WIDTHSW: 
-               case CLIESW: 
-               case SERVSW: 
+               case ALIASW:
+               case FILTSW:
+               case WIDTHSW:
+               case CLIESW:
+               case SERVSW:
+               case SASLMECHSW:
+               case USERSW:
+               case PORTSW:
                    vec[vecp++] = --cp;
                    if (!(cp = *argp++) || *cp == '-') {
                        advise (NULL, "missing argument to %s", argp[-2]);
@@ -846,13 +1238,35 @@ sendit (char *sp, char **arg, char *file, int pushed)
                    vec[vecp++] = cp;
                    continue;
 
-               case SDRFSW: 
-               case SDRMSW: 
+               case SDRFSW:
+               case SDRMSW:
                    if (!(cp = *argp++) || *cp == '-') {
                        advise (NULL, "missing argument to %s", argp[-2]);
                        return;
                    }
-               case SNDRFSW: 
+               case SNDRFSW:
+                   continue;
+
+               case SNDATTACHSW:
+                   if (!(attach = *argp++) || *attach == '-') {
+                       advise (NULL, "missing argument to %s", argp[-2]);
+                       return;
+                   }
+                   continue;
+
+               case SNDATTACHFORMAT:
+                   if (! *argp || **argp == '-')
+                       adios (NULL, "missing argument to %s", argp[-1]);
+                   else {
+                       attachformat = atoi (*argp);
+                       if (attachformat < 0 ||
+                           attachformat > ATTACHFORMATS - 1) {
+                           advise (NULL, "unsupported attachformat %d",
+                                   attachformat);
+                           continue;
+                       }
+                   }
+                   ++argp;
                    continue;
            }
        }
@@ -919,7 +1333,7 @@ sendit (char *sp, char **arg, char *file, int pushed)
     vec[0] = r1bindex (postproc, '/');
     closefds (3);
 
-    if (sendsbr (vec, vecp, file, &st, 1) == OK)
+    if (sendsbr (vec, vecp, file, &st, 1, attach, attachformat) == OK)
        done (0);
 }
 
@@ -938,11 +1352,11 @@ whomfile (char **arg, char *file)
     fflush (stdout);
 
     switch (pid = vfork ()) {
-       case NOTOK: 
+       case NOTOK:
            advise ("fork", "unable to");
            return 1;
 
-       case OK: 
+       case OK:
            vecp = 0;
            vec[vecp++] = r1bindex (whomproc, '/');
            vec[vecp++] = file;
@@ -956,7 +1370,7 @@ whomfile (char **arg, char *file)
            perror (whomproc);
            _exit (-1);         /* NOTREACHED */
 
-       default: 
+       default:
            return (pidwait (pid, NOTOK) & 0377 ? 1 : 0);
     }
 }