change RV8, LRV8, and IND8 to use `struct' instead of `double' assignment
[unix-history] / usr / src / usr.bin / mail / cmd3.c
index 092dc8f..44e4b84 100644 (file)
@@ -9,7 +9,7 @@
  * Still more user commands.
  */
 
  * Still more user commands.
  */
 
-static char *SccsId = "@(#)cmd3.c      1.1 %G%";
+static char *SccsId = "@(#)cmd3.c      1.8 %G%";
 
 /*
  * Process a shell escape by saving signals, ignoring signals,
 
 /*
  * Process a shell escape by saving signals, ignoring signals,
@@ -22,7 +22,11 @@ shell(str)
        int (*sig[2])(), stat[1];
        register int t;
        char *Shell;
        int (*sig[2])(), stat[1];
        register int t;
        char *Shell;
+       char cmd[BUFSIZ];
 
 
+       strcpy(cmd, str);
+       if (bangexp(cmd) < 0)
+               return(-1);
        if ((Shell = value("SHELL")) == NOSTR)
                Shell = SHELL;
        for (t = 2; t < 4; t++)
        if ((Shell = value("SHELL")) == NOSTR)
                Shell = SHELL;
        for (t = 2; t < 4; t++)
@@ -32,7 +36,7 @@ shell(str)
                for (t = 2; t < 4; t++)
                        if (sig[t-2] != SIG_IGN)
                                signal(t, SIG_DFL);
                for (t = 2; t < 4; t++)
                        if (sig[t-2] != SIG_IGN)
                                signal(t, SIG_DFL);
-               execl(Shell, Shell, "-c", str, 0);
+               execl(Shell, Shell, "-c", cmd, 0);
                perror(Shell);
                _exit(1);
        }
                perror(Shell);
                _exit(1);
        }
@@ -56,7 +60,6 @@ dosh(str)
        int (*sig[2])(), stat[1];
        register int t;
        char *Shell;
        int (*sig[2])(), stat[1];
        register int t;
        char *Shell;
-
        if ((Shell = value("SHELL")) == NOSTR)
                Shell = SHELL;
        for (t = 2; t < 4; t++)
        if ((Shell = value("SHELL")) == NOSTR)
                Shell = SHELL;
        for (t = 2; t < 4; t++)
@@ -80,6 +83,60 @@ dosh(str)
        return(0);
 }
 
        return(0);
 }
 
+/*
+ * Expand the shell escape by expanding unescaped !'s into the
+ * last issued command where possible.
+ */
+
+char   lastbang[128];
+
+bangexp(str)
+       char *str;
+{
+       char bangbuf[BUFSIZ];
+       register char *cp, *cp2;
+       register int n;
+       int changed = 0;
+
+       cp = str;
+       cp2 = bangbuf;
+       n = BUFSIZ;
+       while (*cp) {
+               if (*cp == '!') {
+                       if (n < strlen(lastbang)) {
+overf:
+                               printf("Command buffer overflow\n");
+                               return(-1);
+                       }
+                       changed++;
+                       strcpy(cp2, lastbang);
+                       cp2 += strlen(lastbang);
+                       n -= strlen(lastbang);
+                       cp++;
+                       continue;
+               }
+               if (*cp == '\\' && cp[1] == '!') {
+                       if (--n <= 1)
+                               goto overf;
+                       *cp2++ = '!';
+                       cp += 2;
+                       changed++;
+               }
+               if (--n <= 1)
+                       goto overf;
+               *cp2++ = *cp++;
+       }
+       *cp2 = 0;
+       if (changed) {
+               printf("!%s\n", bangbuf);
+               fflush(stdout);
+       }
+       strcpy(str, bangbuf);
+       strncpy(lastbang, bangbuf, 128);
+       lastbang[127] = 0;
+       return(0);
+}
+
 /*
  * Print out a nice help message from some file or another.
  */
 /*
  * Print out a nice help message from some file or another.
  */
@@ -142,7 +199,7 @@ respond(msgvec)
        }
        mp = &message[msgvec[0] - 1];
        dot = mp;
        }
        mp = &message[msgvec[0] - 1];
        dot = mp;
-       rcv = nameof(mp);
+       rcv = nameof(mp, 1);
        strcpy(buf, "");
        cp = hfield("to", mp);
        if (cp != NOSTR)
        strcpy(buf, "");
        cp = hfield("to", mp);
        if (cp != NOSTR)
@@ -164,6 +221,7 @@ respond(msgvec)
        head.h_subject = hfield("subject", mp);
        if (head.h_subject == NOSTR)
                head.h_subject = hfield("subj", mp);
        head.h_subject = hfield("subject", mp);
        if (head.h_subject == NOSTR)
                head.h_subject = hfield("subj", mp);
+       head.h_subject = reedit(head.h_subject);
        head.h_cc = NOSTR;
        cp = hfield("cc", mp);
        if (cp != NOSTR) {
        head.h_cc = NOSTR;
        cp = hfield("cc", mp);
        if (cp != NOSTR) {
@@ -177,6 +235,29 @@ respond(msgvec)
        return(0);
 }
 
        return(0);
 }
 
+/*
+ * Modify the subject we are replying to to begin with Re: if
+ * it does not already.
+ */
+
+char *
+reedit(subj)
+       char *subj;
+{
+       char sbuf[10];
+       register char *newsubj;
+
+       if (subj == NOSTR)
+               return(NOSTR);
+       strncpy(sbuf, subj, 3);
+       sbuf[3] = 0;
+       if (icequal(sbuf, "re:"))
+               return(subj);
+       newsubj = salloc(strlen(subj) + 6);
+       sprintf(newsubj, "Re:  %s", subj);
+       return(newsubj);
+}
+
 /*
  * Preserve the named messages, so that they will be sent
  * back to the system mailbox.
 /*
  * Preserve the named messages, so that they will be sent
  * back to the system mailbox.
@@ -413,20 +494,102 @@ null(e)
 }
 
 /*
 }
 
 /*
- * Print out the current edit file, if we are editting.
+ * Print out the current edit file, if we are editing.
  * Otherwise, print the name of the person who's mail
  * we are reading.
  */
 
  * Otherwise, print the name of the person who's mail
  * we are reading.
  */
 
-file(e)
+file(argv)
+       char **argv;
 {
        register char *cp;
 {
        register char *cp;
+       char fname[BUFSIZ];
 
 
-       if (edit)
-               printf("Reading \"%s\"\n", editfile);
-       else
-               printf("Reading %s's mail\n", rindex(mailname, '/') + 1);
-       return(0);
+       if (argv[0] == NOSTR) {
+               newfileinfo();
+               return(0);
+       }
+
+       /*
+        * Acker's!  Must switch to the new file.
+        * We use a funny interpretation --
+        *      # -- gets the previous file
+        *      % -- gets the invoker's post office box
+        *      %user -- gets someone else's post office box
+        *      & -- gets invoker's mbox file
+        *      string -- reads the given file
+        */
+
+       cp = getfilename(argv[0]);
+       if (cp == NOSTR)
+               return(-1);
+       return(setfile(cp, 1));
+}
+
+/*
+ * Evaluate the string given as a new mailbox name.
+ * Ultimately, we want this to support a number of meta characters.
+ * Possibly:
+ *     % -- for my system mail box
+ *     %user -- for user's system mail box
+ *     # -- for previous file
+ *     & -- get's invoker's mbox file
+ *     file name -- for any other file
+ */
+
+char   prevfile[PATHSIZE];
+
+char *
+getfilename(name)
+       char *name;
+{
+       register char *cp;
+       char savename[BUFSIZ];
+       char oldmailname[BUFSIZ];
+
+       switch (*name) {
+       case '%':
+               strcpy(prevfile, mailname);
+               if (name[1] != 0) {
+                       strcpy(savename, myname);
+                       strcpy(oldmailname, mailname);
+                       strncpy(myname, name+1, PATHSIZE-1);
+                       myname[PATHSIZE-1] = 0;
+                       findmail();
+                       cp = savestr(mailname);
+                       strcpy(myname, savename);
+                       strcpy(mailname, oldmailname);
+                       return(cp);
+               }
+               strcpy(oldmailname, mailname);
+               findmail();
+               cp = savestr(mailname);
+               strcpy(mailname, oldmailname);
+               return(cp);
+
+       case '#':
+               if (name[1] != 0)
+                       goto regular;
+               if (prevfile[0] == 0) {
+                       printf("No previous file\n");
+                       return(NOSTR);
+               }
+               cp = savestr(prevfile);
+               strcpy(prevfile, mailname);
+               return(cp);
+
+       case '&':
+               strcpy(prevfile, mailname);
+               if (name[1] == 0)
+                       return(mbox);
+               /* Fall into . . . */
+
+       default:
+regular:
+               strcpy(prevfile, mailname);
+               cp = expand(name);
+               return(cp);
+       }
 }
 
 /*
 }
 
 /*
@@ -464,7 +627,7 @@ Respond(msgvec)
        for (s = 0, ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
                dot = mp;
        for (s = 0, ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
                dot = mp;
-               s += strlen(nameof(mp)) + 1;
+               s += strlen(nameof(mp, 1)) + 1;
        }
        if (s == 0)
                return(0);
        }
        if (s == 0)
                return(0);
@@ -472,7 +635,7 @@ Respond(msgvec)
        head.h_to = cp;
        for (ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
        head.h_to = cp;
        for (ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
-               cp = copy(nameof(mp), cp);
+               cp = copy(nameof(mp, 1), cp);
                *cp++ = ' ';
        }
        *--cp = 0;
                *cp++ = ' ';
        }
        *--cp = 0;
@@ -481,7 +644,7 @@ Respond(msgvec)
        head.h_seq = 0;
        if (subject == NOSTR)
                subject = hfield("subj", mp);
        head.h_seq = 0;
        if (subject == NOSTR)
                subject = hfield("subj", mp);
-       head.h_subject = subject;
+       head.h_subject = reedit(subject);
        if (subject != NOSTR)
                head.h_seq++;
        head.h_cc = NOSTR;
        if (subject != NOSTR)
                head.h_seq++;
        head.h_cc = NOSTR;
@@ -489,3 +652,79 @@ Respond(msgvec)
        mail1(&head);
        return(0);
 }
        mail1(&head);
        return(0);
 }
+
+/*
+ * Conditional commands.  These allow one to parameterize one's
+ * .mailrc and do some things if sending, others if receiving.
+ */
+
+ifcmd(argv)
+       char **argv;
+{
+       register char *cp;
+
+       if (cond != CANY) {
+               printf("Illegal nested \"if\"\n");
+               return(1);
+       }
+       cond = CANY;
+       cp = argv[0];
+       switch (*cp) {
+       case 'r': case 'R':
+               cond = CRCV;
+               break;
+
+       case 's': case 'S':
+               cond = CSEND;
+               break;
+
+       default:
+               printf("Unrecognized if-keyword: \"%s\"\n", cp);
+               return(1);
+       }
+       return(0);
+}
+
+/*
+ * Implement 'else'.  This is pretty simple -- we just
+ * flip over the conditional flag.
+ */
+
+elsecmd()
+{
+
+       switch (cond) {
+       case CANY:
+               printf("\"Else\" without matching \"if\"\n");
+               return(1);
+
+       case CSEND:
+               cond = CRCV;
+               break;
+
+       case CRCV:
+               cond = CSEND;
+               break;
+
+       default:
+               printf("Mail's idea of conditions is screwed up\n");
+               cond = CANY;
+               break;
+       }
+       return(0);
+}
+
+/*
+ * End of if statement.  Just set cond back to anything.
+ */
+
+endifcmd()
+{
+
+       if (cond == CANY) {
+               printf("\"Endif\" without matching \"if\"\n");
+               return(1);
+       }
+       cond = CANY;
+       return(0);
+}