Fix uip/whom.c for C89 compatibility
[mmh] / uip / whatnow.c
index 273921c..be046ac 100644 (file)
@@ -4,35 +4,6 @@
 ** 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.
-**
-**  The inclusion of attachments is eased by
-**  using the header field name mechanism added to anno and send.
-**  The header field name for attachments is predefined.
-**
-**  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                   This option lists the attachments on the
-**                                draft.
-**
-**        detach numbers          This option removes attachments by
-**                                attachment number from the draft.
 */
 
 #include <h/mh.h>
 #include <signal.h>
 #include <h/mime.h>
 #include <h/utils.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sysexits.h>
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
 
-static struct swit whatnowswitches[] = {
+static struct swit switches[] = {
 #define EDITRSW  0
        { "editor editor", 0 },
 #define PRMPTSW  1
@@ -53,36 +32,40 @@ static struct swit whatnowswitches[] = {
        { NULL, 0 }
 };
 
+char *version=VERSION;
+
 /*
 ** Options at the "whatnow" prompt
 */
 static struct swit aleqs[] = {
 #define EDITSW  0
-       { "edit [<editor> <switches>]", 0 },
-#define REFILEOPT  1
-       { "refile [<switches>] +folder", 0 },
+       { "edit [editor [switches]]", 0 },
+#define LISTSW  1
+       { "list", 0 },
 #define DISPSW  2
        { "display", 0 },
-#define LISTSW  3
-       { "list", 0 },
+#define WHOMSW  3
+       { "whom", 0 },
 #define SENDSW  4
-       { "send [<switches>]", 0 },
-#define QUITSW  5
-       { "quit", 0 },
+       { "send", 0 },
+#define REFILEOPT  5
+       { "refile +folder", 0 },
 #define DELETESW  6
        { "delete", 0 },
-#define CDCMDSW  7
+#define QUITSW  7
+       { "quit", 0 },
+#define CDCMDSW  8
        { "cd [directory]", 0 },
-#define PWDCMDSW  8
+#define PWDCMDSW  9
        { "pwd", 0 },
-#define LSCMDSW  9
+#define LSCMDSW  10
        { "ls", 0 },
-#define ATTACHCMDSW  10
-       { "attach", 0 },
-#define DETACHCMDSW  11
-       { "detach", 0 },
-#define ALISTCMDSW  12
+#define ALISTCMDSW  11
        { "alist", 0 },
+#define ATTACHCMDSW  12
+       { "attach files", 0 },
+#define DETACHCMDSW  13
+       { "detach numbers", 0 },
        { NULL, 0 }
 };
 
@@ -91,20 +74,20 @@ static char *myprompt = "\nWhat now? ";
 /*
 ** static prototypes
 */
-static int editfile(char **, char **, char *, int);
+static int editfile(char **, char **, char *);
 static int sendfile(char **, char *);
 static int refile(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);
+static void writesomecmd(char *, int, char *, char *, char **);
+static FILE* popen_in_dir(const char *, const char *, const char *);
+static int system_in_dir(const char *, const char *);
 
 
 int
 main(int argc, char **argv)
 {
-       int use = 0;
+       int use = NOUSE;
        char *cp;
        char *ed = NULL, *drft = NULL;
        char buf[BUFSIZ], prompt[BUFSIZ];
@@ -129,50 +112,50 @@ main(int argc, char **argv)
        */
 
        if (!getcwd(cwd, sizeof (cwd))) {
-               adios("getcwd", "could not get working directory");
+               adios(EX_USAGE, "getcwd", "could not get working directory");
        }
 
        while ((cp = *argp++)) {
                if (*cp == '-') {
-                       switch (smatch(++cp, whatnowswitches)) {
+                       switch (smatch(++cp, switches)) {
                        case AMBIGSW:
-                               ambigsw(cp, whatnowswitches);
-                               done(1);
+                               ambigsw(cp, switches);
+                               exit(EX_USAGE);
                        case UNKWNSW:
-                               adios(NULL, "-%s unknown", cp);
+                               adios(EX_USAGE, NULL, "-%s unknown", cp);
 
                        case HELPSW:
                                snprintf(buf, sizeof(buf),
                                                "%s [switches] [file]",
                                                invo_name);
-                               print_help(buf, whatnowswitches, 1);
-                               done(1);
+                               print_help(buf, switches, 1);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
                        case VERSIONSW:
                                print_version(invo_name);
-                               done(1);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
 
                        case EDITRSW:
                                if (!(ed = *argp++) || *ed == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                continue;
 
                        case PRMPTSW:
                                if (!(myprompt = *argp++) || *myprompt == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                continue;
 
                        }
                }
                if (drft)
-                       adios(NULL, "only one draft at a time!");
+                       adios(EX_USAGE, NULL, "only one draft at a time!");
                else
                        drft = cp;
        }
 
        if ((!drft && !(drft = getenv("mhdraft"))) || !*drft)
-               drft = getcpy(m_draft(seq_cur));
+               drft = mh_xstrdup(m_draft(seq_cur));
 
        if ((cp = getenv("mhuse")) && *cp)
                use = atoi(cp);
@@ -183,27 +166,22 @@ main(int argc, char **argv)
 
        /* start editing the draft, unless editor is the empty string */
        if (*ed) {
-               if (editfile(&ed, NULL, drft, use) <0) {
+               if (editfile(&ed, NULL, drft) <0) {
                        if (!use) {
                                unlink(drft);
                        }
-                       advise(NULL, "Try again.");
-                       done(1);
+                       adios(EX_SOFTWARE, NULL, "Try again.");
                }
        }
 
        snprintf(prompt, sizeof(prompt), myprompt, invo_name);
-       for (;;) {
-               if (!(argp = getans(prompt, aleqs))) {
-                       done(1);
-               }
+       while ((argp = getans(prompt, aleqs))) {
                switch (smatch(*argp, aleqs)) {
                case DISPSW:
                        /* display the msg being replied to or distributed */
                        if ((cp = getenv("mhaltmsg")) && *cp) {
-                               snprintf(buf, sizeof buf, "%s '%s'",
-                                               listproc, cp);
-                               system(buf);
+                               execprogl(listproc, listproc, "-file", cp,
+                                               (char *)NULL);
                        } else {
                                advise(NULL, "no alternate message to display");
                        }
@@ -213,13 +191,13 @@ main(int argc, char **argv)
                        /* Call an editor on the draft file */
                        if (*++argp)
                                ed = *argp++;
-                       editfile(&ed, argp, drft, NOUSE);
+                       editfile(&ed, argp, drft);
                        break;
 
                case LISTSW:
                        /* display the draft file */
-                       snprintf(buf, sizeof buf, "%s '%s'", listproc, drft);
-                       system(buf);
+                       execprogl(listproc, listproc, "-file", drft,
+                                       (char *)NULL);
                        break;
 
                case QUITSW:
@@ -227,12 +205,12 @@ main(int argc, char **argv)
                        if (stat(drft, &st) != NOTOK) {
                                advise(NULL, "draft left on %s", drft);
                        }
-                       done(1);
+                       exit(EX_OK);
 
                case DELETESW:
                        /* Delete draft and exit */
                        removefile(drft);
-                       done(1);
+                       exit(EX_OK);
 
                case SENDSW:
                        /* Send draft */
@@ -242,7 +220,7 @@ main(int argc, char **argv)
                case REFILEOPT:
                        /* Refile the draft */
                        if (refile(++argp, drft) == 0) {
-                               done(0);
+                               exit(EX_OK);
                        }
                        break;
 
@@ -296,9 +274,9 @@ main(int argc, char **argv)
                        /*
                        ** List attachments on current draft.
                        */
-                       snprintf(buf, sizeof buf, "anno -list -comp '%s' "
-                                       "-number '%s'", attach_hdr, drft);
-                       if (system(buf) != 0) {
+                       if (execprogl("anno", "anno", "-list", "-comp",
+                                       attach_hdr, "-number", drft,
+                                       (char *)NULL) != 0) {
                                advise(NULL, "Could not list attachment headers.");
                        }
                        break;
@@ -330,34 +308,28 @@ main(int argc, char **argv)
                        ** working directory to relative path names.
                        ** Add the attachment annotation to the draft.
                        */
-                       if ((f = popen_in_dir(cwd, buf, "r"))) {
-                               char buf[BUFSIZ];
+                       if (!(f = popen_in_dir(cwd, buf, "r"))) {
+                               advise("popen", "could not get file from shell");
+                               break;
+                       }
 
-                               while (fgets(shell, sizeof(shell), f)) {
-                                       *(strchr(shell, '\n')) = '\0';
+                       while (fgets(shell, sizeof(shell), f)) {
+                               *(strchr(shell, '\n')) = '\0';
 
-                                       if (*shell == '/')
-                                               sprintf(file, "%s", shell);
-                                       else {
-                                               sprintf(file, "%s/%s", cwd,
-                                                               shell);
-                                       }
-                                       snprintf(buf, sizeof buf,
-                                                       "anno -nodate -append "
-                                                       "-comp '%s' -text '%s'"
-                                                       " '%s'",
-                                                       attach_hdr, file,
-                                                       drft);
-                                       if (system(buf) != 0) {
-                                               advise(NULL, "Could not add attachment header.");
-                                       }
+                               if (*shell == '/')
+                                       sprintf(file, "%s", shell);
+                               else {
+                                       sprintf(file, "%s/%s", cwd, shell);
+                               }
+                               if (execprogl("anno", "anno",
+                                               "-nodate", "-append",
+                                               "-comp", attach_hdr,
+                                               "-text", file,
+                                               drft, (char *)NULL) != 0) {
+                                       advise(NULL, "Could not add attachment header.");
                                }
-
-                               pclose(f);
-                       } else {
-                               advise("popen", "could not get file from shell");
                        }
-
+                       pclose(f);
                        break;
 
                case DETACHCMDSW:
@@ -371,22 +343,20 @@ main(int argc, char **argv)
                        ** that the numbering stays correct.
                        */
                        for (arguments=argp+1; *arguments; arguments++) {
-                               char buf[BUFSIZ];
                                int n;
 
                                if (**arguments == '\0') {
                                        continue;
                                }
 
-                               n = atoi(*arguments);
-                               snprintf(buf, sizeof buf, "anno -delete "
-                                               "-comp '%s' -number '%d' "
-                                               "'%s'",
-                                               attach_hdr, n, drft);
-                               if (system(buf) != 0) {
+                               if (execprogl("anno", "anno", "-delete",
+                                               "-comp", attach_hdr,
+                                               "-number", *arguments, drft,
+                                               (char *)NULL) != 0) {
                                        advise(NULL, "Could not delete attachment header.");
                                }
 
+                               n = atoi(*arguments);
                                for (argp=arguments+1; *argp; argp++) {
                                        if (atoi(*argp) > n) {
                                                if (atoi(*argp) == 1) {
@@ -399,13 +369,19 @@ main(int argc, char **argv)
                        }
                        break;
 
+               case WHOMSW:
+                       /* list recipients */
+                       execprogl("whom", "whom", drft, (char *)NULL);
+                       break;
+
                default:
                        /* Unknown command */
                        advise(NULL, "say what?");
                        break;
                }
        }
-       /*NOTREACHED*/
+
+       exit(EX_IOERR);
 }
 
 
@@ -437,7 +413,7 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp)
        */
        int trailln = strlen(trailcmd) + 3;
        if (ln < 0 || ln + trailln > bufsz)
-               adios(NULL, "arguments too long");
+               adios(EX_USAGE, NULL, "arguments too long");
 
        cp = buf + ln;
 
@@ -445,7 +421,7 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp)
                ln = strlen(*argp);
                /* +1 for leading space */
                if (ln + trailln + 1 > bufsz - (cp-buf))
-                       adios(NULL, "arguments too long");
+                       adios(EX_USAGE, NULL, "arguments too long");
                *cp++ = ' ';
                memcpy(cp, *argp, ln+1);
                cp += ln;
@@ -479,12 +455,12 @@ 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");
+               adios(EX_OSERR, "getcwd", "could not get working directory");
        if (chdir(dir) != 0)
-               adios("chdir", "could not change working directory");
+               adios(EX_OSERR, "chdir", "could not change working directory");
        r = system(cmd);
        if (chdir(olddir) != 0)
-               adios("chdir", "could not change working directory");
+               adios(EX_OSERR, "chdir", "could not change working directory");
        return r;
 }
 
@@ -495,12 +471,12 @@ 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");
+               adios(EX_OSERR, "getcwd", "could not get working directory");
        if (chdir(dir) != 0)
-               adios("chdir", "could not change working directory");
+               adios(EX_OSERR, "chdir", "could not change working directory");
        f = popen(cmd, type);
        if (chdir(olddir) != 0)
-               adios("chdir", "could not change working directory");
+               adios(EX_OSERR, "chdir", "could not change working directory");
        return f;
 }
 
@@ -513,7 +489,7 @@ static char *edsave = NULL;  /* the editor we used previously */
 
 
 static int
-editfile(char **ed, char **arg, char *file, int use)
+editfile(char **ed, char **arg, char *file)
 {
        int pid, status, vecp;
        char *cp, *vec[MAXARGS];
@@ -542,28 +518,28 @@ editfile(char **ed, char **arg, char *file, int use)
        switch (pid = fork()) {
        case NOTOK:
                advise("fork", "unable to");
-               status = NOTOK;
+               status = EX_OSERR;
                break;
 
        case OK:
                vecp = 0;
                vec[vecp++] = mhbasename(*ed);
-               if (arg)
-                       while (*arg)
-                               vec[vecp++] = *arg++;
+               while (arg && *arg) {
+                       vec[vecp++] = *arg++;
+               }
                vec[vecp++] = file;
                vec[vecp] = NULL;
 
                execvp(*ed, vec);
                fprintf(stderr, "%s: unable to exec ", invo_name);
                perror(*ed);
-               _exit(-1);
+               _exit(EX_OSERR);
 
        default:
                if ((status = pidwait(pid, NOTOK))) {
                        if ((status & 0xff00) == 0xff00) {
                                /* cmd not found or pidwait() failed */
-                               status = -1;
+                               status = EX_SOFTWARE;
                                break;
                        }
                        if (status & 0x00ff) {
@@ -581,7 +557,7 @@ editfile(char **ed, char **arg, char *file, int use)
        }
 
        /* remember which editor we used */
-       edsave = getcpy(*ed);
+       edsave = mh_xstrdup(*ed);
 
        *ed = NULL;
 
@@ -596,36 +572,22 @@ editfile(char **ed, char **arg, char *file, int use)
 static int
 sendfile(char **arg, char *file)
 {
-       pid_t child_id;
-       int vecp;
+       int vecp = 0;
        char *vec[MAXARGS];
 
-       context_save();  /* save the context file */
+       context_save();
        fflush(stdout);
 
-       switch (child_id = fork()) {
-       case NOTOK:
-               advise(NULL, "unable to fork, so sending directly...");
-               /* fall */
-       case OK:
-               vecp = 0;
-               vec[vecp++] = invo_name;
-               if (arg)
-                       while (*arg)
-                               vec[vecp++] = *arg++;
-               vec[vecp++] = file;
-               vec[vecp] = NULL;
-
-               execvp("send", vec);
-               fprintf(stderr, "%s: unable to exec ", invo_name);
-               perror("send");
-               _exit(-1);
-
-       default:
-               if (pidwait(child_id, OK) == 0)
-                       done(0);
-               return 1;
+       vec[vecp++] = "send";
+       while (arg && *arg) {
+               vec[vecp++] = *arg++;
        }
+       vec[vecp++] = file;
+       vec[vecp] = NULL;
+       execvp(*vec, vec);
+       fprintf(stderr, "%s: unable to exec ", invo_name);
+       perror("send");
+       _exit(EX_OSERR);
 }
 
 
@@ -635,11 +597,9 @@ sendfile(char **arg, char *file)
 static int
 refile(char **arg, char *file)
 {
-       pid_t pid;
-       register int vecp;
+       int vecp = 0;
        char *vec[MAXARGS];
 
-       vecp = 0;
        vec[vecp++] = "refile";
        vec[vecp++] = "-nolink";  /* override bad .mh_profile defaults */
        vec[vecp++] = "-file";
@@ -650,23 +610,10 @@ refile(char **arg, char *file)
        }
        vec[vecp] = NULL;
 
-       context_save();  /* save the context file */
+       context_save();
        fflush(stdout);
 
-       switch (pid = fork()) {
-       case -1:
-               advise("fork", "unable to");
-               return -1;
-
-       case 0:
-               execvp(*vec, vec);
-               fprintf(stderr, "%s: unable to exec ", invo_name);
-               perror(*vec);
-               _exit(-1);
-
-       default:
-               return (pidwait(pid, -1));
-       }
+       return execprog(*vec, vec);
 }
 
 
@@ -678,7 +625,7 @@ static int
 removefile(char *drft)
 {
        if (unlink(drft) == NOTOK)
-               adios(drft, "unable to unlink");
+               adios(EX_IOERR, drft, "unable to unlink");
 
        return OK;
 }