Added declaration of icequal();
[unix-history] / usr / src / usr.bin / mail / fio.c
index 7a4e7df..41c677c 100644 (file)
@@ -10,7 +10,7 @@
  * File I/O.
  */
 
  * File I/O.
  */
 
-static char *SccsId = "@(#)fio.c       1.1 %G%";
+static char *SccsId = "@(#)fio.c       2.12 %G%";
 
 /*
  * Set up the input pointers while copying the mail file into
 
 /*
  * Set up the input pointers while copying the mail file into
@@ -20,10 +20,14 @@ static char *SccsId = "@(#)fio.c    1.1 %G%";
 setptr(ibuf)
        FILE *ibuf;
 {
 setptr(ibuf)
        FILE *ibuf;
 {
-       register int count, s, l;
+       register int c;
+       register char *cp, *cp2;
+       register int count, l;
+       long s;
        off_t offset;
        char linebuf[LINESIZE];
        off_t offset;
        char linebuf[LINESIZE];
-       int maybe, mestmp, flag;
+       char wbuf[LINESIZE];
+       int maybe, mestmp, flag, inhead;
        struct message this;
        extern char tempSet[];
 
        struct message this;
        extern char tempSet[];
 
@@ -31,15 +35,26 @@ setptr(ibuf)
                exit(1);
        msgCount = 0;
        offset = 0;
                exit(1);
        msgCount = 0;
        offset = 0;
-       s = 0;
+       s = 0L;
        l = 0;
        maybe = 1;
        l = 0;
        maybe = 1;
-       flag = MUSED;
-       if (value("hold") != NOSTR)
-               flag = MPRESERVE|MUSED;
+       flag = MUSED|MNEW;
        for (;;) {
        for (;;) {
-               if ((count = readline(ibuf, linebuf)) == 0) {
+               cp = linebuf;
+               c = getc(ibuf);
+               while (c != EOF && c != '\n') {
+                       if (cp - linebuf >= LINESIZE - 1) {
+                               ungetc(c, ibuf);
+                               *cp = 0;
+                               break;
+                       }
+                       *cp++ = c;
+                       c = getc(ibuf);
+               }
+               *cp = 0;
+               if (cp == linebuf && c == EOF) {
                        this.m_flag = flag;
                        this.m_flag = flag;
+                       flag = MUSED|MNEW;
                        this.m_offset = offsetof(offset);
                        this.m_block = blockof(offset);
                        this.m_size = s;
                        this.m_offset = offsetof(offset);
                        this.m_block = blockof(offset);
                        this.m_size = s;
@@ -53,26 +68,49 @@ setptr(ibuf)
                        close(mestmp);
                        return;
                }
                        close(mestmp);
                        return;
                }
-               if (putline(otf, linebuf) < 0) {
+               count = cp - linebuf + 1;
+               for (cp = linebuf; *cp;)
+                       putc(*cp++, otf);
+               putc('\n', otf);
+               if (ferror(otf)) {
                        perror("/tmp");
                        exit(1);
                }
                        perror("/tmp");
                        exit(1);
                }
-               if (maybe && ishead(linebuf)) {
+               if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
                        msgCount++;
                        this.m_flag = flag;
                        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;
                        this.m_block = blockof(offset);
                        this.m_offset = offsetof(offset);
                        this.m_size = s;
                        this.m_lines = l;
-                       s = 0;
+                       s = 0L;
                        l = 0;
                        if (append(&this, mestmp)) {
                                perror(tempSet);
                                exit(1);
                        }
                }
                        l = 0;
                        if (append(&this, mestmp)) {
                                perror(tempSet);
                                exit(1);
                        }
                }
+               if (linebuf[0] == 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;
+                       }
+               }
                offset += count;
                offset += count;
-               s += count;
+               s += (long) count;
                l++;
                maybe = 0;
                if (linebuf[0] == 0)
                l++;
                maybe = 0;
                if (linebuf[0] == 0)
@@ -100,6 +138,38 @@ putline(obuf, linebuf)
        return(c+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);
+}
+
 /*
  * Read up a line from the specified input into the line
  * buffer.  Return the number of characters read.  Do not
 /*
  * Read up a line from the specified input into the line
  * buffer.  Return the number of characters read.  Do not
@@ -167,6 +237,8 @@ makemessage(f)
                printf("Insufficient memory for %d messages\n", msgCount);
                exit(1);
        }
                printf("Insufficient memory for %d messages\n", msgCount);
                exit(1);
        }
+       if (message != (struct message *) 0)
+               cfree((char *) message);
        message = (struct message *) mp;
        dot = message;
        lseek(f, 0L, 0);
        message = (struct message *) mp;
        dot = message;
        lseek(f, 0L, 0);
@@ -175,8 +247,9 @@ makemessage(f)
        for (m = &message[0]; m < &message[msgCount]; m++) {
                m->m_size = (m+1)->m_size;
                m->m_lines = (m+1)->m_lines;
        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;
        }
        }
-       message[msgCount].m_size = 0;
+       message[msgCount].m_size = 0L;
        message[msgCount].m_lines = 0;
 }
 
        message[msgCount].m_lines = 0;
 }
 
@@ -214,26 +287,74 @@ remove(name)
 
 /*
  * Terminate an editing session by attempting to write out the user's
 
 /*
  * Terminate an editing session by attempting to write out the user's
- * file from the temporary.
+ * file from the temporary.  Save any new stuff appended to the file.
  */
  */
-
 edstop()
 {
        register int gotcha, c;
        register struct message *mp;
 edstop()
 {
        register int gotcha, c;
        register struct message *mp;
-       FILE *obuf;
+       FILE *obuf, *ibuf, *readstat;
+       struct stat statb;
+       char tempname[30], *id;
+       int (*sigs[3])();
 
 
-       for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++)
-               if (mp->m_flag & (MODIFY|MDELETED)) {
+       if (readonly)
+               return;
+       holdsigs();
+       if (Tflag != NOSTR) {
+               if ((readstat = fopen(Tflag, "w")) == NULL)
+                       Tflag = NOSTR;
+       }
+       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++;
                        gotcha++;
-                       break;
+               if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
+                       if ((id = hfield("article-id", mp)) != NOSTR)
+                               fprintf(readstat, "%s\n", id);
                }
                }
-       if (!gotcha)
-               return;
+       }
+       if (Tflag != NOSTR)
+               fclose(readstat);
+       if (!gotcha || Tflag != NOSTR)
+               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);
+                       relsesigs();
+                       reset(0);
+               }
+               if ((ibuf = fopen(editfile, "r")) == NULL) {
+                       perror(editfile);
+                       fclose(obuf);
+                       remove(tempname);
+                       relsesigs();
+                       reset(0);
+               }
+               fseek(ibuf, mailsize, 0);
+               while ((c = getc(ibuf)) != EOF)
+                       putc(c, obuf);
+               fclose(ibuf);
+               fclose(obuf);
+               if ((ibuf = fopen(tempname, "r")) == NULL) {
+                       perror(tempname);
+                       remove(tempname);
+                       relsesigs();
+                       reset(0);
+               }
+               remove(tempname);
+       }
        printf("\"%s\" ", editfile);
        flush();
        if ((obuf = fopen(editfile, "w")) == NULL) {
                perror(editfile);
        printf("\"%s\" ", editfile);
        flush();
        if ((obuf = fopen(editfile, "w")) == NULL) {
                perror(editfile);
+               relsesigs();
                reset(0);
        }
        c = 0;
                reset(0);
        }
        c = 0;
@@ -241,23 +362,63 @@ edstop()
                if ((mp->m_flag & MDELETED) != 0)
                        continue;
                c++;
                if ((mp->m_flag & MDELETED) != 0)
                        continue;
                c++;
-               if (send(mp, obuf) < 0) {
+               if (send(mp, obuf, 0) < 0) {
                        perror(editfile);
                        perror(editfile);
+                       relsesigs();
                        reset(0);
                }
        }
                        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);
        fflush(obuf);
        if (ferror(obuf)) {
                perror(editfile);
+               relsesigs();
                reset(0);
        }
                reset(0);
        }
-       if (c == 0) {
+       fclose(obuf);
+       if (gotcha) {
                remove(editfile);
                printf("removed\n");
        }
        else
                printf("complete\n");
        flush();
                remove(editfile);
                printf("removed\n");
        }
        else
                printf("complete\n");
        flush();
+
+done:
+       relsesigs();
+}
+
+/*
+ * Hold signals SIGHUP - SIGQUIT.
+ */
+holdsigs()
+{
+       register int i;
+
+       for (i = SIGHUP; i <= SIGQUIT; i++)
+               /*
+                * This cannot be changed to ``sighold(i)'' because
+                * of a bug in the jobs library.  Sighold does not
+                * record that one is using the new signal mechanisms
+                * so an eventual sigrelse() will fail.
+                */
+               sigset(i, SIG_HOLD);
+}
+
+/*
+ * Release signals SIGHUP - SIGQUIT
+ */
+relsesigs()
+{
+       register int i;
+
+       for (i = SIGHUP; i <= SIGQUIT; i++)
+               sigrelse(i);
 }
 
 /*
 }
 
 /*
@@ -342,16 +503,19 @@ expand(name)
        int s, pivec[2], (*sigint)();
        struct stat sbuf;
 
        int s, pivec[2], (*sigint)();
        struct stat sbuf;
 
+       if (name[0] == '+' && getfold(cmdbuf) >= 0) {
+               sprintf(xname, "%s/%s", cmdbuf, name + 1);
+               return(expand(savestr(xname)));
+       }
        if (!anyof(name, "~{[*?$`'\"\\"))
                return(name);
        if (!anyof(name, "~{[*?$`'\"\\"))
                return(name);
-       /* sigint = signal(SIGINT, SIG_IGN); */
        if (pipe(pivec) < 0) {
                perror("pipe");
        if (pipe(pivec) < 0) {
                perror("pipe");
-               /* signal(SIGINT, sigint) */
                return(name);
        }
        sprintf(cmdbuf, "echo %s", name);
        if ((pid = vfork()) == 0) {
                return(name);
        }
        sprintf(cmdbuf, "echo %s", name);
        if ((pid = vfork()) == 0) {
+               sigchild();
                Shell = value("SHELL");
                if (Shell == NOSTR)
                        Shell = SHELL;
                Shell = value("SHELL");
                if (Shell == NOSTR)
                        Shell = SHELL;
@@ -399,14 +563,29 @@ expand(name)
                fprintf(stderr, "\"%s\": Ambiguous\n", name);
                goto err;
        }
                fprintf(stderr, "\"%s\": Ambiguous\n", name);
                goto err;
        }
-       /* signal(SIGINT, sigint) */
        return(savestr(xname));
 
 err:
        return(savestr(xname));
 
 err:
-       /* signal(SIGINT, sigint); */
        return(NOSTR);
 }
 
        return(NOSTR);
 }
 
+/*
+ * Determine the current folder directory name.
+ */
+getfold(name)
+       char *name;
+{
+       char *folder;
+
+       if ((folder = value("folder")) == NOSTR)
+               return(-1);
+       if (*folder == '/')
+               strcpy(name, folder);
+       else
+               sprintf(name, "%s/%s", homedir, folder);
+       return(0);
+}
+
 /*
  * A nicer version of Fdopen, which allows us to fclose
  * without losing the open file.
 /*
  * A nicer version of Fdopen, which allows us to fclose
  * without losing the open file.