Annotation of 43BSDTahoe/ucb/Mail/fio.c, revision 1.1

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

unix.superglobalmegacorp.com

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