Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Feb 2001 19:27:20 -0500 (EST)
From:      Mike Heffner <mheffner@vt.edu>
To:        FreeBSD-audit <FreeBSD-audit@freebsd.org>
Subject:   mail(1) cleanup patch
Message-ID:  <XFMail.20010215192720.mheffner@vt.edu>

next in thread | raw e-mail | index | archive | help
This message is in MIME format
--_=XFMail.1.4.7.FreeBSD:20010215192720:87326=_
Content-Type: text/plain; charset=us-ascii

The following patch to mail(1) is a combination of changes taken from OpenBSD
and NetBSD, as well as a few of my one. The patch addresses the following:

- remove panic() in favor of err(3) and use err(3) functions
  consistently throughout
- use stat(2)'s S_IS* macros rather than S_IF*
- [r]index -> str[r]chr
- convert some static buffers to dynamic ones
- use real tempfiles rather than reopening the same templates
- rename some functions that clash with libc
- convert wait_status from union to int and use wait(2)
  status macros
- fix multiple potential buffer overflows

as well as some misc. cleanups. I'd also like to eventually do a style(9)
cleanup patch (NOSTR -> NULL, kill register, whitespace fixes, ...) so that
diffs are somewhat closer with the other BSDs.

(also at http://filebox.vt.edu/users/mheffner/patches/mail.patch)


Index: aux.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/aux.c,v
retrieving revision 1.4
diff -u -r1.4 aux.c
--- aux.c       1997/07/24 06:56:33     1.4
+++ aux.c       2001/02/15 21:31:40
@@ -81,38 +81,6 @@
 }
 
 /*
- * Announce a fatal error and die.
- */
-#if __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-void
-#if __STDC__
-panic(const char *fmt, ...)
-#else
-panic(fmt, va_alist)
-       char *fmt;
-        va_dcl
-#endif
-{
-       va_list ap;
-#if __STDC__
-       va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
-       (void)fprintf(stderr, "panic: ");
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       (void)fprintf(stderr, "\n");
-       fflush(stderr);
-       abort();
-}
-
-/*
  * Touch the named message by setting its MTOUCH flag.
  * Touched messages have the effect of not being sent
  * back to the system mailbox on exit.
@@ -139,7 +107,7 @@
 
        if (stat(name, &sbuf) < 0)
                return(0);
-       return((sbuf.st_mode & S_IFMT) == S_IFDIR);
+       return(S_ISDIR(sbuf.st_mode));
 }
 
 /*
@@ -270,18 +238,24 @@
 
 /*
  * Copy a string, lowercasing it as we go.
+ * dsize: space left in buffer (including space for NULL)
  */
 void
-istrcpy(dest, src)
+istrncpy(dest, src, dsize)
        register char *dest, *src;
+       size_t dsize;
 {
 
-       do {
-               if (isupper(*src))
-                       *dest++ = tolower(*src);
-               else
-                       *dest++ = *src;
-       } while (*src++ != 0);
+       if (dsize != 0) {
+               while (--dsize != 0 && *src) {
+                       if (isupper(*src))
+                               *dest++ = tolower(*src);
+                       else
+                               *dest++ = *src;
+                       src++;
+               }
+               *dest = '\0';
+       }
 }
 
 /*
@@ -314,7 +288,7 @@
        if ((cp = expand(*arglist)) == NOSTR)
                return(1);
        if ((fi = Fopen(cp, "r")) == NULL) {
-               perror(cp);
+               warn("%s", cp);
                return(1);
        }
        if (ssp >= SSTACK_SIZE - 1) {
@@ -408,7 +382,7 @@
        cp = skin(name1(mp, reptype));
        if (reptype != 0 || charcount(cp, '!') < 2)
                return(cp);
-       cp2 = rindex(cp, '!');
+       cp2 = strrchr(cp, '!');
        cp2--;
        while (cp2 > cp && *cp2 != '!')
                cp2--;
@@ -454,15 +428,18 @@
 {
        register int c;
        register char *cp, *cp2;
-       char *bufend;
+       char *bufend, *nbuf;
        int gotlt, lastsp;
-       char nbuf[BUFSIZ];
 
        if (name == NOSTR)
                return(NOSTR);
-       if (index(name, '(') == NOSTR && index(name, '<') == NOSTR
-           && index(name, ' ') == NOSTR)
+       if (strchr(name, '(') == NOSTR && strchr(name, '<') == NOSTR
+           && strchr(name, ' ') == NOSTR)
                return(name);
+
+       /* We assume that length(input) <= length(output) */
+       if ((nbuf = (char *)malloc(strlen(name) + 1)) == NULL)
+               errx(1, "Out of memory");
        gotlt = 0;
        lastsp = 0;
        bufend = nbuf;
@@ -546,7 +523,9 @@
        }
        *cp2 = 0;
 
-       return(savestr(nbuf));
+       if ((nbuf = (char *)realloc(nbuf, strlen(nbuf) + 1)) == NULL)
+               errx(1, "Out of memory");
+       return(nbuf);
 }
 
 /*
@@ -586,24 +565,25 @@
        *cp2 = '\0';
        if (readline(ibuf, linebuf, LINESIZE) < 0)
                return(savestr(namebuf));
-       if ((cp = index(linebuf, 'F')) == NULL)
+       if ((cp = strchr(linebuf, 'F')) == NULL)
                return(savestr(namebuf));
        if (strncmp(cp, "From", 4) != 0)
                return(savestr(namebuf));
-       while ((cp = index(cp, 'r')) != NULL) {
+       while ((cp = strchr(cp, 'r')) != NULL) {
                if (strncmp(cp, "remote", 6) == 0) {
-                       if ((cp = index(cp, 'f')) == NULL)
+                       if ((cp = strchr(cp, 'f')) == NULL)
                                break;
                        if (strncmp(cp, "from", 4) != 0)
                                break;
-                       if ((cp = index(cp, ' ')) == NULL)
+                       if ((cp = strchr(cp, ' ')) == NULL)
                                break;
                        cp++;
                        if (first) {
-                               strcpy(namebuf, cp);
+                               cp2 = namebuf;
                                first = 0;
                        } else
-                               strcpy(rindex(namebuf, '!')+1, cp);
+                               cp2 = strrchr(namebuf, '!') + 1;
+                       strlcpy(cp2, cp, sizeof(namebuf) - (cp2 - namebuf) - 1);
                        strcat(namebuf, "!");
                        goto newname;
                }
@@ -637,23 +617,18 @@
        register char *s1, *s2;
 {
 
-       while (*s1)
-               if (index(s2, *s1++))
-                       return 1;
-       return 0;
+       return(strpbrk(s2, s1) != NULL);
 }
 
 /*
  * Convert c to upper case
  */
 int
-raise(c)
+upcase(c)
        register int c;
 {
 
-       if (islower(c))
-               return toupper(c);
-       return c;
+       return toupper(c);
 }
 
 /*
@@ -677,7 +652,7 @@
        char *field;
        struct ignoretab ignore[2];
 {
-       char realfld[BUFSIZ];
+       char realfld[LINESIZE];
 
        if (ignore == ignoreall)
                return 1;
@@ -685,7 +660,7 @@
         * Lower-case the string, so that "Status" and "status"
         * will hash to the same place.
         */
-       istrcpy(realfld, field);
+       istrncpy(realfld, field, sizeof(realfld));
        if (ignore[1].i_count > 0)
                return (!member(realfld, ignore + 1));
        else
Index: cmd1.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/cmd1.c,v
retrieving revision 1.3
diff -u -r1.3 cmd1.c
--- cmd1.c      1998/07/06 21:01:17     1.3
+++ cmd1.c      2001/02/15 21:31:40
@@ -316,7 +316,7 @@
                                cp = _PATH_MORE;
                        obuf = Popen(cp, "w");
                        if (obuf == NULL) {
-                               perror(cp);
+                               warn("%s", cp);
                                obuf = stdout;
                        } else
                                signal(SIGPIPE, brokpipe);
@@ -328,7 +328,7 @@
                dot = mp;
                if (value("quiet") == NOSTR)
                        fprintf(obuf, "Message %d:\n", *ip);
-               (void) send(mp, obuf, doign ? ignore : 0, NOSTR);
+               (void) sendmessage(mp, obuf, doign ? ignore : 0, NOSTR);
        }
 close_pipe:
        if (obuf != stdout) {
@@ -387,7 +387,7 @@
                if (!lineb)
                        printf("\n");
                for (lines = 0; lines < c && lines <= topl; lines++) {
-                       if (readline(ibuf, linebuf, LINESIZE) < 0)
+                       if (readline(ibuf, linebuf, sizeof(linebuf)) < 0)
                                break;
                        puts(linebuf);
                        lineb = blankline(linebuf);
@@ -437,10 +437,10 @@
 int
 folders()
 {
-       char dirname[BUFSIZ];
+       char dirname[PATHSIZE];
        char *cmd;
 
-       if (getfold(dirname) < 0) {
+       if (getfold(dirname, sizeof(dirname)) < 0) {
                printf("No value set for \"folder\"\n");
                return 1;
        }
Index: cmd2.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/cmd2.c,v
retrieving revision 1.5
diff -u -r1.5 cmd2.c
--- cmd2.c      1998/10/10 19:21:39     1.5
+++ cmd2.c      2001/02/15 21:31:40
@@ -187,14 +187,14 @@
        else
                disp = "[New file]";
        if ((obuf = Fopen(file, "a")) == NULL) {
-               perror(NOSTR);
+               warn(NOSTR);
                return(1);
        }
        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                mp = &message[*ip - 1];
                touch(mp);
-               if (send(mp, obuf, ignore, NOSTR) < 0) {
-                       perror(file);
+               if (sendmessage(mp, obuf, ignore, NOSTR) < 0) {
+                       warn("%s", file);
                        Fclose(obuf);
                        return(1);
                }
@@ -203,7 +203,7 @@
        }
        fflush(obuf);
        if (ferror(obuf))
-               perror(file);
+               warn("%s", file);
        Fclose(obuf);
        printf("%s\n", disp);
        return(0);
@@ -367,11 +367,11 @@
 core()
 {
        int pid;
-       extern union wait wait_status;
+       extern int wait_status;
 
        switch (pid = fork()) {
        case -1:
-               perror("fork");
+               warn("fork");
                return(1);
        case 0:
                abort();
@@ -380,7 +380,7 @@
        printf("Okie dokie");
        fflush(stdout);
        wait_child(pid);
-       if (wait_status.w_coredump)
+       if (WIFSIGNALED(wait_status) && WCOREDUMP(wait_status))
                printf(" -- Core dumped.\n");
        else
                printf(" -- Can't dump core.\n");
@@ -467,7 +467,7 @@
        struct ignoretab *tab;
        char *which;
 {
-       char field[BUFSIZ];
+       char field[LINESIZE];
        register int h;
        register struct ignore *igp;
        char **ap;
@@ -475,7 +475,7 @@
        if (*list == NOSTR)
                return igshow(tab, which);
        for (ap = list; *ap != 0; ap++) {
-               istrcpy(field, *ap);
+               istrncpy(field, *ap, sizeof(field));
                if (member(field, tab))
                        continue;
                h = hash(field);
Index: cmd3.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/cmd3.c,v
retrieving revision 1.4
diff -u -r1.4 cmd3.c
--- cmd3.c      1998/07/06 21:01:19     1.4
+++ cmd3.c      2001/02/15 21:31:41
@@ -56,9 +56,10 @@
        char *shell;
        char cmd[BUFSIZ];
 
-       (void) strcpy(cmd, str);
-       if (bangexp(cmd) < 0)
+       if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd))
                return 1;
+       if (bangexp(cmd, sizeof(cmd)) < 0)
+               return 1;
        if ((shell = value("SHELL")) == NOSTR)
                shell = _PATH_CSHELL;
        (void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR);
@@ -90,21 +91,20 @@
  * Expand the shell escape by expanding unescaped !'s into the
  * last issued command where possible.
  */
-
-char   lastbang[128];
-
 int
-bangexp(str)
+bangexp(str, strsize)
        char *str;
+       size_t strsize;
 {
        char bangbuf[BUFSIZ];
+       static char lastbang[BUFSIZ];
        register char *cp, *cp2;
        register int n;
        int changed = 0;
 
        cp = str;
        cp2 = bangbuf;
-       n = BUFSIZ;
+       n = sizeof(bangbuf);
        while (*cp) {
                if (*cp == '!') {
                        if (n < strlen(lastbang)) {
@@ -113,7 +113,7 @@
                                return(-1);
                        }
                        changed++;
-                       strcpy(cp2, lastbang);
+                       strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 -
bangbuf));
                        cp2 += strlen(lastbang);
                        n -= strlen(lastbang);
                        cp++;
@@ -135,9 +135,8 @@
                printf("!%s\n", bangbuf);
                fflush(stdout);
        }
-       strcpy(str, bangbuf);
-       strncpy(lastbang, bangbuf, 128);
-       lastbang[127] = 0;
+       strlcpy(str, bangbuf, strsize);
+       strlcpy(lastbang, bangbuf, sizeof(lastbang));
        return(0);
 }
 
@@ -152,7 +151,7 @@
        register FILE *f;
 
        if ((f = Fopen(_PATH_HELP, "r")) == NULL) {
-               perror(_PATH_HELP);
+               warn("%s", _PATH_HELP);
                return(1);
        }
        while ((c = getc(f)) != EOF)
@@ -170,13 +169,15 @@
 {
        char *cp;
 
-       if (*arglist == NOSTR)
+       if (*arglist == NOSTR) {
+               if (homedir == NOSTR)
+                       return(1);
                cp = homedir;
-       else
+       } else
                if ((cp = expand(*arglist)) == NOSTR)
                        return(1);
        if (chdir(cp) < 0) {
-               perror(cp);
+               warn("%s", cp);
                return(1);
        }
        return 0;
@@ -276,8 +277,7 @@
            subj[2] == ':')
                return subj;
        newsubj = salloc(strlen(subj) + 5);
-       strcpy(newsubj, "Re: ");
-       strcpy(newsubj + 4, subj);
+       sprintf(newsubj, "Re: %s", subj);
        return newsubj;
 }
 
@@ -386,7 +386,7 @@
        for (ap = arglist; *ap != NOSTR; ap++) {
                cp = *ap;
                cp2 = varbuf;
-               while (*cp != '=' && *cp != '\0')
+               while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp
!= '\0')
                        *cp2++ = *cp++;
                *cp2 = '\0';
                if (*cp == '\0')
Index: collect.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/collect.c,v
retrieving revision 1.4
diff -u -r1.4 collect.c
--- collect.c   1998/10/10 09:58:20     1.4
+++ collect.c   2001/02/15 21:31:41
@@ -74,10 +74,9 @@
        int printheaders;
 {
        FILE *fbuf;
-       int lc, cc, escape, eofcount;
+       int lc, cc, escape, eofcount, fd;
        register int c, t;
-       char linebuf[LINESIZE], *cp;
-       extern char *tempMail;
+       char linebuf[LINESIZE], tempname[PATHSIZE], *cp;
        char getsub;
        int omask;
        void collint(), collhup(), collstop();
@@ -96,17 +95,19 @@
        savettou = signal(SIGTTOU, collstop);
        savettin = signal(SIGTTIN, collstop);
        if (setjmp(collabort) || setjmp(colljmp)) {
-               rm(tempMail);
+               rm(tempname);
                goto err;
        }
        sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP)));
 
        noreset++;
-       if ((collf = Fopen(tempMail, "w+")) == NULL) {
-               perror(tempMail);
+       snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir);
+       if ((fd = mkstemp(tempname)) == -1 ||
+           (collf = Fdopen(fd, "w+")) == NULL) {
+               warn("%s", tempname);
                goto err;
        }
-       unlink(tempMail);
+       rm(tempname);
 
        /*
         * If we are going to prompt for a subject,
@@ -261,7 +262,11 @@
                        hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC));
                        break;
                case 'd':
-                       strcpy(linebuf + 2, getdeadletter());
+                       if (strlcpy(linebuf + 2, getdeadletter(),
sizeof(linebuf) - 2)
+                           >= sizeof(linebuf) - 2) {
+                               printf("Line buffer overflow\n");
+                               break;
+                       }
                        /* fall into . . . */
                case 'r':
                        /*
@@ -284,7 +289,7 @@
                                break;
                        }
                        if ((fbuf = Fopen(cp, "r")) == NULL) {
-                               perror(cp);
+                               warn("%s", cp);
                                break;
                        }
                        printf("\"%s\" ", cp);
@@ -328,12 +333,12 @@
                         * standard list processing garbage.
                         * If ~f is given, we don't shift over.
                         */
-                       if (forward(linebuf + 2, collf, c) < 0)
+                       if (forward(linebuf + 2, collf, tempname, c) < 0)
                                goto err;
                        goto cont;
                case '?':
                        if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) {
-                               perror(_PATH_TILDE);
+                               warn("%s", _PATH_TILDE);
                                break;
                        }
                        while ((t = getc(fbuf)) != EOF)
@@ -410,14 +415,14 @@
                printf("\"%s\" ", name);
                fflush(stdout);
        }
-       if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) {
+       if (stat(name, &junk) >= 0 && S_ISREG(junk.st_mode)) {
                if (!f)
                        fprintf(stderr, "%s: ", name);
-               fprintf(stderr, "File exists\n");
+               fprintf(stderr, "File exists\n");               
                return(-1);
        }
        if ((of = Fopen(name, "w")) == NULL) {
-               perror(NOSTR);
+               warn(NOSTR);
                return(-1);
        }
        lc = 0;
@@ -428,7 +433,7 @@
                        lc++;
                (void) putc(c, of);
                if (ferror(of)) {
-                       perror(name);
+                       warn("%s", name);
                        Fclose(of);
                        return(-1);
                }
@@ -471,15 +476,17 @@
        char cmd[];
 {
        FILE *nf;
+       int fd;
        sig_t sigint = signal(SIGINT, SIG_IGN);
-       extern char *tempEdit;
-       char *shell;
+       char *shell, tempname[PATHSIZE];
 
-       if ((nf = Fopen(tempEdit, "w+")) == NULL) {
-               perror(tempEdit);
+       snprintf(tempname, sizeof(tempname), "%s/mail.ReXXXXXXXXXX", tmpdir);
+       if ((fd = mkstemp(tempname)) == -1 ||
+           (nf = Fdopen(fd, "w+")) == NULL) {
+               warn("%s", tempname);
                goto out;
        }
-       (void) unlink(tempEdit);
+       (void) rm(tempname);
        /*
         * stdin = current message.
         * stdout = new message.
@@ -515,13 +522,13 @@
  * should shift over and 'f' if not.
  */
 int
-forward(ms, fp, f)
+forward(ms, fp, fn, f)
        char ms[];
        FILE *fp;
+       char *fn;
        int f;
 {
        register int *msgvec;
-       extern char *tempMail;
        struct ignoretab *ig;
        char *tabst;
 
@@ -549,8 +556,8 @@
 
                touch(mp);
                printf(" %d", *msgvec);
-               if (send(mp, fp, ig, tabst) < 0) {
-                       perror(tempMail);
+               if (sendmessage(mp, fp, ig, tabst) < 0) {
+                       warn("%s", fn);
                        return(-1);
                }
        }
Index: def.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/def.h,v
retrieving revision 1.5
diff -u -r1.5 def.h
--- def.h       2000/10/24 13:54:31     1.5
+++ def.h       2001/02/15 21:31:41
@@ -51,6 +51,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <err.h>
 #include <string.h>
 #include "pathnames.h"
 
Index: edit.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/edit.c,v
retrieving revision 1.3
diff -u -r1.3 edit.c
--- edit.c      2000/10/24 13:54:31     1.3
+++ edit.c      2001/02/15 21:31:42
@@ -125,7 +125,7 @@
                                        break;
                        }
                        if (ferror(otf))
-                               perror("/tmp");
+                               warn("/tmp");
                        (void) Fclose(fp);
                }
                (void) signal(SIGINT, sigint);
@@ -148,17 +148,18 @@
        register FILE *nf = NULL;
        register int t;
        time_t modtime;
-       char *edit;
+       char *edit, tempname[PATHSIZE];
        struct stat statb;
-       extern char *tempEdit;
 
-       if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
-               perror(tempEdit);
+       snprintf(tempname, sizeof(tempname), "%s/mail.ReXXXXXXXXXX", tmpdir);
+       if ((t = mkstemp(tempname)) == -1 ||
+           (nf = Fdopen(t, "w")) == NULL) {
+               warn("%s", tempname);
                goto out;
        }
-       if ((nf = Fdopen(t, "w")) == NULL) {
-               perror(tempEdit);
-               (void) unlink(tempEdit);
+       if (readonly && fchmod(t, 0400) == -1) {
+               warn("%s", tempname);
+               (void)rm(tempname);
                goto out;
        }
        if (size >= 0)
@@ -174,22 +175,22 @@
                modtime = statb.st_mtime;
        if (ferror(nf)) {
                (void) Fclose(nf);
-               perror(tempEdit);
-               (void) unlink(tempEdit);
+               warn("%s", tempname);
+               (void)rm(tempname);
                nf = NULL;
                goto out;
        }
        if (Fclose(nf) < 0) {
-               perror(tempEdit);
-               (void) unlink(tempEdit);
+               warn("%s", tempname);
+               (void)rm(tempname);
                nf = NULL;
                goto out;
        }
        nf = NULL;
        if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
                edit = type == 'e' ? _PATH_EX : _PATH_VI;
-       if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
-               (void) unlink(tempEdit);
+       if (run_command(edit, 0, -1, -1, tempname, NOSTR, NOSTR) < 0) {
+               (void)rm(tempname);
                goto out;
        }
        /*
@@ -197,26 +198,26 @@
         * temporary and return.
         */
        if (readonly) {
-               (void) unlink(tempEdit);
+               (void)rm(tempname);
                goto out;
        }
-       if (stat(tempEdit, &statb) < 0) {
-               perror(tempEdit);
+       if (stat(tempname, &statb) < 0) {
+               warn("%s", tempname);
                goto out;
        }
        if (modtime == statb.st_mtime) {
-               (void) unlink(tempEdit);
+               (void)rm(tempname);
                goto out;
        }
        /*
         * Now switch to new file.
         */
-       if ((nf = Fopen(tempEdit, "a+")) == NULL) {
-               perror(tempEdit);
-               (void) unlink(tempEdit);
+       if ((nf = Fopen(tempname, "a+")) == NULL) {
+               warn("%s", tempname);
+               (void)rm(tempname);
                goto out;
        }
-       (void) unlink(tempEdit);
+       (void)rm(tempname);
 out:
        return nf;
 }
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/extern.h,v
retrieving revision 1.3
diff -u -r1.3 extern.h
--- extern.h    1998/01/02 16:43:48     1.3
+++ extern.h    2001/02/15 21:31:43
@@ -86,7 +86,7 @@
 int     append __P((struct message *, FILE *));
 int     argcount __P((char **));
 void    assign __P((char [], char []));
-int     bangexp __P((char *));
+int     bangexp __P((char *, size_t));
 int     blankline __P((char []));
 void    brokpipe __P((int));
 int     charcount __P((char *, int));
@@ -121,16 +121,16 @@
 int     file __P((char **));
 struct grouphead *
         findgroup __P((char []));
-void    findmail __P((char *, char *));
+void    findmail __P((char *, char *, int));
 int     first __P((int, int));
 void    fixhead __P((struct header *, struct name *));
 void    fmt __P((char *, struct name *, FILE *, int));
 int     folders __P((void));
-int     forward __P((char [], FILE *, int));
+int     forward __P((char [], FILE *, char *, int));
 void    free_child __P((int));
 int     from __P((int *));
 off_t   fsize __P((FILE *));
-int     getfold __P((char *));
+int     getfold __P((char *, int));
 int     gethfield __P((FILE *, char [], int, char **));
 int     getmsglist __P((char *, int *, int));
 int     getrawlist __P((char [], char **, int));
@@ -155,7 +155,7 @@
 int     ishead __P((char []));
 int     isign __P((char *, struct ignoretab []));
 int     isprefix __P((char *, char *));
-void    istrcpy __P((char *, char *));
+void    istrncpy __P((char *, char *, size_t));
 struct cmd *
         lex __P((char []));
 void    load __P((char *));
@@ -179,7 +179,6 @@
 int     newfileinfo __P((void));
 int     next __P((int *));
 int     null __P((int));
-void    panic __P((const char *, ...));
 void    parse __P((char [], struct headline *, char []));
 int     pcmdlist __P((void));
 int     pdot __P((void));
@@ -193,7 +192,7 @@
 int     pversion __P((int));
 void    quit __P((void));
 int     quitcmd __P((void));
-int     raise __P((int));
+int     upcase __P((int));
 int     readline __P((FILE *, char *, int));
 void    register_file __P((FILE *, int, int));
 void    regret __P((int));
@@ -214,7 +213,7 @@
 int     schdir __P((char **));
 int     screensize __P((void));
 int     scroll __P((char []));
-int     send __P((struct message *, FILE *, struct ignoretab *, char *));
+int     sendmessage __P((struct message *, FILE *, struct ignoretab *, char
*));
 int     sendmail __P((char *));
 int     set __P((char **));
 int     setfile __P((char *));
@@ -251,3 +250,6 @@
 int     wait_child __P((int));
 int     wait_command __P((int));
 int     writeback __P((FILE *));
+
+extern char *__progname;
+extern char *tmpdir;
Index: fio.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/fio.c,v
retrieving revision 1.3
diff -u -r1.3 fio.c
--- fio.c       2000/10/24 13:54:31     1.3
+++ fio.c       2001/02/15 21:31:44
@@ -59,22 +59,19 @@
 setptr(ibuf)
        register FILE *ibuf;
 {
-       extern char *tmpdir;
        register int c, count;
        register char *cp, *cp2;
        struct message this;
        FILE *mestmp;
        off_t offset;
        int maybe, inhead;
-       char linebuf[LINESIZE];
+       char linebuf[LINESIZE], pathbuf[PATHSIZE];
 
        /* Get temporary file. */
-       (void)sprintf(linebuf, "%s/mail.XXXXXX", tmpdir);
-       if ((c = mkstemp(linebuf)) == -1 ||
-           (mestmp = Fdopen(c, "r+")) == NULL) {
-               errx(1, "can't open %s", linebuf);
-       }
-       (void)unlink(linebuf);
+       (void)snprintf(pathbuf, sizeof(pathbuf), "%s/mail.XXXXXXXXXX", tmpdir);
+       if ((c = mkstemp(pathbuf)) == -1 || (mestmp = Fdopen(c, "r+")) == NULL)
+               err(1, "can't open %s", pathbuf);
+       (void)rm(pathbuf);
 
        msgCount = 0;
        maybe = 1;
@@ -86,27 +83,22 @@
        this.m_block = 0;
        this.m_offset = 0;
        for (;;) {
-               if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
-                       if (append(&this, mestmp)) {
-                               perror("temporary file");
-                               exit(1);
-                       }
+               if (fgets(linebuf, sizeof(linebuf), ibuf) == NULL) {
+                       if (append(&this, mestmp))
+                               err(1, "temporary file");
                        makemessage(mestmp);
                        return;
                }
                count = strlen(linebuf);
                (void) fwrite(linebuf, sizeof *linebuf, count, otf);
-               if (ferror(otf)) {
-                       perror("/tmp");
-                       exit(1);
-               }
-               linebuf[count - 1] = 0;
+               if (ferror(otf))
+                       err(1, "/tmp");
+               if (count)
+                       linebuf[count - 1] = '\0';
                if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
                        msgCount++;
-                       if (append(&this, mestmp)) {
-                               perror("temporary file");
-                               exit(1);
-                       }
+                       if (append(&this, mestmp))
+                               err(1, "temporary file");
                        this.m_flag = MUSED|MNEW;
                        this.m_size = 0;
                        this.m_lines = 0;
@@ -193,10 +185,8 @@
 {
 
        fflush(otf);
-       if (fseek(itf, (long)positionof(mp->m_block, mp->m_offset), 0) < 0) {
-               perror("fseek");
-               panic("Temporary file seek");
-       }
+       if (fseek(itf, (long)positionof(mp->m_block, mp->m_offset), 0) < 0)
+               err(1, "fseek");
        return (itf);
 }
 
@@ -213,13 +203,13 @@
        if (message != 0)
                free((char *) message);
        if ((message = (struct message *) malloc((unsigned) size)) == 0)
-               panic("Insufficient memory for %d messages", msgCount);
+               err(1, "Out of memory");
        dot = message;
        size -= sizeof (struct message);
        fflush(f);
        (void) lseek(fileno(f), (off_t)sizeof *message, 0);
        if (read(fileno(f), (char *) message, size) != size)
-               panic("Message temporary file corrupted");
+               errx(1, "Message temporary file corrupted");
        message[msgCount].m_size = 0;
        message[msgCount].m_lines = 0;
        Fclose(f);
@@ -315,7 +305,7 @@
        register char *cp, *shell;
        int pivec[2];
        struct stat sbuf;
-       extern union wait wait_status;
+       extern int wait_status;
 
        /*
         * The order of evaluation is "%" and "#" expand into constants.
@@ -325,7 +315,7 @@
         */
        switch (*name) {
        case '%':
-               findmail(name[1] ? name + 1 : myname, xname);
+               findmail(name[1] ? name + 1 : myname, xname, sizeof(xname));
                return savestr(xname);
        case '#':
                if (name[1] != 0)
@@ -340,22 +330,22 @@
                        name = "~/mbox";
                /* fall through */
        }
-       if (name[0] == '+' && getfold(cmdbuf) >= 0) {
-               sprintf(xname, "%s/%s", cmdbuf, name + 1);
+       if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) {
+               snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1);
                name = savestr(xname);
        }
        /* catch the most common shell meta character */
-       if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) {
-               sprintf(xname, "%s%s", homedir, name + 1);
+       if (name[0] == '~' && homedir && (name[1] == '/' || name[1] == '\0')) {
+               snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1);
                name = savestr(xname);
        }
        if (!anyof(name, "~{[*?$`'\"\\"))
                return name;
        if (pipe(pivec) < 0) {
-               perror("pipe");
+               warn("pipe");
                return name;
        }
-       sprintf(cmdbuf, "echo %s", name);
+       snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
        if ((shell = value("SHELL")) == NOSTR)
                shell = _PATH_CSHELL;
        pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR);
@@ -367,12 +357,12 @@
        close(pivec[1]);
        l = read(pivec[0], xname, BUFSIZ);
        close(pivec[0]);
-       if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) {
+       if (wait_child(pid) < 0 && WIFSIGNALED(wait_status) &&
WTERMSIG(wait_status) != SIGPIPE) {
                fprintf(stderr, "\"%s\": Expansion failed.\n", name);
                return NOSTR;
        }
        if (l < 0) {
-               perror("read");
+               warn("read");
                return NOSTR;
        }
        if (l == 0) {
@@ -383,11 +373,11 @@
                fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name);
                return NOSTR;
        }
-       xname[l] = 0;
+       xname[l] = '\0';
        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                ;
        cp[1] = '\0';
-       if (index(xname, ' ') && stat(xname, &sbuf) < 0) {
+       if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) {
                fprintf(stderr, "\"%s\": Ambiguous.\n", name);
                return NOSTR;
        }
@@ -398,17 +388,18 @@
  * Determine the current folder directory name.
  */
 int
-getfold(name)
+getfold(name, namelen)
        char *name;
+       int namelen;
 {
        char *folder;
 
        if ((folder = value("folder")) == NOSTR)
                return (-1);
        if (*folder == '/')
-               strcpy(name, folder);
+               strlcpy(name, folder, namelen);
        else
-               sprintf(name, "%s/%s", homedir, folder);
+               snprintf(name, namelen, "%s/%s", homedir ? homedir : ".",
folder);
        return (0);
 }
 
@@ -425,7 +416,7 @@
        else if (*cp != '/') {
                char buf[PATHSIZE];
 
-               (void) sprintf(buf, "~/%s", cp);
+               (void) snprintf(buf, sizeof(buf), "~/%s", cp);
                cp = expand(buf);
        }
        return cp;
Index: getname.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/getname.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 getname.c
--- getname.c   1994/05/27 12:32:06     1.1.1.1
+++ getname.c   2001/02/15 21:31:44
@@ -42,8 +42,8 @@
 /* Getname / getuserid for those with hashed passwd data base). */
 
 /*
- * Search the passwd file for a uid.  Return name through ref parameter
- * if found, indicating success with 0 return.  Return -1 on error.
+ * Search the passwd file for a uid. Return name on success,
+ * NOSTR on failure
  */
 char *
 getname(uid)
Index: head.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/head.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 head.c
--- head.c      1994/05/27 12:32:06     1.1.1.1
+++ head.c      2001/02/15 21:31:44
@@ -53,13 +53,10 @@
 ishead(linebuf)
        char linebuf[];
 {
-       register char *cp;
        struct headline hl;
        char parbuf[BUFSIZ];
 
-       cp = linebuf;
-       if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
-           *cp++ != ' ')
+       if (strncmp(linebuf, "From ", 5))
                return (0);
        parse(linebuf, &hl, parbuf);
        if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
Index: lex.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/lex.c,v
retrieving revision 1.8
diff -u -r1.8 lex.c
--- lex.c       2000/11/27 07:32:29     1.8
+++ lex.c       2001/02/15 21:31:45
@@ -61,12 +61,12 @@
        char *name;
 {
        FILE *ibuf;
-       int i;
+       int i, fd;
        struct stat stb;
        char isedit = *name != '%';
        char *who = name[1] ? name + 1 : myname;
+       char tempname[PATHSIZE];
        static int shudclob;
-       extern char *tempMesg;
 
        if ((name = expand(name)) == NOSTR)
                return -1;
@@ -74,12 +74,12 @@
        if ((ibuf = Fopen(name, "r")) == NULL) {
                if (!isedit && errno == ENOENT)
                        goto nomail;
-               perror(name);
+               warn("%s", name);
                return(-1);
        }
 
        if (fstat(fileno(ibuf), &stb) < 0) {
-               perror("fstat");
+               warn("fstat");
                Fclose(ibuf);
                return (-1);
        }
@@ -88,7 +88,7 @@
        case S_IFDIR:
                Fclose(ibuf);
                errno = EISDIR;
-               perror(name);
+               warn("%s", name);
                return (-1);
 
        case S_IFREG:
@@ -97,7 +97,7 @@
        default:
                Fclose(ibuf);
                errno = EINVAL;
-               perror(name);
+               warn("%s", name);
                return (-1);
        }
 
@@ -128,21 +128,18 @@
        }
        shudclob = 1;
        edit = isedit;
-       strcpy(prevfile, mailname);
+       strlcpy(prevfile, mailname, sizeof(prevfile));
        if (name != mailname)
-               strcpy(mailname, name);
+               strlcpy(mailname, name, sizeof(mailname));
        mailsize = fsize(ibuf);
-       if ((otf = fopen(tempMesg, "w")) == NULL) {
-               perror(tempMesg);
-               exit(1);
-       }
+       snprintf(tempname, sizeof(tempname), "%s/mail.RxXXXXXXXXXX", tmpdir);
+       if ((fd = mkstemp(tempname)) == -1 || (otf = fdopen(fd, "w")) == NULL)
+               err(1, "%s", tempname);
        (void) fcntl(fileno(otf), F_SETFD, 1);
-       if ((itf = fopen(tempMesg, "r")) == NULL) {
-               perror(tempMesg);
-               exit(1);
-       }
+       if ((itf = fopen(tempname, "r")) == NULL)
+               err(1, "%s", tempname);
        (void) fcntl(fileno(itf), F_SETFD, 1);
-       rm(tempMesg);
+       rm(tempname);
        setptr(ibuf);
        setmsize(msgCount);
        Fclose(ibuf);
@@ -273,7 +270,7 @@
                return(0);
        }
        cp2 = word;
-       while (*cp && index(" \t0123456789$^.:/-+*'\"", *cp) == NOSTR)
+       while (*cp && strchr(" \t0123456789$^.:/-+*'\"", *cp) == NOSTR)
                *cp2++ = *cp++;
        *cp2 = '\0';
 
@@ -405,7 +402,7 @@
                break;
 
        default:
-               panic("Unknown argtype");
+               errx(1, "Unknown argtype");
        }
 
 out:
@@ -463,7 +460,7 @@
         * ignore trailing chars after `#' 
         *
         * lines with beginning `#' are comments
-        * spaces befor `#' are ignored in execute()
+        * spaces before `#' are ignored in execute()
         */
 
        if (*word == '#')
@@ -588,7 +585,7 @@
 {
        register struct message *mp;
        register int u, n, mdot, d, s;
-       char fname[BUFSIZ], zname[BUFSIZ], *ename;
+       char fname[PATHSIZE+1], zname[PATHSIZE+1], *ename;
 
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                if (mp->m_flag & MNEW)
@@ -613,10 +610,10 @@
                        s++;
        }
        ename = mailname;
-       if (getfold(fname) >= 0) {
+       if (getfold(fname, sizeof(fname) - 1) >= 0) {
                strcat(fname, "/");
                if (strncmp(fname, mailname, strlen(fname)) == 0) {
-                       sprintf(zname, "+%s", mailname + strlen(fname));
+                       snprintf(zname, sizeof(zname), "+%s", mailname +
strlen(fname));
                        ename = zname;
                }
        }
Index: list.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/list.c,v
retrieving revision 1.2
diff -u -r1.2 list.c
--- list.c      1995/05/30 06:31:40     1.2
+++ list.c      2001/02/15 21:31:46
@@ -391,8 +391,12 @@
 {
        register char c, *cp, *cp2, quotec;
        int argn;
-       char linebuf[BUFSIZ];
+       char *linebuf;
+       size_t linebufsize = BUFSIZ;
 
+       if ((linebuf = (char *)malloc(linebufsize)) == NULL)
+               err(1, "Out of memory");
+
        argn = 0;
        cp = line;
        for (;;) {
@@ -408,6 +412,13 @@
                cp2 = linebuf;
                quotec = '\0';
                while ((c = *cp) != '\0') {
+                       /* Allocate more space if necessary */
+                       if (cp2 - linebuf == linebufsize - 1) {
+                               linebufsize += BUFSIZ;
+                               if ((linebuf = realloc(linebuf, linebufsize))
== NULL)
+                                       err(1, "Out of memory");
+                               cp2 = linebuf + linebufsize - BUFSIZ - 1;
+                       }
                        cp++;
                        if (quotec != '\0') {
                                if (c == quotec)
@@ -473,6 +484,7 @@
                argv[argn++] = savestr(linebuf);
        }
        argv[argn] = NOSTR;
+       free(linebuf);
        return argn;
 }
 
@@ -605,7 +617,7 @@
        int token;
 {
        if (++regretp >= REGDEP)
-               panic("Too many regrets");
+               errx(1, "Too many regrets");
        regretstack[regretp] = token;
        lexstring[STRINGLEN-1] = '\0';
        string_stack[regretp] = savestr(lexstring);
@@ -662,7 +674,7 @@
        while (*cp2) {
                if (*cp == 0)
                        return(1);
-               if (raise(*cp++) != raise(*cp2++)) {
+               if (upcase(*cp++) != upcase(*cp2++)) {
                        cp2 = ++backup;
                        cp = str;
                }
@@ -678,7 +690,7 @@
  * previous search string.
  */
 
-char lastscan[128];
+char lastscan[STRINGLEN];
 int
 matchsubj(str, mesg)
        char *str;
@@ -688,17 +700,17 @@
        register char *cp, *cp2, *backup;
 
        str++;
-       if (strlen(str) == 0)
+       if (*str == '\0')
                str = lastscan;
        else
-               strcpy(lastscan, str);
+               strlcpy(lastscan, str, sizeof(lastscan));
        mp = &message[mesg-1];
 
        /*
         * Now look, ignoring case, for the word in the string.
         */
 
-       if (value("searchheaders") && (cp = index(str, ':'))) {
+       if (value("searchheaders") && (cp = strchr(str, ':'))) {
                *cp++ = '\0';
                cp2 = hfield(str, mp);
                cp[-1] = ':';
@@ -713,7 +725,7 @@
        while (*cp2) {
                if (*cp == 0)
                        return(1);
-               if (raise(*cp++) != raise(*cp2++)) {
+               if (upcase(*cp++) != upcase(*cp2++)) {
                        cp2 = ++backup;
                        cp = str;
                }
@@ -732,7 +744,7 @@
 
        i = mesg;
        if (i < 1 || i > msgCount)
-               panic("Bad message number to mark");
+               errx(1, "Bad message number to mark");
        message[i-1].m_flag |= MMARK;
 }
 
@@ -747,7 +759,7 @@
 
        i = mesg;
        if (i < 1 || i > msgCount)
-               panic("Bad message number to unmark");
+               errx(1, "Bad message number to unmark");
        message[i-1].m_flag &= ~MMARK;
 }
 
Index: main.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/main.c,v
retrieving revision 1.6
diff -u -r1.6 main.c
--- main.c      1999/05/20 22:23:04     1.6
+++ main.c      2001/02/15 21:31:46
@@ -42,7 +42,6 @@
 #endif /* not lint */
 
 #include "rcv.h"
-#include <err.h>
 #include <fcntl.h>
 #include "extern.h"
 
@@ -99,10 +98,8 @@
                         * articles have been read/deleted for netnews.
                         */
                        Tflag = optarg;
-                       if ((i = creat(Tflag, 0600)) < 0) {
-                               perror(Tflag);
-                               exit(1);
-                       }
+                       if ((i = creat(Tflag, 0600)) < 0)
+                               err(1, "%s", Tflag);
                        close(i);
                        break;
                case 'u':
@@ -197,14 +194,10 @@
        /*
         * Check for inconsistent arguments.
         */
-       if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) {
-               fputs("You must specify direct recipients with -s, -c, or
-b.\n", stderr);
-               exit(1);
-       }
-       if (ef != NOSTR && to != NIL) {
-               fprintf(stderr, "Cannot give -f and people to send to.\n");
-               exit(1);
-       }
+       if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL))
+               errx(1, "You must specify direct recipients with -s, -c, or
-b.");
+       if (ef != NOSTR && to != NIL)
+               errx(1, "Cannot give -f and people to send to.");
        tinit();
        setscreensize();
        input = stdin;
Index: names.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/names.c,v
retrieving revision 1.4
diff -u -r1.4 names.c
--- names.c     1998/10/10 09:58:20     1.4
+++ names.c     2001/02/15 21:31:49
@@ -94,10 +94,12 @@
 {
        register char *cp;
        register struct name *top, *np, *t;
-       char nbuf[BUFSIZ];
+       char *nbuf;
 
        if (line == NOSTR || *line == '\0')
                return NIL;
+       if ((nbuf = (char *)malloc(strlen(line) + 1)) == NULL)
+               err(1, "Out of memory");
        top = NIL;
        np = NIL;
        cp = line;
@@ -110,6 +112,7 @@
                t->n_blink = np;
                np = t;
        }
+       free(nbuf);
        return top;
 }
 
@@ -153,9 +156,9 @@
                        *cp++ = ',';
                *cp++ = ' ';
        }
-       *--cp = 0;
+       *--cp = '\0';
        if (comma && *--cp == ',')
-               *cp = 0;
+               *cp = '\0';
        return(top);
 }
 
@@ -197,7 +200,7 @@
                for (cp2 = wbuf; *cp && (*cp2++ = *cp++) != '>';)
                        ;
        else
-               for (cp2 = wbuf; *cp && !index(" \t,(", *cp); *cp2++ = *cp++)
+               for (cp2 = wbuf; *cp && !strchr(" \t,(", *cp); *cp2++ = *cp++)
                        ;
        *cp2 = '\0';
        return cp;
@@ -223,7 +226,6 @@
        char *date, *fname, *ctime();
        FILE *fout, *fin;
        int ispipe;
-       extern char *tempEdit;
 
        top = names;
        np = names;
@@ -246,15 +248,21 @@
                 */
 
                if (image < 0) {
-                       if ((fout = Fopen(tempEdit, "a")) == NULL) {
-                               perror(tempEdit);
+                       int fd;
+                       char tempname[PATHSIZE];
+
+                       snprintf(tempname, sizeof(tempname),
+                                "%s/mail.ReXXXXXXXXXX", tmpdir);
+                       if ((fd = mkstemp(tempname)) == -1 ||
+                           (fout = Fdopen(fd, "a")) == NULL) {
+                               warn("%s", tempname);
                                senderr++;
                                goto cant;
                        }
-                       image = open(tempEdit, 2);
-                       (void) unlink(tempEdit);
+                       image = open(tempname, O_RDWR);
+                       (void)rm(tempname);
                        if (image < 0) {
-                               perror(tempEdit);
+                               warn("%s", tempname);
                                senderr++;
                                (void) Fclose(fout);
                                goto cant;
@@ -268,8 +276,12 @@
                        rewind(fo);
                        (void) putc('\n', fout);
                        (void) fflush(fout);
-                       if (ferror(fout))
-                               perror(tempEdit);
+                       if (ferror(fout)) {
+                               warn("%s", tempname);
+                               senderr++;
+                               Fclose(fout);
+                               goto cant;
+                       }
                        (void) Fclose(fout);
                }
 
@@ -303,12 +315,12 @@
                } else {
                        int f;
                        if ((fout = Fopen(fname, "a")) == NULL) {
-                               perror(fname);
+                               warn("%s", fname);
                                senderr++;
                                goto cant;
                        }
                        if ((f = dup(image)) < 0) {
-                               perror("dup");
+                               warn("dup");
                                fin = NULL;
                        } else
                                fin = Fdopen(f, "r");
@@ -321,8 +333,13 @@
                        rewind(fin);
                        while ((c = getc(fin)) != EOF)
                                (void) putc(c, fout);
-                       if (ferror(fout))
-                               senderr++, perror(fname);
+                       if (ferror(fout)) {
+                               warn("%s", fname);
+                               senderr++;
+                               Fclose(fout);
+                               Fclose(fin);
+                               goto cant;
+                       }
                        (void) Fclose(fout);
                        (void) Fclose(fin);
                }
@@ -483,7 +500,7 @@
 
        n = np;
        if ((t = count(n)) == 0)
-               panic("No names to unpack");
+               errx(1, "No names to unpack");
        /*
         * Compute the number of extra arguments we will need.
         * We need at least two extra -- one for "mail" and one for
Index: popen.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/popen.c,v
retrieving revision 1.2
diff -u -r1.2 popen.c
--- popen.c     1998/10/10 19:18:30     1.2
+++ popen.c     2001/02/15 21:31:49
@@ -55,12 +55,13 @@
        int pid;
        char done;
        char free;
-       union wait status;
+       int status;
        struct child *link;
 };
 static struct child *child;
 static struct child *findchild __P((int));
 static void delchild __P((struct child *));
+static int file_pid __P((FILE *));
 
 FILE *
 Fopen(file, mode)
@@ -166,7 +167,7 @@
        struct fp *fpp;
 
        if ((fpp = (struct fp *) malloc(sizeof *fpp)) == NULL)
-               panic("Out of memory");
+               err(1, "Out of memory");
        fpp->fp = fp;
        fpp->pipe = pipe;
        fpp->pid = pid;
@@ -186,9 +187,11 @@
                        free((char *) p);
                        return;
                }
-       panic("Invalid file pointer");
+       errx(1, "Invalid file pointer");
+       /*NOTREACHED*/
 }
 
+int
 file_pid(fp)
        FILE *fp;
 {
@@ -197,7 +200,7 @@
        for (p = fp_head; p; p = p->link)
                if (p->fp == fp)
                        return (p->pid);
-       panic("Invalid file pointer");
+       errx(1, "Invalid file pointer");
        /*NOTREACHED*/
 }
 
@@ -232,7 +235,7 @@
        int pid;
 
        if ((pid = fork()) < 0) {
-               perror("fork");
+               warn("fork");
                return -1;
        }
        if (pid == 0) {
@@ -245,7 +248,7 @@
                        argv[i] = NOSTR;
                prepare_child(mask, infd, outfd);
                execvp(argv[0], argv);
-               perror(argv[0]);
+               warn("%s", argv[0]);
                _exit(1);
        }
        return pid;
@@ -320,11 +323,10 @@
        int signo;
 {
        int pid;
-       union wait status;
+       int status;
        register struct child *cp;
 
-       while ((pid =
-           wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) {
+       while ((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0) {
                cp = findchild(pid);
                if (cp->free)
                        delchild(cp);
@@ -335,7 +337,7 @@
        }
 }
 
-union wait wait_status;
+int wait_status;
 
 /*
  * Wait for a specific child to die.
@@ -352,7 +354,7 @@
        wait_status = cp->status;
        delchild(cp);
        sigsetmask(mask);
-       return wait_status.w_status ? -1 : 0;
+       return((WIFEXITED(wait_status) && WEXITSTATUS(wait_status)) ? -1 : 0);
 }
 
 /*
Index: quit.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/quit.c,v
retrieving revision 1.2
diff -u -r1.2 quit.c
--- quit.c      1998/10/10 09:58:20     1.2
+++ quit.c      2001/02/15 21:31:50
@@ -72,9 +72,9 @@
        FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
        register struct message *mp;
        register int c;
-       extern char *tempQuit, *tempResid;
+       int fd;
        struct stat minfo;
-       char *mbox;
+       char *mbox, tempname[PATHSIZE];
 
        /*
         * If we are read only, we can't do anything,
@@ -108,8 +108,9 @@
        rbuf = NULL;
        if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
                printf("New mail has arrived.\n");
-               rbuf = Fopen(tempResid, "w");
-               if (rbuf == NULL || fbuf == NULL)
+               snprintf(tempname, sizeof(tempname), "%s/mail.RqXXXXXXXXXX",
tmpdir);
+               if ((fd = mkstemp(tempname)) == -1 ||
+                   (rbuf = Fdopen(fd, "w")) == NULL)
                        goto newmail;
 #ifdef APPEND
                fseek(fbuf, (long)mailsize, 0);
@@ -125,9 +126,9 @@
                }
 #endif
                Fclose(rbuf);
-               if ((rbuf = Fopen(tempResid, "r")) == NULL)
+               if ((rbuf = Fopen(tempname, "r")) == NULL)
                        goto newmail;
-               rm(tempResid);
+               rm(tempname);
        }
 
        /*
@@ -198,26 +199,28 @@
        mbox = expand("&");
        mcount = c;
        if (value("append") == NOSTR) {
-               if ((obuf = Fopen(tempQuit, "w")) == NULL) {
-                       perror(tempQuit);
+               snprintf(tempname, sizeof(tempname), "%s/mail.RmXXXXXXXXXX",
tmpdir);
+               if ((fd = mkstemp(tempname)) == -1 ||
+                   (obuf = Fdopen(fd, "w")) == NULL) {
+                       warn("%s", tempname);
                        Fclose(fbuf);
                        return;
                }
-               if ((ibuf = Fopen(tempQuit, "r")) == NULL) {
-                       perror(tempQuit);
-                       rm(tempQuit);
+               if ((ibuf = Fopen(tempname, "r")) == NULL) {
+                       warn("%s", tempname);
+                       rm(tempname);
                        Fclose(obuf);
                        Fclose(fbuf);
                        return;
                }
-               rm(tempQuit);
+               rm(tempname);
                if ((abuf = Fopen(mbox, "r")) != NULL) {
                        while ((c = getc(abuf)) != EOF)
                                (void) putc(c, obuf);
                        Fclose(abuf);
                }
                if (ferror(obuf)) {
-                       perror(tempQuit);
+                       warn("%s", tempname);
                        Fclose(ibuf);
                        Fclose(obuf);
                        Fclose(fbuf);
@@ -226,7 +229,7 @@
                Fclose(obuf);
                close(creat(mbox, 0600));
                if ((obuf = Fopen(mbox, "r+")) == NULL) {
-                       perror(mbox);
+                       warn("%s", mbox);
                        Fclose(ibuf);
                        Fclose(fbuf);
                        return;
@@ -234,7 +237,7 @@
        }
        if (value("append") != NOSTR) {
                if ((obuf = Fopen(mbox, "a")) == NULL) {
-                       perror(mbox);
+                       warn("%s", mbox);
                        Fclose(fbuf);
                        return;
                }
@@ -242,8 +245,8 @@
        }
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                if (mp->m_flag & MBOX)
-                       if (send(mp, obuf, saveignore, NOSTR) < 0) {
-                               perror(mbox);
+                       if (sendmessage(mp, obuf, saveignore, NOSTR) < 0) {
+                               warn("%s", mbox);
                                Fclose(ibuf);
                                Fclose(obuf);
                                Fclose(fbuf);
@@ -270,7 +273,7 @@
        }
        trunc(obuf);
        if (ferror(obuf)) {
-               perror(mbox);
+               warn("%s", mbox);
                Fclose(obuf);
                Fclose(fbuf);
                return;
@@ -337,7 +340,7 @@
 
        p = 0;
        if ((obuf = Fopen(mailname, "r+")) == NULL) {
-               perror(mailname);
+               warn("%s", mailname);
                return(-1);
        }
 #ifndef APPEND
@@ -348,8 +351,8 @@
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
                        p++;
-                       if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
-                               perror(mailname);
+                       if (sendmessage(mp, obuf, (struct ignoretab *)0, NOSTR)
< 0) {
+                               warn("%s", mailname);
                                Fclose(obuf);
                                return(-1);
                        }
@@ -362,7 +365,7 @@
        fflush(obuf);
        trunc(obuf);
        if (ferror(obuf)) {
-               perror(mailname);
+               warn("%s", mailname);
                Fclose(obuf);
                return(-1);
        }
@@ -384,13 +387,11 @@
 void
 edstop()
 {
-       extern char *tmpdir;
        register int gotcha, c;
        register struct message *mp;
        FILE *obuf, *ibuf, *readstat;
        struct stat statb;
-       char tempname[30];
-       char *mktemp();
+       char tempname[PATHSIZE];
 
        if (readonly)
                return;
@@ -419,16 +420,16 @@
                goto done;
        ibuf = NULL;
        if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
-               strcpy(tempname, tmpdir);
-               strcat(tempname, "mboxXXXXXX");
-               mktemp(tempname);
-               if ((obuf = Fopen(tempname, "w")) == NULL) {
-                       perror(tempname);
+               int fd;
+
+               snprintf(tempname, sizeof(tempname), "%s/mbox.XXXXXXXXXX",
tmpdir);
+               if ((fd = mkstemp(tempname)) == -1 || (obuf = Fdopen(fd, "w"))
== NULL) {
+                       warn("%s", tempname);
                        relsesigs();
                        reset(0);
                }
                if ((ibuf = Fopen(mailname, "r")) == NULL) {
-                       perror(mailname);
+                       warn("%s", mailname);
                        Fclose(obuf);
                        rm(tempname);
                        relsesigs();
@@ -440,7 +441,7 @@
                Fclose(ibuf);
                Fclose(obuf);
                if ((ibuf = Fopen(tempname, "r")) == NULL) {
-                       perror(tempname);
+                       warn("%s", tempname);
                        rm(tempname);
                        relsesigs();
                        reset(0);
@@ -450,7 +451,7 @@
        printf("\"%s\" ", mailname);
        fflush(stdout);
        if ((obuf = Fopen(mailname, "r+")) == NULL) {
-               perror(mailname);
+               warn("%s", mailname);
                relsesigs();
                reset(0);
        }
@@ -460,8 +461,8 @@
                if ((mp->m_flag & MDELETED) != 0)
                        continue;
                c++;
-               if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
-                       perror(mailname);
+               if (sendmessage(mp, obuf, (struct ignoretab *) NULL, NOSTR) <
0) {
+                       warn("%s", mailname);
                        relsesigs();
                        reset(0);
                }
@@ -474,7 +475,7 @@
        }
        fflush(obuf);
        if (ferror(obuf)) {
-               perror(mailname);
+               warn("%s", mailname);
                relsesigs();
                reset(0);
        }
Index: send.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/send.c,v
retrieving revision 1.5
diff -u -r1.5 send.c
--- send.c      1998/10/10 09:58:20     1.5
+++ send.c      2001/02/15 21:31:50
@@ -52,7 +52,7 @@
  * prefix is a string to prepend to each output line.
  */
 int
-send(mp, obuf, doign, prefix)
+sendmessage(mp, obuf, doign, prefix)
        register struct message *mp;
        FILE *obuf;
        struct ignoretab *doign;
@@ -87,7 +87,7 @@
         * Process headers first
         */
        while (count > 0 && ishead) {
-               if (fgets(line, LINESIZE, ibuf) == NULL)
+               if (fgets(line, sizeof(line), ibuf) == NULL)
                        break;
                count -= length = strlen(line);
                if (firstline) {
@@ -172,12 +172,13 @@
                         * Strip trailing whitespace from prefix
                         * if line is blank.
                         */
-                       if (prefix != NOSTR)
+                       if (prefix != NOSTR) {
                                if (length > 1)
                                        fputs(prefix, obuf);
                                else
                                        (void) fwrite(prefix, sizeof *prefix,
                                                        prefixlen, obuf);
+                       }
                        (void) fwrite(line, sizeof *line, length, obuf);
                        if (ferror(obuf))
                                return -1;
@@ -190,7 +191,7 @@
                count--;                /* skip final blank line */
        if (prefix != NOSTR)
                while (count > 0) {
-                       if (fgets(line, LINESIZE, ibuf) == NULL) {
+                       if (fgets(line, sizeof(line), ibuf) == NULL) {
                                c = 0;
                                break;
                        }
@@ -312,18 +313,20 @@
         */
        if ((mtf = collect(hp, printheaders)) == NULL)
                return;
-       if (value("interactive") != NOSTR)
+       if (value("interactive") != NOSTR) {
                if (value("askcc") != NOSTR)
                        grabh(hp, GCC);
                else {
                        printf("EOT\n");
                        (void) fflush(stdout);
                }
-       if (fsize(mtf) == 0)
+       }
+       if (fsize(mtf) == 0) {
                if (hp->h_subject == NOSTR)
                        printf("No message, no subject; hope that's ok\n");
                else
                        printf("Null message body; hope that's ok\n");
+       }
        /*
         * Now, take the user names from the combined
         * to and cc lists and do all the alias
@@ -369,7 +372,7 @@
         */
        pid = fork();
        if (pid == -1) {
-               perror("fork");
+               warn("fork");
                savedeadletter(mtf);
                goto out;
        }
@@ -382,7 +385,7 @@
                else
                        cp = _PATH_SENDMAIL;
                execv(cp, namelist);
-               perror(cp);
+               warn("%s", cp);
                _exit(1);
        }
        if (value("verbose") != NOSTR)
@@ -428,20 +431,24 @@
        struct header *hp;
        FILE *fi;
 {
-       extern char *tempMail;
        register FILE *nfo, *nfi;
        register int c;
+       int fd;
+       char tempname[PATHSIZE];
 
-       if ((nfo = Fopen(tempMail, "w")) == NULL) {
-               perror(tempMail);
+       snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir);
+       if ((fd = mkstemp(tempname)) == -1 ||
+           (nfo = Fdopen(fd, "w")) == NULL) {
+               warn("%s", tempname);
                return(fi);
        }
-       if ((nfi = Fopen(tempMail, "r")) == NULL) {
-               perror(tempMail);
+       if ((nfi = Fopen(tempname, "r")) == NULL) {
+               warn("%s", tempname);
                (void) Fclose(nfo);
+               (void)rm(tempname);
                return(fi);
        }
-       (void) rm(tempMail);
+       (void) rm(tempname);
        (void) puthead(hp, nfo,
                       GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO|GNL|GCOMMA);
        c = getc(fi);
@@ -450,13 +457,13 @@
                c = getc(fi);
        }
        if (ferror(fi)) {
-               perror("read");
+               warn("read");
                rewind(fi);
                return(fi);
        }
        (void) fflush(nfo);
        if (ferror(nfo)) {
-               perror(tempMail);
+               warn("%s", tempname);
                (void) Fclose(nfo);
                (void) Fclose(nfi);
                rewind(fi);
@@ -549,7 +556,7 @@
        char *ctime();
 
        if ((fo = Fopen(name, "a")) == NULL) {
-               perror(name);
+               warn("%s", name);
                return (-1);
        }
        (void) time(&now);
@@ -559,7 +566,7 @@
        (void) putc('\n', fo);
        (void) fflush(fo);
        if (ferror(fo))
-               perror(name);
+               warn("%s", name);
        (void) Fclose(fo);
        rewind(fi);
        return (0);
Index: strings.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/strings.c,v
retrieving revision 1.2
diff -u -r1.2 strings.c
--- strings.c   1999/01/13 10:37:22     1.2
+++ strings.c   2001/02/15 21:31:50
@@ -75,14 +75,12 @@
                index++;
        }
        if (sp >= &stringdope[NSPACE])
-               panic("String too large");
+               errx(1, "String too large");
        if (sp->s_topFree == NOSTR) {
                index = sp - &stringdope[0];
                sp->s_topFree = malloc(STRINGSIZE << index);
-               if (sp->s_topFree == NOSTR) {
-                       fprintf(stderr, "No room for space %d\n", index);
-                       panic("Internal error");
-               }
+               if (sp->s_topFree == NOSTR)
+                       errx(1, "No room for space %d", index);
                sp->s_nextFree = sp->s_topFree;
                sp->s_nleft = STRINGSIZE << index;
        }
Index: temp.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/temp.c,v
retrieving revision 1.6
diff -u -r1.6 temp.c
--- temp.c      1999/08/28 01:03:23     1.6
+++ temp.c      2001/02/15 21:31:50
@@ -40,7 +40,6 @@
 #endif /* not lint */
 
 #include "rcv.h"
-#include <err.h>
 #include "extern.h"
 
 /*
@@ -49,75 +48,45 @@
  * Give names to all the temporary files that we will need.
  */
 
-char   *tempMail;
-char   *tempQuit;
-char   *tempEdit;
-char   *tempResid;
-char   *tempMesg;
 char   *tmpdir;
 
 void
 tinit()
 {
        register char *cp;
-       int len;
 
-       if ((tmpdir = getenv("TMPDIR")) == NULL)
+       if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
                tmpdir = _PATH_TMP;
-       else {
-               len = strlen(tmpdir);
-               if ((cp = malloc(len + 2)) == NULL)
-                       panic("Out of memory");
-               (void)strcpy(cp, tmpdir);
-               cp[len] = '/';
-               cp[len + 1] = '\0';
-               tmpdir = cp;
+       if ((tmpdir = strdup(tmpdir)) == NULL)
+               errx(1, "Out of memory");
+       /* Strip trailing '/' if necessary */
+       cp = tmpdir + strlen(tmpdir) - 1;
+       while (cp > tmpdir && *cp == '/') {
+               *cp = '\0';
+               cp--;
        }
-       len = strlen(tmpdir);
-       if ((tempMail = malloc(len + sizeof("RsXXXXXX"))) == NULL)
-               panic("Out of memory");
-       strcpy(tempMail, tmpdir);
-       mktemp(strcat(tempMail, "RsXXXXXX"));
-       if ((tempResid = malloc(len + sizeof("RqXXXXXX"))) == NULL)
-               panic("Out of memory");
-       strcpy(tempResid, tmpdir);
-       mktemp(strcat(tempResid, "RqXXXXXX"));
-       if ((tempQuit = malloc(len + sizeof("RmXXXXXX"))) == NULL)
-               panic("Out of memory");
-       strcpy(tempQuit, tmpdir);
-       mktemp(strcat(tempQuit, "RmXXXXXX"));
-       if ((tempEdit = malloc(len + sizeof("ReXXXXXX"))) == NULL)
-               panic("Out of memory");
-       strcpy(tempEdit, tmpdir);
-       mktemp(strcat(tempEdit, "ReXXXXXX"));
-       if ((tempMesg = malloc(len + sizeof("RxXXXXXX"))) == NULL)
-               panic("Out of memory");
-       strcpy(tempMesg, tmpdir);
-       mktemp(strcat(tempMesg, "RxXXXXXX"));
 
        /*
         * It's okay to call savestr in here because main will
         * do a spreserve() after us.
         */
        if (myname != NOSTR) {
-               if (getuserid(myname) < 0) {
-                       printf("\"%s\" is not a user of this system\n",
-                           myname);
-                       exit(1);
-               }
+               if (getuserid(myname) < 0)
+                       errx(1, "\"%s\" is not a user of this system", myname);
        } else {
                if ((cp = username()) == NOSTR) {
                        myname = "ubluit";
-                       if (rcvmode) {
-                               printf("Who are you!?\n");
-                               exit(1);
-                       }
+                       if (rcvmode)
+                               errx(1, "Who are you!?");
                } else
                        myname = savestr(cp);
        }
-       if ((cp = getenv("HOME")) == NOSTR)
-               cp = ".";
-       homedir = savestr(cp);
+       if ((cp = getenv("HOME")) == NOSTR || *cp == '\0' ||
+           strlen(cp) >= PATHSIZE)
+               homedir = NULL;
+       else
+               homedir = savestr(cp);
        if (debug)
-               printf("user = %s, homedir = %s\n", myname, homedir);
+               printf("user = %s, homedir = %s\n", myname,
+                      homedir ? homedir : "NONE");
 }
Index: tty.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/tty.c,v
retrieving revision 1.2
diff -u -r1.2 tty.c
--- tty.c       1996/08/19 20:23:35     1.2
+++ tty.c       2001/02/15 21:31:50
@@ -80,7 +80,7 @@
        ttyset = 0;
 #endif
        if (tcgetattr(fileno(stdin), &tio) < 0) {
-               perror("tcgetattr(stdin)");
+               warn("tcgetattr(stdin)");
                return(-1);
        }
        c_erase = tio.c_cc[VERASE];
@@ -183,11 +183,11 @@
                ioctl(0, TIOCSTI, &ch);
        }
        cp = canonb;
-       *cp = 0;
+       *cp = '\0';
 #endif
        cp2 = cp;
        while (cp2 < canonb + BUFSIZ)
-               *cp2++ = 0;
+               *cp2++ = '\0';
        cp2 = cp;
        if (setjmp(rewrite))
                goto redo;
Index: v7.local.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/v7.local.c,v
retrieving revision 1.2
diff -u -r1.2 v7.local.c
--- v7.local.c  1996/10/06 01:55:32     1.2
+++ v7.local.c  2001/02/15 21:31:50
@@ -52,15 +52,16 @@
  * mail is queued).
  */
 void
-findmail(user, buf)
+findmail(user, buf, buflen)
        char *user, *buf;
+       int buflen;
 {
        char    *tmp = getenv("MAIL");
 
        if (tmp == NULL)
-               (void)sprintf(buf, "%s/%s", _PATH_MAILDIR, user);
+               (void)snprintf(buf, buflen, "%s/%s", _PATH_MAILDIR, user);
        else
-               (void)strcpy(buf, tmp);
+               (void)strlcpy(buf, tmp, buflen);
 }
 
 /*
@@ -81,8 +82,14 @@
 username()
 {
        char *np;
+       uid_t uid;
 
        if ((np = getenv("USER")) != NOSTR)
                return np;
-       return getname(getuid());
+       if ((np = getenv("LOGNAME")) != NOSTR)
+               return np;
+       if ((np = getname(uid = getuid())) != NOSTR)
+               return np;
+       printf("Cannot associate a name with uid %u\n", (unsigned)uid);
+       return NOSTR;
 }
Index: vars.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/mail/vars.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 vars.c
--- vars.c      1994/05/27 12:32:07     1.1.1.1
+++ vars.c      2001/02/15 21:31:50
@@ -96,7 +96,7 @@
                return "";
        len = strlen(str) + 1;
        if ((new = malloc(len)) == NULL)
-               panic("Out of memory");
+               err(1, "Out of memory");
        bcopy(str, new, (int) len);
        return new;
 }


-- 
  Mike Heffner       <mheffner@vt.edu>
  Blacksburg, VA   <mikeh@FreeBSD.org>
  http://filebox.vt.edu/users/mheffner


--_=XFMail.1.4.7.FreeBSD:20010215192720:87326=_
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (FreeBSD)
Comment: For info see http://www.gnupg.org

iD8DBQE6jHPnFokZQs3sv5kRAk2hAJ9tcwfNi5YOHEqAblDif5vtRME0ygCfUjRM
DPlk9yQy8vSRIhvY6NoBoU8=
=dmMR
-----END PGP SIGNATURE-----

--_=XFMail.1.4.7.FreeBSD:20010215192720:87326=_--
End of MIME message


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.20010215192720.mheffner>