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

unix.superglobalmegacorp.com

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