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

1.1       root        1: #ident "@(#)fio.c      1.3 'attmail mail(1) command'"
                      2: #ident "@(#)mailx:fio.c        1.13.1.2"
                      3: /*     Copyright (c) 1984 AT&T */
                      4: /*       All Rights Reserved   */
                      5: 
                      6: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
                      7: /*     The copyright notice above does not evidence any        */
                      8: /*     actual or intended publication of such source code.     */
                      9: 
                     10: #ident "@(#)mailx:fio.c        1.13.1.1"
                     11: 
                     12: #include "rcv.h"
                     13: 
                     14: /*
                     15:  * mailx -- a modified version of a University of California at Berkeley
                     16:  *     mail program
                     17:  *
                     18:  * File I/O.
                     19:  */
                     20: 
                     21: static int getln();
                     22: 
                     23: /*
                     24:  * Set up the input pointers while copying the mail file into
                     25:  * /tmp.
                     26:  */
                     27: 
                     28: void
                     29: setptr(ibuf)
                     30:        FILE *ibuf;
                     31: {
                     32:        int n, newline = 1;
                     33:        int ToldUser = FALSE;
                     34:        int ctf = FALSE;                /* header continuation flag */
                     35:        long clen = 0;
                     36:        long explicit_clen = 0;
                     37:        int hdr = 0;
                     38:        register char *cp;
                     39:        register int l;
                     40:        register long s;
                     41:        off_t offset;
                     42:        char linebuf[LINESIZE];
                     43:        int inhead, newmail, Odot;
                     44:        short flag;
                     45: 
                     46:        if ( !space ) {
                     47:                msgCount = 0;
                     48:                offset = 0;
                     49:                space = 32;
                     50:                newmail = 0;
                     51:                message = (struct message *)calloc(space, sizeof(struct message));
                     52:                if ( message == NULL ) {
                     53:                        fprintf(stderr,"calloc: insufficient memory for %d messages\n",space);
                     54:                        exit(1);
                     55:                        /* NOTREACHED */
                     56:                }
                     57:                dot = message;
                     58:        } else {
                     59:                newmail = 1;
                     60:                offset = fsize(otf);
                     61:        }
                     62:        s = 0L;
                     63:        l = 0;
                     64:        flag = MUSED|MNEW;
                     65: 
                     66:        while ((n = getln(linebuf, sizeof linebuf, ibuf)) > 0) {
                     67:                if (!newline) {
                     68:                        goto putout;
                     69:                } else if ((hdr = isheader (linebuf, &ctf)) == FALSE) {
                     70:                        ctf = FALSE;    /* next line can't be cont. */
                     71:                }
                     72: 
                     73:                /*
                     74:                        bug msgCount should be checked
                     75:                        also, ignore anything that looks like a header line
                     76:                        after the header is finished!!!   -- adb
                     77:                */
                     78:                switch (hdr) {
                     79:                case H_FROM:
                     80: 
                     81:                        if ( (msgCount > 0) && (!newmail) ){
                     82:                                message[msgCount-1].m_size = s;
                     83:                                message[msgCount-1].m_clen = 
                     84:                                        (explicit_clen <= 0  || clen < explicit_clen) ?
                     85:                                        clen : explicit_clen;
                     86: /*                             if ( message[msgCount-1].m_text == TRUE ) { */
                     87:                                        message[msgCount-1].m_lines = l;
                     88: /*                             } else { */
                     89: /*                                     message[msgCount-1].m_lines = -99; */
                     90:                        /*      } */
                     91:                                message[msgCount-1].m_flag = flag;
                     92:                                flag = MUSED|MNEW;
                     93:                        }
                     94:                        if ( msgCount >= space ) {
                     95: 
                     96:                /* Limit the speed at which the allocated space grows */
                     97: 
                     98:                                if ( space < 512 )
                     99:                                        space = space*2;
                    100:                                else
                    101:                                        space += 512;
                    102:                                errno = 0;
                    103:                                Odot = dot - &(message[0]);
                    104:                                message = (struct message *)realloc(message,space*(sizeof( struct message)));
                    105:                                if ( message == NULL ) {
                    106:                                        perror("realloc failed");
                    107:                                        fprintf(stderr,"realloc: insufficient memory for %d messages\n",space);
                    108:                                        exit(1);
                    109:                                }
                    110:                                dot = &message[Odot];
                    111:                        }
                    112:                        message[msgCount].m_block = blockof(offset);
                    113:                        message[msgCount].m_offset = offsetofaddr(offset);
                    114:                        message[msgCount].m_text = TRUE;
                    115:                        newmail = 0;
                    116:                        msgCount++;
                    117:                        flag = MUSED|MNEW;
                    118:                        inhead = 1;
                    119:                        s = 0L;
                    120:                        explicit_clen = clen = 0L;
                    121:                        l = 0;
                    122:                        ToldUser = FALSE;
                    123:                        break;
                    124:                case H_CLEN:
                    125:                        if (!inhead) {
                    126:                                break;
                    127:                        }
                    128:                        explicit_clen = atol (strpbrk (linebuf, ":")+1);
                    129:                        break;
                    130: 
                    131:                case H_STATUS:
                    132:                        if (inhead && ishfield(linebuf, "status")) {
                    133:                                cp = hcontents(linebuf);
                    134:                                if (strchr(cp, 'R'))
                    135:                                        flag |= MREAD;
                    136:                                if (strchr(cp, 'O'))
                    137:                                        flag &= ~MNEW;
                    138:                        }
                    139:                        break;
                    140:                default:
                    141:                        break;
                    142:                }
                    143:                if( !inhead && hdr) hdr = 0;
                    144: putout:
                    145:                offset += n;
                    146:                s += (long)n;
                    147:                if( !hdr ) {
                    148:                        if( inhead ) {
                    149:                                inhead = 0;
                    150:                                if( n == 1 && linebuf[0] == '\n')
                    151:                                        clen = -1L;     /* cheat: avoid leading blank */
                    152:                        }
                    153:                        clen += (long)n;
                    154:                }
                    155:                if (msgCount && message[msgCount-1].m_text == TRUE) {
                    156:                        message[msgCount-1].m_text = istext(linebuf,(long)n);
                    157:                }
                    158:                if (fwrite(linebuf,1,n,otf) != n) {
                    159:                        fclose(ibuf);
                    160:                        fflush(otf);
                    161:                } else {
                    162:                        l++;
                    163:                }
                    164:                if (ferror(otf)) {
                    165:                        perror("/tmp");
                    166:                        exit(1);
                    167:                }
                    168:                if (msgCount == 0) {
                    169:                        fclose(ibuf);
                    170:                        fflush(otf);
                    171: 
                    172:                }
                    173:                newline = (linebuf[n-1] == '\n');
                    174: 
                    175:                /* distribution mailx had unreachable code here -- ignore */
                    176:        }
                    177: 
                    178:        /*
                    179:                last plus 1
                    180:        */
                    181: 
                    182:        if (n == 0) {
                    183:                fflush(otf);
                    184:                if ( msgCount ) {
                    185:                        message[msgCount-1].m_size = s;
                    186:                        message[msgCount-1].m_clen = clen;
                    187: /*                     if ( message[msgCount-1].m_text == TRUE ) {   */
                    188:                                message[msgCount-1].m_lines = l;
                    189: /*                     } else {   */
                    190: /*                             message[msgCount-1].m_lines = -99;  */
                    191: /*                     }       */
                    192:                        message[msgCount-1].m_flag = flag;
                    193:                }
                    194:                flag = MUSED|MNEW;
                    195:                fclose(ibuf);
                    196:                fflush(otf);
                    197:                return;
                    198:        }
                    199: }
                    200: 
                    201: /*  HMF:  Code from fio.c. (getln)                                         */
                    202: 
                    203: static int
                    204: getln(line, max, f)
                    205:        char *line;
                    206:        int max;
                    207:        FILE    *f;
                    208: {
                    209:        int     i,ch;
                    210:        for (i=0; i < max-1 && (ch=getc(f)) != EOF;)
                    211:                if ((line[i++] = (char)ch) == '\n') break;
                    212:        line[i] = '\0';
                    213:        return(i);
                    214: }
                    215: 
                    216: /*
                    217:  * Drop the passed line onto the passed output buffer.
                    218:  * If a write error occurs, return -1, else the count of
                    219:  * characters written, including the newline.
                    220:  */
                    221: 
                    222: putline(obuf, linebuf)
                    223:        FILE *obuf;
                    224:        char *linebuf;
                    225: {
                    226:        register int c;
                    227: 
                    228:        c = strlen(linebuf);
                    229:        fputs(linebuf, obuf);
                    230:        putc('\n', obuf);
                    231:        if (ferror(obuf))
                    232:                return(-1);
                    233:        return(c+1);
                    234: }
                    235: 
                    236: /*
                    237:  * Read up a line from the specified input into the line
                    238:  * buffer.  Return the number of characters read.  Do not
                    239:  * include the newline at the end.
                    240:  */
                    241: 
                    242: readline(ibuf, linebuf)
                    243:        FILE *ibuf;
                    244:        char *linebuf;
                    245: {
                    246:        register char *cp;
                    247:        register int c;
                    248: 
                    249:        do {
                    250:                clearerr(ibuf);
                    251:                c = getc(ibuf);
                    252:                for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
                    253: /*
                    254:                        if (c == 0) {
                    255:                                fprintf(stderr, "mailx: NUL changed to @\n");
                    256:                                c = '@';
                    257:                        }
                    258: */
                    259:                        if (cp - linebuf < LINESIZE-2)
                    260:                                *cp++ = (char)c;
                    261:                }
                    262:        } while (ferror(ibuf) && ibuf == stdin);
                    263:        *cp = 0;
                    264:        if (c == EOF && cp == linebuf)
                    265:                return(0);
                    266:        return(cp - linebuf + 1);
                    267: }
                    268: 
                    269: /*
                    270:  * Return a file buffer all ready to read up the
                    271:  * passed message pointer.
                    272:  */
                    273: 
                    274: FILE *
                    275: setinput(mp)
                    276:        register struct message *mp;
                    277: {
                    278:        off_t off;
                    279: 
                    280:        fflush(otf);
                    281:        off = mp->m_block;
                    282:        off <<= 9;
                    283:        off += mp->m_offset;
                    284:        if (fseek(itf, off, 0) < 0) {
                    285:                perror("fseek");
                    286:                panic("temporary file seek");
                    287:        }
                    288:        return(itf);
                    289: }
                    290: 
                    291: 
                    292: /*
                    293:  * Delete a file, but only if the file is a plain file.
                    294:  */
                    295: 
                    296: removefile(name)
                    297:        char name[];
                    298: {
                    299:        struct stat statb;
                    300: 
                    301:        if (stat(name, &statb) < 0)
                    302:                return(-1);
                    303:        if ((statb.st_mode & S_IFMT) != S_IFREG) {
                    304:                errno = EISDIR;
                    305:                return(-1);
                    306:        }
                    307:        return(unlink(name));
                    308: }
                    309: 
                    310: /*
                    311:  * Terminate an editing session by attempting to write out the user's
                    312:  * file from the temporary.  Save any new stuff appended to the file.
                    313:  */
                    314: int
                    315: edstop()
                    316: {
                    317:        register int gotcha, c;
                    318:        register struct message *mp;
                    319:        FILE *obuf, *ibuf, *tbuf = 0, *readstat;
                    320:        FILE *lockopen();                                       /* adb */
                    321:        struct stat statb;
                    322:        char tempname[30], *id;
                    323: 
                    324:        if (readonly)
                    325:                return(0);
                    326:        holdsigs();
                    327:        if (Tflag != NOSTR) {
                    328:                if ((readstat = fopen(Tflag, "w")) == NULL)
                    329:                        Tflag = NOSTR;
                    330:        }
                    331:        for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
                    332:                if (mp->m_flag & MNEW) {
                    333:                        mp->m_flag &= ~MNEW;
                    334:                        mp->m_flag |= MSTATUS;
                    335:                }
                    336:                if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
                    337:                        gotcha++;
                    338:                if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
                    339:                        if ((id = hfield("article-id", mp, addone)) != NOSTR)
                    340:                                fprintf(readstat, "%s\n", id);
                    341:                }
                    342:        }
                    343:        if (Tflag != NOSTR)
                    344:                fclose(readstat);
                    345:        if (!gotcha || Tflag != NOSTR)
                    346:                goto done;
                    347:        if ((ibuf = lockopen(editfile, "r+w", 0666, -1, -1)) == NULL) {         /* adb */
                    348:                perror(editfile);
                    349:                relsesigs();
                    350:                longjmp(srbuf, 1);
                    351:        }
                    352: /*     lock(ibuf, "r+", 1);                                                       adb */
                    353:        if (fstat(fileno(ibuf), &statb) >= 0 && statb.st_size > mailsize) {
                    354:                strcpy(tempname, "/tmp/mboxXXXXXX");
                    355:                mktemp(tempname);
                    356:                if ((obuf = fopen(tempname, "w")) == NULL) {
                    357:                        perror(tempname);
                    358:                        lockclose(ibuf);                                /* adb */
                    359:                        relsesigs();
                    360:                        longjmp(srbuf, 1);
                    361:                }
                    362:                fseek(ibuf, mailsize, 0);
                    363:                while ((c = getc(ibuf)) != EOF)
                    364:                        putc(c, obuf);
                    365:                fclose(obuf);
                    366:                if ((tbuf = fopen(tempname, "r")) == NULL) {
                    367:                        perror(tempname);
                    368:                        lockclose(ibuf);                                /* adb */
                    369:                        removefile(tempname);
                    370:                        relsesigs();
                    371:                        longjmp(srbuf, 1);
                    372:                }
                    373:                removefile(tempname);
                    374:        }
                    375:        printf("\"%s\" ", editfile);
                    376:        flush();
                    377:        if ((obuf = fopen(editfile, "w")) == NULL) {
                    378:                perror(editfile);
                    379:                lockclose(ibuf);                                        /* adb */
                    380:                if (tbuf)
                    381:                        fclose(tbuf);
                    382:                relsesigs();
                    383:                longjmp(srbuf, 1);
                    384:        }
                    385:        c = 0;
                    386:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    387:                if ((mp->m_flag & MDELETED) != 0)
                    388:                        continue;
                    389:                c++;
                    390:                if (send(mp, obuf, 0) < 0) {
                    391:                        perror(editfile);
                    392:                        lockclose(ibuf);                                /* adb */
                    393:                        fclose(obuf);
                    394:                        if (tbuf)
                    395:                                fclose(tbuf);
                    396:                        relsesigs();
                    397:                        longjmp(srbuf, 1);
                    398:                }
                    399:        }
                    400:        gotcha = (c == 0 && ibuf == NULL);
                    401:        if (tbuf != NULL) {
                    402:                while ((c = getc(tbuf)) != EOF)
                    403:                        putc(c, obuf);
                    404:                fclose(tbuf);
                    405:        }
                    406:        fflush(obuf);
                    407:        if (ferror(obuf)) {
                    408:                perror(editfile);
                    409:                lockclose(ibuf);                                        /* adb */
                    410:                fclose(obuf);
                    411:                relsesigs();
                    412:                longjmp(srbuf, 1);
                    413:        }
                    414:        if (gotcha) {
                    415:                removefile(editfile);
                    416:                printf("removed\n");
                    417:        }
                    418:        else
                    419:                printf("complete\n");
                    420:        lockclose(ibuf);                                                /* adb */
                    421:        fclose(obuf);
                    422:        flush();
                    423: 
                    424: done:
                    425:        relsesigs();
                    426:        return(1);
                    427: }
                    428: 
                    429: /*
                    430:  * Hold signals SIGHUP - SIGQUIT.
                    431:  */
                    432: void
                    433: holdsigs()
                    434: {
                    435:        sighold(SIGHUP);
                    436:        sighold(SIGINT);
                    437:        sighold(SIGQUIT);
                    438: }
                    439: 
                    440: /*
                    441:  * Release signals SIGHUP - SIGQUIT
                    442:  */
                    443: void
                    444: relsesigs()
                    445: {
                    446:        sigrelse(SIGHUP);
                    447:        sigrelse(SIGINT);
                    448:        sigrelse(SIGQUIT);
                    449: }
                    450: 
                    451: /*
                    452:  * Empty the output buffer.
                    453:  * (now a no-op; why was it here?)
                    454:  */
                    455: void
                    456: clrbuf(buf)
                    457:        register FILE *buf;
                    458: {
                    459: /***
                    460:        buf = stdout;
                    461:        buf->_ptr = buf->_base;
                    462:        buf->_cnt = BUFSIZ;
                    463: ***/   (void) buf;
                    464: }
                    465: 
                    466: 
                    467: /*
                    468:  * Flush the standard output.
                    469:  */
                    470: 
                    471: void
                    472: flush()
                    473: {
                    474:        fflush(stdout);
                    475:        fflush(stderr);
                    476: }
                    477: 
                    478: /*
                    479:  * Determine the size of the file possessed by
                    480:  * the passed buffer.
                    481:  */
                    482: 
                    483: off_t
                    484: fsize(iob)
                    485:        FILE *iob;
                    486: {
                    487:        register int f;
                    488:        struct stat sbuf;
                    489: 
                    490:        f = fileno(iob);
                    491:        if (fstat(f, &sbuf) < 0)
                    492:                return(0);
                    493:        return(sbuf.st_size);
                    494: }
                    495: 
                    496: /*
                    497:  * Take a file name, possibly with shell meta characters
                    498:  * in it and expand it by using "sh -c echo filename"
                    499:  * Return the file name as a dynamic string.
                    500:  */
                    501: 
                    502: char *
                    503: expand(name)
                    504:        char name[];
                    505: {
                    506:        char xname[BUFSIZ];
                    507:        char cmdbuf[BUFSIZ];
                    508:        register pid_t pid;
                    509:        register int l;
                    510:        register char *cp;
                    511:        int s, pivec[2];
                    512:        struct stat sbuf;
                    513:        char *Shell;
                    514: 
                    515:        if (debug) fprintf(stderr, "expand(%s)=", name);
                    516:        if (name[0] == '+') {
                    517:                cp = expand(++name);
                    518:                if (*cp != '/' && getfold(cmdbuf) >= 0) {
                    519:                        sprintf(xname, "%s/%s", cmdbuf, cp);
                    520:                        cp = savestr(xname);
                    521:                }
                    522:                if (debug) fprintf(stderr, "%s\n", cp);
                    523:                return cp;
                    524:        }
                    525:        if (!anyof(name, "~{[*?$`'\"\\")) {
                    526:                if (debug) fprintf(stderr, "%s\n", name);
                    527:                return(name);
                    528:        }
                    529:        if (pipe(pivec) < 0) {
                    530:                perror("pipe");
                    531:                return(name);
                    532:        }
                    533:        sprintf(cmdbuf, "echo %s", name);
                    534:        if ((pid = fork()) == 0) {
                    535:                sigchild();
                    536:                close(pivec[0]);
                    537:                close(1);
                    538:                dup(pivec[1]);
                    539:                close(pivec[1]);
                    540:                close(2);
                    541:                if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
                    542:                        Shell = SHELL;
                    543:                execlp(Shell, Shell, "-c", cmdbuf, (char *)0);
                    544:                _exit(1);
                    545:        }
                    546:        if (pid == (pid_t)-1) {
                    547:                perror("fork");
                    548:                close(pivec[0]);
                    549:                close(pivec[1]);
                    550:                return(NOSTR);
                    551:        }
                    552:        close(pivec[1]);
                    553:        l = read(pivec[0], xname, BUFSIZ);
                    554:        close(pivec[0]);
                    555:        while (wait(&s) != pid);
                    556:                ;
                    557:        s &= 0377;
                    558:        if (s != 0 && s != SIGPIPE) {
                    559:                fprintf(stderr, "\"Echo\" failed\n");
                    560:                goto err;
                    561:        }
                    562:        if (l < 0) {
                    563:                perror("read");
                    564:                goto err;
                    565:        }
                    566:        if (l == 0) {
                    567:                fprintf(stderr, "\"%s\": No match\n", name);
                    568:                goto err;
                    569:        }
                    570:        if (l == BUFSIZ) {
                    571:                fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
                    572:                goto err;
                    573:        }
                    574:        xname[l] = 0;
                    575:        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                    576:                ;
                    577:        *++cp = '\0';
                    578:        if (any(' ', xname) && stat(xname, &sbuf) < 0) {
                    579:                fprintf(stderr, "\"%s\": Ambiguous\n", name);
                    580:                goto err;
                    581:        }
                    582:        if (debug) fprintf(stderr, "%s\n", xname);
                    583:        return(savestr(xname));
                    584: 
                    585: err:
                    586:        printf("\n");
                    587:        return(NOSTR);
                    588: }
                    589: 
                    590: /*
                    591:  * Determine the current folder directory name.
                    592:  */
                    593: getfold(name)
                    594:        char *name;
                    595: {
                    596:        char *folder;
                    597: 
                    598:        if ((folder = value("folder")) == NOSTR) {
                    599:                strcpy(name, homedir);
                    600:                return(0);
                    601:        }
                    602:        if ((folder = expand(folder)) == NOSTR)
                    603:                return(-1);
                    604:        if (*folder == '/')
                    605:                strcpy(name, folder);
                    606:        else
                    607:                sprintf(name, "%s/%s", homedir, folder);
                    608:        return(0);
                    609: }
                    610: 
                    611: /*
                    612:  * A nicer version of Fdopen, which allows us to fclose
                    613:  * without losing the open file.
                    614:  */
                    615: 
                    616: FILE *
                    617: Fdopen(fildes, mode)
                    618:        char *mode;
                    619: {
                    620:        register int f;
                    621: 
                    622:        f = dup(fildes);
                    623:        if (f < 0) {
                    624:                perror("dup");
                    625:                return(NULL);
                    626:        }
                    627:        return(fdopen(f, mode));
                    628: }
                    629: 
                    630: /*
                    631:  * return the filename associated with "s".  This function always
                    632:  * returns a non-null string (no error checking is done on the receiving end)
                    633:  */
                    634: char *
                    635: Getf(s)
                    636: register char *s;
                    637: {
                    638:        register char *cp;
                    639:        static char defbuf[PATHSIZE];
                    640: 
                    641:        if (((cp = value(s)) != 0) && *cp) {
                    642:                return expand(cp);
                    643:        } else if (strcmp(s, "MBOX")==0) {
                    644:                strcpy(defbuf, Getf("HOME"));
                    645:                strcat(defbuf, "/");
                    646:                strcat(defbuf, "mbox");
                    647:                return(defbuf);
                    648:        } else if (strcmp(s, "DEAD")==0) {
                    649:                strcpy(defbuf, Getf("HOME"));
                    650:                strcat(defbuf, "/");
                    651:                strcat(defbuf, "dead.letter");
                    652:                return(defbuf);
                    653:        } else if (strcmp(s, "MAILRC")==0) {
                    654:                strcpy(defbuf, Getf("HOME"));
                    655:                strcat(defbuf, "/");
                    656:                strcat(defbuf, ".mailrc");
                    657:                return(defbuf);
                    658:        } else if (strcmp(s, "HOME")==0) {
                    659:                /* no recursion allowed! */
                    660:                return(".");
                    661:        }
                    662:        return("DEAD"); /* "cannot happen" */
                    663: }

unix.superglobalmegacorp.com

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