Annotation of 43BSDTahoe/ucb/Mail/fio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that this notice is preserved and that due credit is given
                      7:  * to the University of California at Berkeley. The name of the University
                      8:  * may not be used to endorse or promote products derived from this
                      9:  * software without specific prior written permission. This software
                     10:  * is provided ``as is'' without express or implied warranty.
                     11:  */
                     12: 
                     13: #ifdef notdef
                     14: static char sccsid[] = "@(#)fio.c      5.6 (Berkeley) 2/18/88";
                     15: #endif /* notdef */
                     16: 
                     17: #include "rcv.h"
                     18: #include <sys/stat.h>
                     19: #include <sys/file.h>
                     20: #include <sys/wait.h>
                     21: #include <errno.h>
                     22: 
                     23: /*
                     24:  * Mail -- a mail program
                     25:  *
                     26:  * File I/O.
                     27:  */
                     28: 
                     29: /*
                     30:  * Set up the input pointers while copying the mail file into
                     31:  * /tmp.
                     32:  */
                     33: setptr(ibuf)
                     34:        register FILE *ibuf;
                     35: {
                     36:        register c;
                     37:        register char *cp, *cp2;
                     38:        register count;
                     39:        char linebuf[LINESIZE];
                     40:        int maybe, inhead;
                     41:        FILE *mestmp;
                     42:        off_t offset;
                     43:        struct message this;
                     44:        extern char tempSet[];
                     45: 
                     46:        if ((c = opentemp(tempSet)) < 0)
                     47:                exit(1);
                     48:        if ((mestmp = fdopen(c, "r+")) == NULL)
                     49:                panic("Can't open temporary");
                     50:        msgCount = 0;
                     51:        maybe = 1;
                     52:        inhead = 0;
                     53:        offset = 0;
                     54:        this.m_flag = MUSED|MNEW;
                     55:        this.m_size = 0;
                     56:        this.m_lines = 0;
                     57:        this.m_block = 0;
                     58:        this.m_offset = 0;
                     59:        for (;;) {
                     60:                if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
                     61:                        if (append(&this, mestmp)) {
                     62:                                perror(tempSet);
                     63:                                exit(1);
                     64:                        }
                     65:                        fclose(ibuf);
                     66:                        makemessage(mestmp);
                     67:                        return;
                     68:                }
                     69:                count = strlen(linebuf);
                     70:                fwrite(linebuf, sizeof *linebuf, count, otf);
                     71:                if (ferror(otf)) {
                     72:                        perror("/tmp");
                     73:                        exit(1);
                     74:                }
                     75:                linebuf[count - 1] = 0;
                     76:                if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
                     77:                        msgCount++;
                     78:                        if (append(&this, mestmp)) {
                     79:                                perror(tempSet);
                     80:                                exit(1);
                     81:                        }
                     82:                        this.m_flag = MUSED|MNEW;
                     83:                        this.m_size = 0;
                     84:                        this.m_lines = 0;
                     85:                        this.m_block = blockof(offset);
                     86:                        this.m_offset = offsetof(offset);
                     87:                        inhead = 1;
                     88:                } else if (linebuf[0] == 0) {
                     89:                        inhead = 0;
                     90:                } else if (inhead) {
                     91:                        for (cp = linebuf, cp2 = "status";; cp++) {
                     92:                                if ((c = *cp2++) == 0) {
                     93:                                        while (isspace(*cp++))
                     94:                                                ;
                     95:                                        if (cp[-1] != ':')
                     96:                                                break;
                     97:                                        while (c = *cp++)
                     98:                                                if (c == 'R')
                     99:                                                        this.m_flag |= MREAD;
                    100:                                                else if (c == 'O')
                    101:                                                        this.m_flag &= ~MNEW;
                    102:                                        inhead = 0;
                    103:                                        break;
                    104:                                }
                    105:                                if (*cp != c && *cp != toupper(c))
                    106:                                        break;
                    107:                        }
                    108:                }
                    109:                offset += count;
                    110:                this.m_size += count;
                    111:                this.m_lines++;
                    112:                maybe = linebuf[0] == 0;
                    113:        }
                    114: }
                    115: 
                    116: /*
                    117:  * Drop the passed line onto the passed output buffer.
                    118:  * If a write error occurs, return -1, else the count of
                    119:  * characters written, including the newline.
                    120:  */
                    121: putline(obuf, linebuf)
                    122:        FILE *obuf;
                    123:        char *linebuf;
                    124: {
                    125:        register int c;
                    126: 
                    127:        c = strlen(linebuf);
                    128:        fwrite(linebuf, sizeof *linebuf, c, obuf);
                    129:        putc('\n', obuf);
                    130:        if (ferror(obuf))
                    131:                return (-1);
                    132:        return (c + 1);
                    133: }
                    134: 
                    135: /*
                    136:  * Read up a line from the specified input into the line
                    137:  * buffer.  Return the number of characters read.  Do not
                    138:  * include the newline at the end.
                    139:  */
                    140: readline(ibuf, linebuf)
                    141:        FILE *ibuf;
                    142:        char *linebuf;
                    143: {
                    144:        register int n;
                    145: 
                    146:        clearerr(ibuf);
                    147:        if (fgets(linebuf, LINESIZE, ibuf) == NULL)
                    148:                return -1;
                    149:        n = strlen(linebuf);
                    150:        if (n > 0 && linebuf[n - 1] == '\n')
                    151:                linebuf[--n] = '\0';
                    152:        return n;
                    153: }
                    154: 
                    155: /*
                    156:  * Return a file buffer all ready to read up the
                    157:  * passed message pointer.
                    158:  */
                    159: FILE *
                    160: setinput(mp)
                    161:        register struct message *mp;
                    162: {
                    163: 
                    164:        fflush(otf);
                    165:        if (fseek(itf, positionof(mp->m_block, mp->m_offset), 0) < 0) {
                    166:                perror("fseek");
                    167:                panic("temporary file seek");
                    168:        }
                    169:        return (itf);
                    170: }
                    171: 
                    172: /*
                    173:  * Take the data out of the passed ghost file and toss it into
                    174:  * a dynamically allocated message structure.
                    175:  */
                    176: makemessage(f)
                    177:        FILE *f;
                    178: {
                    179:        register size = (msgCount + 1) * sizeof (struct message);
                    180:        off_t lseek();
                    181: 
                    182:        if (message != 0)
                    183:                free((char *) message);
                    184:        if ((message = (struct message *) malloc((unsigned) size)) == 0)
                    185:                panic("Insufficient memory for %d messages", msgCount);
                    186:        dot = message;
                    187:        size -= sizeof (struct message);
                    188:        fflush(f);
                    189:        lseek(fileno(f), (long) sizeof *message, 0);
                    190:        if (read(fileno(f), (char *) message, size) != size)
                    191:                panic("Message temporary file corrupted");
                    192:        message[msgCount].m_size = 0;
                    193:        message[msgCount].m_lines = 0;
                    194:        fclose(f);
                    195: }
                    196: 
                    197: /*
                    198:  * Append the passed message descriptor onto the temp file.
                    199:  * If the write fails, return 1, else 0
                    200:  */
                    201: append(mp, f)
                    202:        struct message *mp;
                    203:        FILE *f;
                    204: {
                    205:        return fwrite((char *) mp, sizeof *mp, 1, f) != 1;
                    206: }
                    207: 
                    208: /*
                    209:  * Delete a file, but only if the file is a plain file.
                    210:  */
                    211: remove(name)
                    212:        char name[];
                    213: {
                    214:        struct stat statb;
                    215:        extern int errno;
                    216: 
                    217:        if (stat(name, &statb) < 0)
                    218:                return(-1);
                    219:        if ((statb.st_mode & S_IFMT) != S_IFREG) {
                    220:                errno = EISDIR;
                    221:                return(-1);
                    222:        }
                    223:        return unlink(name);
                    224: }
                    225: 
                    226: /*
                    227:  * Terminate an editing session by attempting to write out the user's
                    228:  * file from the temporary.  Save any new stuff appended to the file.
                    229:  */
                    230: edstop()
                    231: {
                    232:        register int gotcha, c;
                    233:        register struct message *mp;
                    234:        FILE *obuf, *ibuf, *readstat;
                    235:        struct stat statb;
                    236:        char tempname[30], *id;
                    237:        char *mktemp();
                    238: 
                    239:        if (readonly)
                    240:                return;
                    241:        holdsigs();
                    242:        if (Tflag != NOSTR) {
                    243:                if ((readstat = fopen(Tflag, "w")) == NULL)
                    244:                        Tflag = NOSTR;
                    245:        }
                    246:        for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
                    247:                if (mp->m_flag & MNEW) {
                    248:                        mp->m_flag &= ~MNEW;
                    249:                        mp->m_flag |= MSTATUS;
                    250:                }
                    251:                if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
                    252:                        gotcha++;
                    253:                if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
                    254:                        if ((id = hfield("article-id", mp)) != NOSTR)
                    255:                                fprintf(readstat, "%s\n", id);
                    256:                }
                    257:        }
                    258:        if (Tflag != NOSTR)
                    259:                fclose(readstat);
                    260:        if (!gotcha || Tflag != NOSTR)
                    261:                goto done;
                    262:        ibuf = NULL;
                    263:        if (stat(editfile, &statb) >= 0 && statb.st_size > mailsize) {
                    264:                strcpy(tempname, "/tmp/mboxXXXXXX");
                    265:                mktemp(tempname);
                    266:                if ((obuf = fopen(tempname, "w")) == NULL) {
                    267:                        perror(tempname);
                    268:                        relsesigs();
                    269:                        reset(0);
                    270:                }
                    271:                if ((ibuf = fopen(editfile, "r")) == NULL) {
                    272:                        perror(editfile);
                    273:                        fclose(obuf);
                    274:                        remove(tempname);
                    275:                        relsesigs();
                    276:                        reset(0);
                    277:                }
                    278:                fseek(ibuf, mailsize, 0);
                    279:                while ((c = getc(ibuf)) != EOF)
                    280:                        putc(c, obuf);
                    281:                fclose(ibuf);
                    282:                fclose(obuf);
                    283:                if ((ibuf = fopen(tempname, "r")) == NULL) {
                    284:                        perror(tempname);
                    285:                        remove(tempname);
                    286:                        relsesigs();
                    287:                        reset(0);
                    288:                }
                    289:                remove(tempname);
                    290:        }
                    291:        printf("\"%s\" ", editfile);
                    292:        fflush(stdout);
                    293:        if ((obuf = fopen(editfile, "r+")) == NULL) {
                    294:                perror(editfile);
                    295:                relsesigs();
                    296:                reset(0);
                    297:        }
                    298:        trunc(obuf);
                    299:        c = 0;
                    300:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    301:                if ((mp->m_flag & MDELETED) != 0)
                    302:                        continue;
                    303:                c++;
                    304:                if (send(mp, obuf, 0) < 0) {
                    305:                        perror(editfile);
                    306:                        relsesigs();
                    307:                        reset(0);
                    308:                }
                    309:        }
                    310:        gotcha = (c == 0 && ibuf == NULL);
                    311:        if (ibuf != NULL) {
                    312:                while ((c = getc(ibuf)) != EOF)
                    313:                        putc(c, obuf);
                    314:                fclose(ibuf);
                    315:        }
                    316:        fflush(obuf);
                    317:        if (ferror(obuf)) {
                    318:                perror(editfile);
                    319:                relsesigs();
                    320:                reset(0);
                    321:        }
                    322:        fclose(obuf);
                    323:        if (gotcha) {
                    324:                remove(editfile);
                    325:                printf("removed\n");
                    326:        }
                    327:        else
                    328:                printf("complete\n");
                    329:        fflush(stdout);
                    330: 
                    331: done:
                    332:        relsesigs();
                    333: }
                    334: 
                    335: static int sigdepth = 0;               /* depth of holdsigs() */
                    336: static int omask = 0;
                    337: /*
                    338:  * Hold signals SIGHUP, SIGINT, and SIGQUIT.
                    339:  */
                    340: holdsigs()
                    341: {
                    342: 
                    343:        if (sigdepth++ == 0)
                    344:                omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT));
                    345: }
                    346: 
                    347: /*
                    348:  * Release signals SIGHUP, SIGINT, and SIGQUIT.
                    349:  */
                    350: relsesigs()
                    351: {
                    352: 
                    353:        if (--sigdepth == 0)
                    354:                sigsetmask(omask);
                    355: }
                    356: 
                    357: /*
                    358:  * Open a temp file by creating and unlinking.
                    359:  * Return the open file descriptor.
                    360:  */
                    361: opentemp(file)
                    362:        char file[];
                    363: {
                    364:        int f;
                    365: 
                    366:        if ((f = open(file, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0)
                    367:                perror(file);
                    368:        remove(file);
                    369:        return (f);
                    370: }
                    371: 
                    372: /*
                    373:  * Determine the size of the file possessed by
                    374:  * the passed buffer.
                    375:  */
                    376: off_t
                    377: fsize(iob)
                    378:        FILE *iob;
                    379: {
                    380:        struct stat sbuf;
                    381: 
                    382:        if (fstat(fileno(iob), &sbuf) < 0)
                    383:                return 0;
                    384:        return sbuf.st_size;
                    385: }
                    386: 
                    387: /*
                    388:  * Take a file name, possibly with shell meta characters
                    389:  * in it and expand it by using "sh -c echo filename"
                    390:  * Return the file name as a dynamic string.
                    391:  */
                    392: char *
                    393: expand(name)
                    394:        char name[];
                    395: {
                    396:        char xname[BUFSIZ];
                    397:        char cmdbuf[BUFSIZ];
                    398:        register int pid, l;
                    399:        register char *cp, *Shell;
                    400:        int pivec[2];
                    401:        struct stat sbuf;
                    402:        union wait s;
                    403: 
                    404:        if (name[0] == '+' && getfold(cmdbuf) >= 0) {
                    405:                sprintf(xname, "%s/%s", cmdbuf, name + 1);
                    406:                return(expand(savestr(xname)));
                    407:        }
                    408:        if (!anyof(name, "~{[*?$`'\"\\"))
                    409:                return(name);
                    410:        if (pipe(pivec) < 0) {
                    411:                perror("pipe");
                    412:                return(name);
                    413:        }
                    414:        sprintf(cmdbuf, "echo %s", name);
                    415:        if ((pid = vfork()) == 0) {
                    416:                Shell = value("SHELL");
                    417:                if (Shell == NOSTR)
                    418:                        Shell = SHELL;
                    419:                close(pivec[0]);
                    420:                close(1);
                    421:                dup(pivec[1]);
                    422:                close(pivec[1]);
                    423:                close(2);
                    424:                execl(Shell, Shell, "-c", cmdbuf, 0);
                    425:                _exit(1);
                    426:        }
                    427:        if (pid == -1) {
                    428:                perror("fork");
                    429:                close(pivec[0]);
                    430:                close(pivec[1]);
                    431:                return(NOSTR);
                    432:        }
                    433:        close(pivec[1]);
                    434:        l = read(pivec[0], xname, BUFSIZ);
                    435:        close(pivec[0]);
                    436:        while (wait(&s) != pid);
                    437:                ;
                    438:        if (s.w_status != 0 && s.w_termsig != SIGPIPE) {
                    439:                fprintf(stderr, "\"Echo\" failed\n");
                    440:                goto err;
                    441:        }
                    442:        if (l < 0) {
                    443:                perror("read");
                    444:                goto err;
                    445:        }
                    446:        if (l == 0) {
                    447:                fprintf(stderr, "\"%s\": No match\n", name);
                    448:                goto err;
                    449:        }
                    450:        if (l == BUFSIZ) {
                    451:                fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
                    452:                goto err;
                    453:        }
                    454:        xname[l] = 0;
                    455:        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                    456:                ;
                    457:        *++cp = '\0';
                    458:        if (any(' ', xname) && stat(xname, &sbuf) < 0) {
                    459:                fprintf(stderr, "\"%s\": Ambiguous\n", name);
                    460:                goto err;
                    461:        }
                    462:        return(savestr(xname));
                    463: 
                    464: err:
                    465:        return(NOSTR);
                    466: }
                    467: 
                    468: /*
                    469:  * Determine the current folder directory name.
                    470:  */
                    471: getfold(name)
                    472:        char *name;
                    473: {
                    474:        char *folder;
                    475: 
                    476:        if ((folder = value("folder")) == NOSTR)
                    477:                return (-1);
                    478:        if (*folder == '/')
                    479:                strcpy(name, folder);
                    480:        else
                    481:                sprintf(name, "%s/%s", homedir, folder);
                    482:        return (0);
                    483: }
                    484: 
                    485: /*
                    486:  * A nicer version of Fdopen, which allows us to fclose
                    487:  * without losing the open file.
                    488:  */
                    489: FILE *
                    490: Fdopen(fildes, mode)
                    491:        char *mode;
                    492: {
                    493:        int f;
                    494: 
                    495:        if ((f = dup(fildes)) < 0) {
                    496:                perror("dup");
                    497:                return (NULL);
                    498:        }
                    499:        return fdopen(f, mode);
                    500: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.