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

unix.superglobalmegacorp.com

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