Annotation of researchv10no/lbin/Mail/fio.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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