add .Vx so tmac.andoc will call tmac.mdoc-old
[unix-history] / usr / src / usr.bin / mail / fio.c
index 78a5683..7f0ca8a 100644 (file)
@@ -1,7 +1,19 @@
-#
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)fio.c      5.24 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "rcv.h"
 #include <sys/stat.h>
 
 #include "rcv.h"
 #include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <paths.h>
 #include <errno.h>
 
 /*
 #include <errno.h>
 
 /*
  * File I/O.
  */
 
  * File I/O.
  */
 
-static char *SccsId = "@(#)fio.c       1.10 %G%";
-
 /*
 /*
- * Set up the input pointers while copying the mail file into
- * /tmp.
+ * Set up the input pointers while copying the mail file into /tmp.
  */
  */
-
 setptr(ibuf)
 setptr(ibuf)
-       FILE *ibuf;
+       register FILE *ibuf;
 {
 {
-       register int c;
+       register int c, count;
        register char *cp, *cp2;
        register char *cp, *cp2;
-       register int count, s, l;
+       struct message this;
+       FILE *mestmp;
        off_t offset;
        off_t offset;
+       int maybe, inhead;
        char linebuf[LINESIZE];
        char linebuf[LINESIZE];
-       char wbuf[LINESIZE];
-       int maybe, mestmp, flag, inhead;
-       struct message this;
-       extern char tempSet[];
 
 
-       if ((mestmp = opentemp(tempSet)) < 0)
+       /* Get temporary file. */
+       (void)sprintf(linebuf, "%s/mail.XXXXXX", _PATH_TMP);
+       if ((c = mkstemp(linebuf)) == -1 ||
+           (mestmp = Fdopen(c, "r+")) == NULL) {
+               (void)fprintf(stderr, "mail: can't open %s\n", linebuf);
                exit(1);
                exit(1);
+       }
+       (void)unlink(linebuf);
+
        msgCount = 0;
        msgCount = 0;
-       offset = 0;
-       s = 0;
-       l = 0;
        maybe = 1;
        maybe = 1;
-       flag = MUSED|MNEW;
+       inhead = 0;
+       offset = 0;
+       this.m_flag = MUSED|MNEW;
+       this.m_size = 0;
+       this.m_lines = 0;
+       this.m_block = 0;
+       this.m_offset = 0;
        for (;;) {
        for (;;) {
-               cp = linebuf;
-               c = getc(ibuf);
-               while (c != EOF && c != '\n') {
-                       if (cp - linebuf >= BUFSIZ - 1) {
-                               ungetc(c, ibuf);
-                               *cp = 0;
-                               break;
-                       }
-                       *cp++ = c;
-                       c = getc(ibuf);
-               }
-               *cp = 0;
-               if (cp == linebuf && c == EOF) {
-                       this.m_flag = flag;
-                       flag = MUSED|MNEW;
-                       this.m_offset = offsetof(offset);
-                       this.m_block = blockof(offset);
-                       this.m_size = s;
-                       this.m_lines = l;
+               if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
                        if (append(&this, mestmp)) {
                        if (append(&this, mestmp)) {
-                               perror(tempSet);
+                               perror("temporary file");
                                exit(1);
                        }
                                exit(1);
                        }
-                       fclose(ibuf);
                        makemessage(mestmp);
                        makemessage(mestmp);
-                       close(mestmp);
                        return;
                }
                        return;
                }
-               count = cp - linebuf + 1;
-               for (cp = linebuf; *cp;)
-                       putc(*cp++, otf);
-               putc('\n', otf);
+               count = strlen(linebuf);
+               (void) fwrite(linebuf, sizeof *linebuf, count, otf);
                if (ferror(otf)) {
                        perror("/tmp");
                        exit(1);
                }
                if (ferror(otf)) {
                        perror("/tmp");
                        exit(1);
                }
+               linebuf[count - 1] = 0;
                if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
                        msgCount++;
                if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
                        msgCount++;
-                       this.m_flag = flag;
-                       flag = MUSED|MNEW;
-                       inhead = 1;
-                       this.m_block = blockof(offset);
-                       this.m_offset = offsetof(offset);
-                       this.m_size = s;
-                       this.m_lines = l;
-                       s = 0;
-                       l = 0;
                        if (append(&this, mestmp)) {
                        if (append(&this, mestmp)) {
-                               perror(tempSet);
+                               perror("temporary file");
                                exit(1);
                        }
                                exit(1);
                        }
-               }
-               if (linebuf[0] == 0)
+                       this.m_flag = MUSED|MNEW;
+                       this.m_size = 0;
+                       this.m_lines = 0;
+                       this.m_block = blockof(offset);
+                       this.m_offset = offsetof(offset);
+                       inhead = 1;
+               } else if (linebuf[0] == 0) {
                        inhead = 0;
                        inhead = 0;
-               if (inhead && index(linebuf, ':')) {
-                       cp = linebuf;
-                       cp2 = wbuf;
-                       while (isalpha(*cp))
-                               *cp2++ = *cp++;
-                       *cp2 = 0;
-                       if (icequal(wbuf, "status")) {
-                               cp = index(linebuf, ':');
-                               if (index(cp, 'R'))
-                                       flag |= MREAD;
-                               if (index(cp, 'O'))
-                                       flag &= ~MNEW;
-                               inhead = 0;
+               } else if (inhead) {
+                       for (cp = linebuf, cp2 = "status";; cp++) {
+                               if ((c = *cp2++) == 0) {
+                                       while (isspace(*cp++))
+                                               ;
+                                       if (cp[-1] != ':')
+                                               break;
+                                       while (c = *cp++)
+                                               if (c == 'R')
+                                                       this.m_flag |= MREAD;
+                                               else if (c == 'O')
+                                                       this.m_flag &= ~MNEW;
+                                       inhead = 0;
+                                       break;
+                               }
+                               if (*cp != c && *cp != toupper(c))
+                                       break;
                        }
                }
                offset += count;
                        }
                }
                offset += count;
-               s += count;
-               l++;
-               maybe = 0;
-               if (linebuf[0] == 0)
-                       maybe = 1;
+               this.m_size += count;
+               this.m_lines++;
+               maybe = linebuf[0] == 0;
        }
 }
 
        }
 }
 
@@ -122,7 +115,6 @@ setptr(ibuf)
  * If a write error occurs, return -1, else the count of
  * characters written, including the newline.
  */
  * If a write error occurs, return -1, else the count of
  * characters written, including the newline.
  */
-
 putline(obuf, linebuf)
        FILE *obuf;
        char *linebuf;
 putline(obuf, linebuf)
        FILE *obuf;
        char *linebuf;
@@ -130,43 +122,11 @@ putline(obuf, linebuf)
        register int c;
 
        c = strlen(linebuf);
        register int c;
 
        c = strlen(linebuf);
-       fputs(linebuf, obuf);
-       putc('\n', obuf);
+       (void) fwrite(linebuf, sizeof *linebuf, c, obuf);
+       (void) putc('\n', obuf);
        if (ferror(obuf))
        if (ferror(obuf))
-               return(-1);
-       return(c+1);
-}
-
-/*
- * Quickly read a line from the specified input into the line
- * buffer; return characters read.
- */
-
-freadline(ibuf, linebuf)
-       register FILE *ibuf;
-       register char *linebuf;
-{
-       register int c;
-       register char *cp;
-
-       c = getc(ibuf);
-       cp = linebuf;
-       while (c != '\n' && c != EOF) {
-               if (c == 0) {
-                       c = getc(ibuf);
-                       continue;
-               }
-               if (cp - linebuf >= BUFSIZ-1) {
-                       *cp = 0;
-                       return(cp - linebuf + 1);
-               }
-               *cp++ = c;
-               c = getc(ibuf);
-       }
-       if (c == EOF && cp == linebuf)
-               return(0);
-       *cp = 0;
-       return(cp - linebuf + 1);
+               return (-1);
+       return (c + 1);
 }
 
 /*
 }
 
 /*
@@ -174,398 +134,260 @@ freadline(ibuf, linebuf)
  * buffer.  Return the number of characters read.  Do not
  * include the newline at the end.
  */
  * buffer.  Return the number of characters read.  Do not
  * include the newline at the end.
  */
-
-readline(ibuf, linebuf)
+readline(ibuf, linebuf, linesize)
        FILE *ibuf;
        char *linebuf;
 {
        FILE *ibuf;
        char *linebuf;
 {
-       register char *cp;
-       register int c;
-
-       do {
-               clearerr(ibuf);
-               c = getc(ibuf);
-               for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
-                       if (c == 0)
-                               continue;
-                       if (cp - linebuf < LINESIZE-2)
-                               *cp++ = c;
-               }
-       } while (ferror(ibuf) && ibuf == stdin);
-       *cp = 0;
-       if (c == EOF && cp == linebuf)
-               return(0);
-       return(cp - linebuf + 1);
+       register int n;
+
+       clearerr(ibuf);
+       if (fgets(linebuf, linesize, ibuf) == NULL)
+               return -1;
+       n = strlen(linebuf);
+       if (n > 0 && linebuf[n - 1] == '\n')
+               linebuf[--n] = '\0';
+       return n;
 }
 
 /*
  * Return a file buffer all ready to read up the
  * passed message pointer.
  */
 }
 
 /*
  * Return a file buffer all ready to read up the
  * passed message pointer.
  */
-
 FILE *
 setinput(mp)
        register struct message *mp;
 {
 FILE *
 setinput(mp)
        register struct message *mp;
 {
-       off_t off;
 
        fflush(otf);
 
        fflush(otf);
-       off = mp->m_block;
-       off <<= 9;
-       off += mp->m_offset;
-       if (fseek(itf, off, 0) < 0) {
+       if (fseek(itf, positionof(mp->m_block, mp->m_offset), 0) < 0) {
                perror("fseek");
                panic("temporary file seek");
        }
                perror("fseek");
                panic("temporary file seek");
        }
-       return(itf);
+       return (itf);
 }
 
 /*
  * Take the data out of the passed ghost file and toss it into
  * a dynamically allocated message structure.
  */
 }
 
 /*
  * Take the data out of the passed ghost file and toss it into
  * a dynamically allocated message structure.
  */
-
 makemessage(f)
 makemessage(f)
+       FILE *f;
 {
 {
-       register struct message *m;
-       register char *mp;
-       register count;
+       register size = (msgCount + 1) * sizeof (struct message);
+       off_t lseek();
 
 
-       mp = calloc((unsigned) (msgCount + 1), sizeof *m);
-       if (mp == NOSTR) {
-               printf("Insufficient memory for %d messages\n", msgCount);
-               exit(1);
-       }
-       if (message != (struct message *) 0)
-               cfree((char *) message);
-       message = (struct message *) mp;
+       if (message != 0)
+               free((char *) message);
+       if ((message = (struct message *) malloc((unsigned) size)) == 0)
+               panic("Insufficient memory for %d messages", msgCount);
        dot = message;
        dot = message;
-       lseek(f, 0L, 0);
-       while (count = read(f, mp, BUFSIZ))
-               mp += count;
-       for (m = &message[0]; m < &message[msgCount]; m++) {
-               m->m_size = (m+1)->m_size;
-               m->m_lines = (m+1)->m_lines;
-               m->m_flag = (m+1)->m_flag;
-       }
+       size -= sizeof (struct message);
+       fflush(f);
+       (void) lseek(fileno(f), (long) sizeof *message, 0);
+       if (read(fileno(f), (char *) message, size) != size)
+               panic("Message temporary file corrupted");
        message[msgCount].m_size = 0;
        message[msgCount].m_lines = 0;
        message[msgCount].m_size = 0;
        message[msgCount].m_lines = 0;
+       Fclose(f);
 }
 
 /*
  * Append the passed message descriptor onto the temp file.
  * If the write fails, return 1, else 0
  */
 }
 
 /*
  * Append the passed message descriptor onto the temp file.
  * If the write fails, return 1, else 0
  */
-
 append(mp, f)
        struct message *mp;
 append(mp, f)
        struct message *mp;
+       FILE *f;
 {
 {
-       if (write(f, (char *) mp, sizeof *mp) != sizeof *mp)
-               return(1);
-       return(0);
+       return fwrite((char *) mp, sizeof *mp, 1, f) != 1;
 }
 
 /*
  * Delete a file, but only if the file is a plain file.
  */
 }
 
 /*
  * Delete a file, but only if the file is a plain file.
  */
-
-remove(name)
-       char name[];
+rm(name)
+       char *name;
 {
 {
-       struct stat statb;
-       extern int errno;
+       struct stat sb;
 
 
-       if (stat(name, &statb) < 0)
+       if (stat(name, &sb) < 0)
                return(-1);
                return(-1);
-       if ((statb.st_mode & S_IFMT) != S_IFREG) {
+       if (!S_ISREG(sb.st_mode)) {
                errno = EISDIR;
                return(-1);
        }
        return(unlink(name));
 }
 
                errno = EISDIR;
                return(-1);
        }
        return(unlink(name));
 }
 
+static int sigdepth;           /* depth of holdsigs() */
+static int omask;
 /*
 /*
- * Terminate an editing session by attempting to write out the user's
- * file from the temporary.  Save any new stuff appended to the file.
- */
-edstop()
-{
-       register int gotcha, c;
-       register struct message *mp;
-       FILE *obuf, *ibuf;
-       struct stat statb;
-       char tempname[30];
-       int (*sigs[3])();
-
-       if (readonly)
-               return;
-       sigsave(sigs, SIG_IGN);
-       for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
-               if (mp->m_flag & MNEW) {
-                       mp->m_flag &= ~MNEW;
-                       mp->m_flag |= MSTATUS;
-               }
-               if (mp->m_flag & (MODIFY|MDELETED|MSTATUS)) {
-                       gotcha++;
-                       break;
-               }
-       }
-       if (!gotcha)
-               goto done;
-       ibuf = NULL;
-       if (stat(editfile, &statb) >= 0 && statb.st_size > mailsize) {
-               strcpy(tempname, "/tmp/mboxXXXXXX");
-               mktemp(tempname);
-               if ((obuf = fopen(tempname, "w")) == NULL) {
-                       perror(tempname);
-                       sigret(sigs);
-                       reset(0);
-               }
-               if ((ibuf = fopen(editfile, "r")) == NULL) {
-                       perror(editfile);
-                       fclose(obuf);
-                       remove(tempname);
-                       sigret(sigs);
-                       reset(0);
-               }
-               while ((c = getc(ibuf)) != EOF)
-                       putc(c, obuf);
-               fclose(ibuf);
-               fclose(obuf);
-               if ((ibuf = fopen(tempname, "r")) == NULL) {
-                       perror(tempname);
-                       remove(tempname);
-                       sigret(sigs);
-                       reset(0);
-               }
-               remove(tempname);
-       }
-       printf("\"%s\" ", editfile);
-       flush();
-       if ((obuf = fopen(editfile, "w")) == NULL) {
-               perror(editfile);
-               sigret(sigs);
-               reset(0);
-       }
-       c = 0;
-       for (mp = &message[0]; mp < &message[msgCount]; mp++) {
-               if ((mp->m_flag & MDELETED) != 0)
-                       continue;
-               c++;
-               if (send(mp, obuf) < 0) {
-                       perror(editfile);
-                       sigret(sigs);
-                       reset(0);
-               }
-       }
-       gotcha = (c == 0 && ibuf == NULL);
-       if (ibuf != NULL) {
-               while ((c = getc(ibuf)) != EOF)
-                       putc(c, obuf);
-               fclose(ibuf);
-       }
-       fflush(obuf);
-       if (ferror(obuf)) {
-               perror(editfile);
-               sigret(sigs);
-               reset(0);
-       }
-       fclose(obuf);
-       if (gotcha) {
-               remove(editfile);
-               printf("removed\n");
-       }
-       else
-               printf("complete\n");
-       flush();
-
-done:
-       sigret(sigs);
-}
-
-/*
- * Save signals SIGHUP - SIGQUIT in sigs, set them all to action.
+ * Hold signals SIGHUP, SIGINT, and SIGQUIT.
  */
  */
-sigsave(sigs, action)
-       int (*sigs[])();
+holdsigs()
 {
 {
-       register int i;
 
 
-       for (i = SIGHUP; i <= SIGQUIT; i++)
-               sigs[i - SIGHUP] = sigset(i, action);
+       if (sigdepth++ == 0)
+               omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT));
 }
 
 /*
 }
 
 /*
- * Restore SIGHUP - SIGQUIT from sigs.
+ * Release signals SIGHUP, SIGINT, and SIGQUIT.
  */
  */
-sigret(sigs)
-       int (*sigs[])();
+relsesigs()
 {
 {
-       register int i;
-       
-       for (i = SIGHUP; i <= SIGQUIT; i++)
-               sigset(i, sigs[i - SIGHUP]);
-}
 
 
-/*
- * Empty the output buffer.
- */
-
-clrbuf(buf)
-       register FILE *buf;
-{
-
-       buf = stdout;
-       buf->_ptr = buf->_base;
-       buf->_cnt = BUFSIZ;
-}
-
-/*
- * Open a temp file by creating, closing, unlinking, and
- * reopening.  Return the open file descriptor.
- */
-
-opentemp(file)
-       char file[];
-{
-       register int f;
-
-       if ((f = creat(file, 0600)) < 0) {
-               perror(file);
-               return(-1);
-       }
-       close(f);
-       if ((f = open(file, 2)) < 0) {
-               perror(file);
-               remove(file);
-               return(-1);
-       }
-       remove(file);
-       return(f);
-}
-
-/*
- * Flush the standard output.
- */
-
-flush()
-{
-       fflush(stdout);
-       fflush(stderr);
+       if (--sigdepth == 0)
+               sigsetmask(omask);
 }
 
 /*
  * Determine the size of the file possessed by
  * the passed buffer.
  */
 }
 
 /*
  * Determine the size of the file possessed by
  * the passed buffer.
  */
-
 off_t
 fsize(iob)
        FILE *iob;
 {
 off_t
 fsize(iob)
        FILE *iob;
 {
-       register int f;
        struct stat sbuf;
 
        struct stat sbuf;
 
-       f = fileno(iob);
-       if (fstat(f, &sbuf) < 0)
-               return(0);
-       return(sbuf.st_size);
+       if (fstat(fileno(iob), &sbuf) < 0)
+               return 0;
+       return sbuf.st_size;
 }
 
 /*
 }
 
 /*
- * Take a file name, possibly with shell meta characters
- * in it and expand it by using "sh -c echo filename"
+ * Evaluate the string given as a new mailbox name.
+ * Supported meta characters:
+ *     %       for my system mail box
+ *     %user   for user's system mail box
+ *     #       for previous file
+ *     &       invoker's mbox file
+ *     +file   file in folder directory
+ *     any shell meta character
  * Return the file name as a dynamic string.
  */
  * Return the file name as a dynamic string.
  */
-
 char *
 expand(name)
 char *
 expand(name)
-       char name[];
+       register char *name;
 {
 {
-       char xname[BUFSIZ];
-       char cmdbuf[BUFSIZ];
-       register int pid, l, rc;
-       register char *cp, *Shell;
-       int s, pivec[2], (*sigint)();
+       char xname[PATHSIZE];
+       char cmdbuf[PATHSIZE];          /* also used for file names */
+       register int pid, l;
+       register char *cp, *shell;
+       int pivec[2];
        struct stat sbuf;
        struct stat sbuf;
-
+       extern union wait wait_status;
+
+       /*
+        * The order of evaluation is "%" and "#" expand into constants.
+        * "&" can expand into "+".  "+" can expand into shell meta characters.
+        * Shell meta characters expand into constants.
+        * This way, we make no recursive expansion.
+        */
+       switch (*name) {
+       case '%':
+               findmail(name[1] ? name + 1 : myname, xname);
+               return savestr(xname);
+       case '#':
+               if (name[1] != 0)
+                       break;
+               if (prevfile[0] == 0) {
+                       printf("No previous file\n");
+                       return NOSTR;
+               }
+               return savestr(prevfile);
+       case '&':
+               if (name[1] == 0 && (name = value("MBOX")) == NOSTR)
+                       name = "~/mbox";
+               /* fall through */
+       }
+       if (name[0] == '+' && getfold(cmdbuf) >= 0) {
+               sprintf(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);
+               name = savestr(xname);
+       }
        if (!anyof(name, "~{[*?$`'\"\\"))
        if (!anyof(name, "~{[*?$`'\"\\"))
-               return(name);
+               return name;
        if (pipe(pivec) < 0) {
                perror("pipe");
        if (pipe(pivec) < 0) {
                perror("pipe");
-               return(name);
+               return name;
        }
        sprintf(cmdbuf, "echo %s", name);
        }
        sprintf(cmdbuf, "echo %s", name);
-       if ((pid = vfork()) == 0) {
-               Shell = value("SHELL");
-               if (Shell == NOSTR)
-                       Shell = SHELL;
+       if ((shell = value("SHELL")) == NOSTR)
+               shell = _PATH_CSHELL;
+       pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR);
+       if (pid < 0) {
                close(pivec[0]);
                close(pivec[0]);
-               close(1);
-               dup(pivec[1]);
                close(pivec[1]);
                close(pivec[1]);
-               close(2);
-               execl(Shell, Shell, "-c", cmdbuf, 0);
-               _exit(1);
-       }
-       if (pid == -1) {
-               perror("fork");
-               close(pivec[0]);
-               close(pivec[1]);
-               return(NOSTR);
+               return NOSTR;
        }
        close(pivec[1]);
        l = read(pivec[0], xname, BUFSIZ);
        close(pivec[0]);
        }
        close(pivec[1]);
        l = read(pivec[0], xname, BUFSIZ);
        close(pivec[0]);
-       while (wait(&s) != pid);
-               ;
-       s &= 0377;
-       if (s != 0 && s != SIGPIPE) {
-               fprintf(stderr, "\"Echo\" failed\n");
-               goto err;
+       if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) {
+               fprintf(stderr, "\"%s\": Expansion failed.\n", name);
+               return NOSTR;
        }
        if (l < 0) {
                perror("read");
        }
        if (l < 0) {
                perror("read");
-               goto err;
+               return NOSTR;
        }
        if (l == 0) {
        }
        if (l == 0) {
-               fprintf(stderr, "\"%s\": No match\n", name);
-               goto err;
+               fprintf(stderr, "\"%s\": No match.\n", name);
+               return NOSTR;
        }
        if (l == BUFSIZ) {
        }
        if (l == BUFSIZ) {
-               fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
-               goto err;
+               fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name);
+               return NOSTR;
        }
        xname[l] = 0;
        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                ;
        }
        xname[l] = 0;
        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                ;
-       *++cp = '\0';
-       if (any(' ', xname) && stat(xname, &sbuf) < 0) {
-               fprintf(stderr, "\"%s\": Ambiguous\n", name);
-               goto err;
+       cp[1] = '\0';
+       if (index(xname, ' ') && stat(xname, &sbuf) < 0) {
+               fprintf(stderr, "\"%s\": Ambiguous.\n", name);
+               return NOSTR;
        }
        }
-       return(savestr(xname));
-
-err:
-       return(NOSTR);
+       return savestr(xname);
 }
 
 /*
 }
 
 /*
- * A nicer version of Fdopen, which allows us to fclose
- * without losing the open file.
+ * Determine the current folder directory name.
  */
  */
+getfold(name)
+       char *name;
+{
+       char *folder;
 
 
-FILE *
-Fdopen(fildes, mode)
-       char *mode;
+       if ((folder = value("folder")) == NOSTR)
+               return (-1);
+       if (*folder == '/')
+               strcpy(name, folder);
+       else
+               sprintf(name, "%s/%s", homedir, folder);
+       return (0);
+}
+
+/*
+ * Return the name of the dead.letter file.
+ */
+char *
+getdeadletter()
 {
 {
-       register int f;
-       FILE *fdopen();
+       register char *cp;
+
+       if ((cp = value("DEAD")) == NOSTR || (cp = expand(cp)) == NOSTR)
+               cp = expand("~/dead.letter");
+       else if (*cp != '/') {
+               char buf[PATHSIZE];
 
 
-       f = dup(fildes);
-       if (f < 0) {
-               perror("dup");
-               return(NULL);
+               (void) sprintf(buf, "~/%s", cp);
+               cp = expand(buf);
        }
        }
-       return(fdopen(f, mode));
+       return cp;
 }
 }