Annotation of 3BSD/cmd/ucbmail/fio.c, revision 1.1.1.1

1.1       root        1: #
                      2: 
                      3: #include "rcv.h"
                      4: #include <sys/stat.h>
                      5: #include <errno.h>
                      6: 
                      7: /*
                      8:  * Mail -- a mail program
                      9:  *
                     10:  * File I/O.
                     11:  */
                     12: 
                     13: /*
                     14:  * Set up the input pointers while copying the mail file into
                     15:  * /tmp.
                     16:  */
                     17: 
                     18: setptr(ibuf)
                     19:        FILE *ibuf;
                     20: {
                     21:        register int count, s, l;
                     22:        off_t offset;
                     23:        char linebuf[LINESIZE];
                     24:        int maybe, mestmp;
                     25:        struct message this;
                     26:        extern char tempSet[];
                     27: 
                     28:        if ((mestmp = opentemp(tempSet)) < 0)
                     29:                exit(1);
                     30:        msgCount = 0;
                     31:        offset = 0;
                     32:        s = 0;
                     33:        l = 0;
                     34:        maybe = 1;
                     35:        for (;;) {
                     36:                if ((count = readline(ibuf, linebuf)) == 0) {
                     37:                        this.m_offset = offsetof(offset);
                     38:                        this.m_block = blockof(offset);
                     39:                        this.m_size = s;
                     40:                        this.m_lines = l;
                     41:                        if (append(&this, mestmp)) {
                     42:                                perror(tempSet);
                     43:                                exit(1);
                     44:                        }
                     45:                        fclose(ibuf);
                     46:                        makemessage(mestmp);
                     47:                        close(mestmp);
                     48:                        return;
                     49:                }
                     50:                if (putline(otf, linebuf) < 0) {
                     51:                        perror("/tmp");
                     52:                        exit(1);
                     53:                }
                     54:                if (maybe && ishead(linebuf)) {
                     55:                        msgCount++;
                     56:                        this.m_flag = MUSED;
                     57:                        this.m_block = blockof(offset);
                     58:                        this.m_offset = offsetof(offset);
                     59:                        this.m_size = s;
                     60:                        this.m_lines = l;
                     61:                        s = 0;
                     62:                        l = 0;
                     63:                        if (append(&this, mestmp)) {
                     64:                                perror(tempSet);
                     65:                                exit(1);
                     66:                        }
                     67:                }
                     68:                offset += count;
                     69:                s += count;
                     70:                l++;
                     71:                maybe = 0;
                     72:                if (linebuf[0] == 0)
                     73:                        maybe = 1;
                     74:        }
                     75: }
                     76: 
                     77: /*
                     78:  * Drop the passed line onto the passed output buffer.
                     79:  * If a write error occurs, return -1, else the count of
                     80:  * characters written, including the newline.
                     81:  */
                     82: 
                     83: putline(obuf, linebuf)
                     84:        FILE *obuf;
                     85:        char *linebuf;
                     86: {
                     87:        register int c;
                     88: 
                     89:        c = strlen(linebuf);
                     90:        fputs(linebuf, obuf);
                     91:        putc('\n', obuf);
                     92:        if (ferror(obuf))
                     93:                return(-1);
                     94:        return(c+1);
                     95: }
                     96: 
                     97: /*
                     98:  * Read up a line from the specified input into the line
                     99:  * buffer.  Return the number of characters read.  Do not
                    100:  * include the newline at the end.
                    101:  */
                    102: 
                    103: readline(ibuf, linebuf)
                    104:        FILE *ibuf;
                    105:        char *linebuf;
                    106: {
                    107:        register char *cp;
                    108:        register c;
                    109: 
                    110: again:
                    111:        do {
                    112:                clearerr(ibuf);
                    113:                for (cp=linebuf, c=getc(ibuf); c!='\n' && c!= EOF; c=getc(ibuf))
                    114:                        if (cp - linebuf < LINESIZE-1)
                    115:                                        *cp++ = c;
                    116:        } while (ferror(ibuf) && ibuf == stdin);
                    117:        *cp = 0;
                    118:        if (c == EOF && cp == linebuf)
                    119:                return(0);
                    120:        return(cp - linebuf + 1);
                    121: }
                    122: 
                    123: /*
                    124:  * Return a file buffer all ready to read up the
                    125:  * passed message pointer.
                    126:  */
                    127: 
                    128: FILE *
                    129: setinput(mp)
                    130:        register struct message *mp;
                    131: {
                    132:        off_t off;
                    133: 
                    134:        fflush(otf);
                    135:        off = mp->m_block;
                    136:        off <<= 9;
                    137:        off += mp->m_offset;
                    138:        if (fseek(itf, off, 0) < 0) {
                    139:                perror("fseek");
                    140:                panic("temporary file seek");
                    141:        }
                    142:        return(itf);
                    143: }
                    144: 
                    145: /*
                    146:  * Take the data out of the passed ghost file and toss it into
                    147:  * a dynamically allocated message structure.
                    148:  */
                    149: 
                    150: makemessage(f)
                    151: {
                    152:        register struct message *m;
                    153:        register char *mp;
                    154:        register count;
                    155: 
                    156:        mp = calloc((unsigned) (msgCount + 1), sizeof *m);
                    157:        if (mp == NOSTR) {
                    158:                printf("Insufficient memory for %d messages\n", msgCount);
                    159:                exit(1);
                    160:        }
                    161:        message = (struct message *) mp;
                    162:        dot = message;
                    163:        lseek(f, 0L, 0);
                    164:        while (count = read(f, mp, BUFSIZ))
                    165:                mp += count;
                    166:        for (m = &message[0]; m < &message[msgCount]; m++) {
                    167:                m->m_size = (m+1)->m_size;
                    168:                m->m_lines = (m+1)->m_lines;
                    169:        }
                    170:        message[msgCount].m_size = 0;
                    171:        message[msgCount].m_lines = 0;
                    172: }
                    173: 
                    174: /*
                    175:  * Append the passed message descriptor onto the temp file.
                    176:  * If the write fails, return 1, else 0
                    177:  */
                    178: 
                    179: append(mp, f)
                    180:        struct message *mp;
                    181: {
                    182:        if (write(f, (char *) mp, sizeof *mp) != sizeof *mp)
                    183:                return(1);
                    184:        return(0);
                    185: }
                    186: 
                    187: /*
                    188:  * Delete a file, but only if the file is a plain file.
                    189:  */
                    190: 
                    191: remove(name)
                    192:        char name[];
                    193: {
                    194:        struct stat statb;
                    195:        extern int errno;
                    196: 
                    197:        if (stat(name, &statb) < 0)
                    198:                return(-1);
                    199:        if ((statb.st_mode & S_IFMT) != S_IFREG) {
                    200:                errno = EISDIR;
                    201:                return(-1);
                    202:        }
                    203:        return(unlink(name));
                    204: }
                    205: 
                    206: /*
                    207:  * Terminate an editing session by attempting to write out the user's
                    208:  * file from the temporary.
                    209:  */
                    210: 
                    211: edstop()
                    212: {
                    213:        register int gotcha;
                    214:        register struct message *mp;
                    215:        FILE *obuf;
                    216: 
                    217:        for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++)
                    218:                if (mp->m_flag & (MODIFY|MDELETED)) {
                    219:                        gotcha++;
                    220:                        break;
                    221:                }
                    222:        if (!gotcha)
                    223:                return;
                    224:        printf("\"%s\" ", editfile);
                    225:        flush();
                    226:        if ((obuf = fopen(editfile, "w")) == NULL) {
                    227:                perror(editfile);
                    228:                reset(0);
                    229:        }
                    230:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    231:                if ((mp->m_flag & MDELETED) != 0)
                    232:                        continue;
                    233:                if (send(mp, obuf) < 0) {
                    234:                        perror(editfile);
                    235:                        reset(0);
                    236:                }
                    237:        }
                    238:        fflush(obuf);
                    239:        if (ferror(obuf)) {
                    240:                perror(editfile);
                    241:                reset(0);
                    242:        }
                    243:        printf("complete\n");
                    244:        flush();
                    245: }
                    246: 
                    247: /*
                    248:  * Empty the output buffer.
                    249:  */
                    250: 
                    251: clrbuf(buf)
                    252:        register FILE *buf;
                    253: {
                    254: 
                    255:        buf = stdout;
                    256:        buf->_ptr = buf->_base;
                    257:        buf->_cnt = BUFSIZ;
                    258: }
                    259: 
                    260: /*
                    261:  * Open a temp file by creating, closing, unlinking, and
                    262:  * reopening.  Return the open file descriptor.
                    263:  */
                    264: 
                    265: opentemp(file)
                    266:        char file[];
                    267: {
                    268:        register int f;
                    269: 
                    270:        if ((f = creat(file, 0600)) < 0) {
                    271:                perror(file);
                    272:                return(-1);
                    273:        }
                    274:        close(f);
                    275:        if ((f = open(file, 2)) < 0) {
                    276:                perror(file);
                    277:                remove(file);
                    278:                return(-1);
                    279:        }
                    280:        remove(file);
                    281:        return(f);
                    282: }
                    283: 
                    284: /*
                    285:  * Flush the standard output.
                    286:  */
                    287: 
                    288: flush()
                    289: {
                    290:        fflush(stdout);
                    291:        fflush(stderr);
                    292: }
                    293: 
                    294: /*
                    295:  * Determine the size of the file possessed by
                    296:  * the passed buffer.
                    297:  */
                    298: 
                    299: off_t
                    300: fsize(iob)
                    301:        FILE *iob;
                    302: {
                    303:        register int f;
                    304:        struct stat sbuf;
                    305: 
                    306:        f = fileno(iob);
                    307:        if (fstat(f, &sbuf) < 0)
                    308:                return(0);
                    309:        return(sbuf.st_size);
                    310: }
                    311: 
                    312: /*
                    313:  * Take a file name, possibly with shell meta characters
                    314:  * in it and expand it by using "sh -c echo filename"
                    315:  * Return the file name as a dynamic string.
                    316:  */
                    317: 
                    318: char *
                    319: expand(name)
                    320:        char name[];
                    321: {
                    322:        char xname[BUFSIZ];
                    323:        char cmdbuf[BUFSIZ];
                    324:        register int pid, l, rc;
                    325:        register char *cp, *Shell;
                    326:        int s, pivec[2], (*sigint)();
                    327:        struct stat sbuf;
                    328: 
                    329:        if (!anyof(name, "~{[*?$`'\"\\"))
                    330:                return(name);
                    331:        /* sigint = signal(SIGINT, SIG_IGN); */
                    332:        if (pipe(pivec) < 0) {
                    333:                perror("pipe");
                    334:                /* signal(SIGINT, sigint) */
                    335:                return(name);
                    336:        }
                    337:        sprintf(cmdbuf, "echo %s", name);
                    338:        if ((pid = vfork()) == 0) {
                    339:                Shell = value("SHELL");
                    340:                if (Shell == NOSTR)
                    341:                        Shell = SHELL;
                    342:                close(pivec[0]);
                    343:                close(1);
                    344:                dup(pivec[1]);
                    345:                close(pivec[1]);
                    346:                close(2);
                    347:                execl(Shell, Shell, "-c", cmdbuf, 0);
                    348:                _exit(1);
                    349:        }
                    350:        if (pid == -1) {
                    351:                perror("fork");
                    352:                close(pivec[0]);
                    353:                close(pivec[1]);
                    354:                return(NOSTR);
                    355:        }
                    356:        close(pivec[1]);
                    357:        l = read(pivec[0], xname, BUFSIZ);
                    358:        close(pivec[0]);
                    359:        while (wait(&s) != pid);
                    360:                ;
                    361:        s &= 0377;
                    362:        if (s != 0 && s != SIGPIPE) {
                    363:                fprintf(stderr, "\"Echo\" failed\n");
                    364:                goto err;
                    365:        }
                    366:        if (l < 0) {
                    367:                perror("read");
                    368:                goto err;
                    369:        }
                    370:        if (l == 0) {
                    371:                fprintf(stderr, "\"%s\": No match\n", name);
                    372:                goto err;
                    373:        }
                    374:        if (l == BUFSIZ) {
                    375:                fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
                    376:                goto err;
                    377:        }
                    378:        xname[l] = 0;
                    379:        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                    380:                ;
                    381:        *++cp = '\0';
                    382:        if (any(' ', xname) && stat(xname, &sbuf) < 0) {
                    383:                fprintf(stderr, "\"%s\": Ambiguous\n", name);
                    384:                goto err;
                    385:        }
                    386:        /* signal(SIGINT, sigint) */
                    387:        return(savestr(xname));
                    388: 
                    389: err:
                    390:        /* signal(SIGINT, sigint); */
                    391:        return(NOSTR);
                    392: }
                    393: 
                    394: /*
                    395:  * A nicer version of Fdopen, which allows us to fclose
                    396:  * without losing the open file.
                    397:  */
                    398: 
                    399: FILE *
                    400: Fdopen(fildes, mode)
                    401:        char *mode;
                    402: {
                    403:        register int f;
                    404:        FILE *fdopen();
                    405: 
                    406:        f = dup(fildes);
                    407:        if (f < 0) {
                    408:                perror("dup");
                    409:                return(NULL);
                    410:        }
                    411:        return(fdopen(f, mode));
                    412: }

unix.superglobalmegacorp.com

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