X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/3a125934e8be273e196a4d82d171c6ca822351a6..ee9b0a0a8b22a0093f2be1a2d21620e27628666a:/usr/src/usr.bin/mail/fio.c diff --git a/usr/src/usr.bin/mail/fio.c b/usr/src/usr.bin/mail/fio.c index e3cd0bbb98..7f0ca8a31a 100644 --- a/usr/src/usr.bin/mail/fio.c +++ b/usr/src/usr.bin/mail/fio.c @@ -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 +#include +#include +#include #include /* @@ -10,110 +22,91 @@ * File I/O. */ -static char *SccsId = "@(#)fio.c 2.6 %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) - FILE *ibuf; + register FILE *ibuf; { - register int c; + register int c, count; register char *cp, *cp2; - register int count, s, l; + struct message this; + FILE *mestmp; off_t offset; + int maybe, inhead; 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); + } + (void)unlink(linebuf); + msgCount = 0; - offset = 0; - s = 0; - l = 0; 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 (;;) { - 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; - 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)) { - perror(tempSet); + perror("temporary file"); exit(1); } - fclose(ibuf); makemessage(mestmp); - close(mestmp); 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); } + linebuf[count - 1] = 0; 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)) { - perror(tempSet); + perror("temporary file"); 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; - 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; - 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. */ - putline(obuf, linebuf) FILE *obuf; char *linebuf; @@ -130,43 +122,11 @@ putline(obuf, 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)) - 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,412 +134,260 @@ freadline(ibuf, linebuf) * 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; { - 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. */ - FILE * setinput(mp) register struct message *mp; { - off_t off; 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"); } - return(itf); + return (itf); } /* * Take the data out of the passed ghost file and toss it into * a dynamically allocated message structure. */ - 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; - 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; + Fclose(f); } /* * Append the passed message descriptor onto the temp file. * If the write fails, return 1, else 0 */ - 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. */ - -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); - if ((statb.st_mode & S_IFMT) != S_IFREG) { + if (!S_ISREG(sb.st_mode)) { 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, *readstat; - struct stat statb; - char tempname[30], *id; - int (*sigs[3])(); - - 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++; - if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { - if ((id = hfield("article-id", mp)) != NOSTR) - fprintf(readstat, "%s\n", id); - } - } - 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); - relsesigs(); - 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); - relsesigs(); - 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); - relsesigs(); - reset(0); - } - fclose(obuf); - if (gotcha) { - remove(editfile); - printf("removed\n"); - } - else - printf("complete\n"); - flush(); - -done: - relsesigs(); -} - -/* - * Hold signals SIGHUP - SIGQUIT. + * Hold signals SIGHUP, SIGINT, and SIGQUIT. */ holdsigs() { - register int i; - for (i = SIGHUP; i <= SIGQUIT; i++) - sighold(i); + if (sigdepth++ == 0) + omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT)); } /* - * Release signals SIGHUP - SIGQUIT + * Release signals SIGHUP, SIGINT, and SIGQUIT. */ relsesigs() { - register int i; - - for (i = SIGHUP; i <= SIGQUIT; i++) - sigrelse(i); -} - -/* - * 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. */ - off_t fsize(iob) FILE *iob; { - register int f; 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. */ - 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; - - if (name[0] == '+' && (cp = value("maildir")) != 0) { - if (*cp == '/') - sprintf(xname, "%s/%s", cp, name + 1); - else - sprintf(xname, "%s/%s/%s", homedir, cp, name + 1); - return(expand(savestr(xname))); + 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, "~{[*?$`'\"\\")) - return(name); + return name; if (pipe(pivec) < 0) { perror("pipe"); - return(name); + return 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(1); - dup(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]); - 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"); - goto err; + return NOSTR; } if (l == 0) { - fprintf(stderr, "\"%s\": No match\n", name); - goto err; + fprintf(stderr, "\"%s\": No match.\n", name); + return NOSTR; } 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--) ; - *++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; }