BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / mail / main.c
index 3a500f6..0a8cc7d 100644 (file)
@@ -2,23 +2,44 @@
  * Copyright (c) 1980 Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1980 Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
  */
 
-#ifdef notdef
+#ifndef lint
 char copyright[] =
 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  All rights reserved.\n";
 char copyright[] =
 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  All rights reserved.\n";
-#endif /* notdef */
+#endif /* not lint */
 
 
-#ifdef notdef
-static char sccsid[] = "@(#)main.c     5.6 (Berkeley) %G%";
-#endif /* notdef */
+#ifndef lint
+static char sccsid[] = "@(#)main.c     5.28 (Berkeley) 4/1/91";
+#endif /* not lint */
 
 #include "rcv.h"
 #include <sys/stat.h>
 
 #include "rcv.h"
 #include <sys/stat.h>
@@ -31,91 +52,61 @@ static char sccsid[] = "@(#)main.c  5.6 (Berkeley) %G%";
 
 jmp_buf        hdrjmp;
 
 
 jmp_buf        hdrjmp;
 
-/*
- * Find out who the user is, copy his mail file (if exists) into
- * /tmp/Rxxxxx and set up the message pointers.  Then, print out the
- * message headers and read user commands.
- *
- * Command line syntax:
- *     Mail [ -i ] [ -r address ] [ -h number ] [ -f [ name ] ]
- * or:
- *     Mail [ -i ] [ -r address ] [ -h number ] people ...
- */
-
 main(argc, argv)
        char **argv;
 {
 main(argc, argv)
        char **argv;
 {
-       register char *ef, opt;
        register int i;
        struct name *to, *cc, *bcc, *smopts;
        register int i;
        struct name *to, *cc, *bcc, *smopts;
-       int  mustsend, hdrstop(), (*prevint)(), f;
-       struct sgttyb tbuf;
+       char *subject;
+       char *ef;
+       char nosrc = 0;
+       void hdrstop();
+       sig_t prevint;
        extern int getopt(), optind, opterr;
        extern char *optarg;
        extern int getopt(), optind, opterr;
        extern char *optarg;
+       void sigchild();
 
        /*
         * Set up a reasonable environment.
 
        /*
         * Set up a reasonable environment.
-        * Figure out whether we are being run interactively, set up
-        * all the temporary files, buffer standard output, and so forth.
+        * Figure out whether we are being run interactively,
+        * start the SIGCHLD catcher, and so forth.
         */
         */
-
-#ifdef GETHOST
-       inithost();
-#endif GETHOST
-       mypid = getpid();
-       intty = isatty(0);
-       outtty = isatty(1);
-       if (outtty) {
-               gtty(1, &tbuf);
-               baud = tbuf.sg_ospeed;
-       } else
-               baud = B9600;
+       (void) signal(SIGCHLD, sigchild);
+       if (isatty(0))
+               assign("interactive", "");
        image = -1;
        image = -1;
-
        /*
         * Now, determine how we are being used.
        /*
         * Now, determine how we are being used.
-        * We successively pick off instances of -r, -h, -f, and -i.
-        * If called as "rmail" we note this fact for letter sending.
+        * We successively pick off - flags.
         * If there is anything left, it is the base of the list
         * of users to mail to.  Argp will be set to point to the
         * first of these users.
         */
         * If there is anything left, it is the base of the list
         * of users to mail to.  Argp will be set to point to the
         * first of these users.
         */
-
        ef = NOSTR;
        ef = NOSTR;
-       to = NULL;
-       cc = NULL;
-       bcc = NULL;
-       smopts = NULL;
-       mustsend = 0;
-       if (argc > 0 && **argv == 'r')
-               rmail++;
-       while ((opt = getopt(argc, argv, "INT:b:c:dfh:inr:s:u:v")) != EOF) {
-               switch (opt) {
-               case 'r':
-                       /*
-                        * Next argument is address to be sent along
-                        * to the mailer.
-                        */
-                       mustsend++;
-                       rflag = optarg;
-                       break;
+       to = NIL;
+       cc = NIL;
+       bcc = NIL;
+       smopts = NIL;
+       subject = NOSTR;
+       while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) {
+               switch (i) {
                case 'T':
                        /*
                         * Next argument is temp file to write which
                         * articles have been read/deleted for netnews.
                         */
                        Tflag = optarg;
                case 'T':
                        /*
                         * Next argument is temp file to write which
                         * articles have been read/deleted for netnews.
                         */
                        Tflag = optarg;
-                       if ((f = creat(Tflag, 0600)) < 0) {
+                       if ((i = creat(Tflag, 0600)) < 0) {
                                perror(Tflag);
                                exit(1);
                        }
                                perror(Tflag);
                                exit(1);
                        }
-                       close(f);
+                       close(i);
                        break;
                case 'u':
                        /*
                         * Next argument is person to pretend to be.
                         */
                        break;
                case 'u':
                        /*
                         * Next argument is person to pretend to be.
                         */
-                       strcpy(myname, optarg);
+                       myname = optarg;
                        break;
                case 'i':
                        /*
                        break;
                case 'i':
                        /*
@@ -127,42 +118,27 @@ main(argc, argv)
                case 'd':
                        debug++;
                        break;
                case 'd':
                        debug++;
                        break;
-               case 'h':
-                       /*
-                        * Specified sequence number for network.
-                        * This is the number of "hops" made so
-                        * far (count of times message has been
-                        * forwarded) to help avoid infinite mail loops.
-                        */
-                       mustsend++;
-                       hflag = atoi(optarg);
-                       if (hflag == 0) {
-                               fprintf(stderr, "-h needs non-zero number\n");
-                               exit(1);
-                       }
-                       break;
                case 's':
                        /*
                         * Give a subject field for sending from
                         * non terminal
                         */
                case 's':
                        /*
                         * Give a subject field for sending from
                         * non terminal
                         */
-                       mustsend++;
-                       sflag = optarg;
+                       subject = optarg;
                        break;
                case 'f':
                        /*
                         * User is specifying file to "edit" with Mail,
                         * as opposed to reading system mailbox.
                         * If no argument is given after -f, we read his
                        break;
                case 'f':
                        /*
                         * User is specifying file to "edit" with Mail,
                         * as opposed to reading system mailbox.
                         * If no argument is given after -f, we read his
-                        * mbox file in his home directory.
+                        * mbox file.
                         *
                         * getopt() can't handle optional arguments, so here
                         * is an ugly hack to get around it.
                         */
                         *
                         * getopt() can't handle optional arguments, so here
                         * is an ugly hack to get around it.
                         */
-                       if ((argv[optind]) && (argv[optind][0] != '-')) 
+                       if ((argv[optind]) && (argv[optind][0] != '-'))
                                ef = argv[optind++];
                        else
                                ef = argv[optind++];
                        else
-                               ef = mbox;
+                               ef = "&";
                        break;
                case 'n':
                        /*
                        break;
                case 'n':
                        /*
@@ -174,7 +150,7 @@ main(argc, argv)
                        /*
                         * Avoid initial header printing.
                         */
                        /*
                         * Avoid initial header printing.
                         */
-                       noheader++;
+                       assign("noheader", "");
                        break;
                case 'v':
                        /*
                        break;
                case 'v':
                        /*
@@ -186,115 +162,97 @@ main(argc, argv)
                        /*
                         * We're interactive
                         */
                        /*
                         * We're interactive
                         */
-                       intty = 1;
+                       assign("interactive", "");
                        break;
                case 'c':
                        /*
                         * Get Carbon Copy Recipient list
                         */
                        break;
                case 'c':
                        /*
                         * Get Carbon Copy Recipient list
                         */
-                       cc = cat(cc, nalloc(optarg));
-                       mustsend++;
+                       cc = cat(cc, nalloc(optarg, GCC));
                        break;
                case 'b':
                        /*
                         * Get Blind Carbon Copy Recipient list
                         */
                        break;
                case 'b':
                        /*
                         * Get Blind Carbon Copy Recipient list
                         */
-                       bcc = cat(bcc, nalloc(optarg));
-                       mustsend++;
+                       bcc = cat(bcc, nalloc(optarg, GBCC));
                        break;
                case '?':
                        break;
                case '?':
-                       fputs("Usage: XXX\n", stderr);
+                       fputs("\
+Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
+            [- sendmail-options ...]\n\
+       mail [-iInNv] -f [name]\n\
+       mail [-iInNv] [-u user]\n",
+                               stderr);
                        exit(1);
                }
        }
                        exit(1);
                }
        }
-       for (i = optind; (argv[i]) && (*argv[i] != '-'); i++) 
-               to = cat(to, nalloc(argv[i]));
+       for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
+               to = cat(to, nalloc(argv[i], GTO));
        for (; argv[i]; i++)
        for (; argv[i]; i++)
-               smopts = cat(smopts, nalloc(argv[i]));
+               smopts = cat(smopts, nalloc(argv[i], 0));
        /*
         * Check for inconsistent arguments.
         */
        /*
         * Check for inconsistent arguments.
         */
-       if (!to && (cc || bcc)) {
-               fputs("You must also specify direct recipients of mail.\n", stderr);
+       if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) {
+               fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr);
                exit(1);
        }
                exit(1);
        }
-       if ((ef != NOSTR) && to) {
+       if (ef != NOSTR && to != NIL) {
                fprintf(stderr, "Cannot give -f and people to send to.\n");
                exit(1);
        }
                fprintf(stderr, "Cannot give -f and people to send to.\n");
                exit(1);
        }
-       if (mustsend && !to) {
-               fprintf(stderr, "The flags you gave make no sense since you're not sending mail.\n");
-               exit(1);
-       }
        tinit();
        setscreensize();
        input = stdin;
        rcvmode = !to;
        tinit();
        setscreensize();
        input = stdin;
        rcvmode = !to;
+       spreserve();
        if (!nosrc)
        if (!nosrc)
-               load(MASTER);
-       load(mailrc);
+               load(_PATH_MASTER_RC);
+       /*
+        * Expand returns a savestr, but load only uses the file name
+        * for fopen, so it's safe to do this.
+        */
+       load(expand("~/.mailrc"));
        if (!rcvmode) {
        if (!rcvmode) {
-               mail(to, cc, bcc, smopts);
-
+               mail(to, cc, bcc, smopts, subject);
                /*
                 * why wait?
                 */
                /*
                 * why wait?
                 */
-
                exit(senderr);
        }
                exit(senderr);
        }
-
        /*
         * Ok, we are reading mail.
         * Decide whether we are editing a mailbox or reading
         * the system mailbox, and open up the right stuff.
         */
        /*
         * Ok, we are reading mail.
         * Decide whether we are editing a mailbox or reading
         * the system mailbox, and open up the right stuff.
         */
+       if (ef == NOSTR)
+               ef = "%";
+       if (setfile(ef) < 0)
+               exit(1);                /* error already reported */
+       if (setjmp(hdrjmp) == 0) {
+               extern char *version;
 
 
-       if (ef != NOSTR) {
-               char *ename;
-
-               edit++;
-               ename = expand(ef);
-               if (ename != ef) {
-                       ef = malloc((unsigned) strlen(ename) + 1);
-                       strcpy(ef, ename);
-               }
-               editfile = ef;
-               strcpy(mailname, ef);
-       }
-       if (setfile(mailname, edit) < 0) {
-               if (edit)
-                       perror(mailname);
-               else
-                       fprintf(stderr, "No mail for %s\n", myname);
-               exit(1);
-       }
-       if (!noheader && value("noheader") == NOSTR) {
-               if (setjmp(hdrjmp) == 0) {
-                       if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
-                               signal(SIGINT, hdrstop);
-                       announce(!0);
-                       fflush(stdout);
-                       signal(SIGINT, prevint);
-               }
-       }
-       if (!edit && msgCount == 0) {
-               printf("No mail\n");
+               if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
+                       signal(SIGINT, hdrstop);
+               if (value("quiet") == NOSTR)
+                       printf("Mail version %s.  Type ? for help.\n",
+                               version);
+               announce();
                fflush(stdout);
                fflush(stdout);
-               exit(0);
+               signal(SIGINT, prevint);
        }
        commands();
        }
        commands();
-       if (!edit) {
-               signal(SIGHUP, SIG_IGN);
-               signal(SIGINT, SIG_IGN);
-               signal(SIGQUIT, SIG_IGN);
-               quit();
-       }
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       quit();
        exit(0);
 }
 
 /*
  * Interrupt printing of the headers.
  */
        exit(0);
 }
 
 /*
  * Interrupt printing of the headers.
  */
+void
 hdrstop()
 {
 
 hdrstop()
 {
 
@@ -304,7 +262,7 @@ hdrstop()
 }
 
 /*
 }
 
 /*
- * Compute what the screen size should be.
+ * Compute what the screen size for printing headers should be.
  * We use the following algorithm for the height:
  *     If baud rate < 1200, use  9
  *     If baud rate = 1200, use 14
  * We use the following algorithm for the height:
  *     If baud rate < 1200, use  9
  *     If baud rate = 1200, use 14
@@ -313,26 +271,23 @@ hdrstop()
  */
 setscreensize()
 {
  */
 setscreensize()
 {
-#ifdef TIOCGWINSZ
+       struct sgttyb tbuf;
        struct winsize ws;
 
        struct winsize ws;
 
-       if (ioctl(fileno(stdout), TIOCGWINSZ, (char *) &ws) < 0)
+       if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
                ws.ws_col = ws.ws_row = 0;
                ws.ws_col = ws.ws_row = 0;
-#endif
-       if (baud < B1200)
+       if (ioctl(1, TIOCGETP, &tbuf) < 0)
+               tbuf.sg_ospeed = B9600;
+       if (tbuf.sg_ospeed < B1200)
                screenheight = 9;
                screenheight = 9;
-       else if (baud == B1200)
+       else if (tbuf.sg_ospeed == B1200)
                screenheight = 14;
                screenheight = 14;
-#ifdef TIOCGWINSZ
        else if (ws.ws_row != 0)
                screenheight = ws.ws_row;
        else if (ws.ws_row != 0)
                screenheight = ws.ws_row;
-#endif
        else
                screenheight = 24;
        else
                screenheight = 24;
-#ifdef TIOCGWINSZ
-       if (ws.ws_col != 0)
-               screenwidth = ws.ws_col;
-       else
-#endif
+       if ((realscreenheight = ws.ws_row) == 0)
+               realscreenheight = 24;
+       if ((screenwidth = ws.ws_col) == 0)
                screenwidth = 80;
 }
                screenwidth = 80;
 }