Annotation of 43BSD/contrib/news/src/inews.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This software is Copyright (c) 1986 by Rick Adams.
        !             3:  *
        !             4:  * Permission is hereby granted to copy, reproduce, redistribute or
        !             5:  * otherwise use this software as long as: there is no monetary
        !             6:  * profit gained specifically from the use or reproduction or this
        !             7:  * software, it is not sold, rented, traded or otherwise marketed, and
        !             8:  * this copyright notice is included prominently in any copy
        !             9:  * made.
        !            10:  *
        !            11:  * The author make no claims as to the fitness or correctness of
        !            12:  * this software for any use whatsoever, and it is provided as is. 
        !            13:  * Any use of this software is at the user's own risk.
        !            14:  *
        !            15:  * inews - insert, receive, and transmit news articles.
        !            16:  *
        !            17:  */
        !            18: 
        !            19: #ifdef SCCSID
        !            20: static char    *SccsId = "@(#)inews.c  2.61    3/19/86";
        !            21: #endif /* SCCSID */
        !            22: 
        !            23: #include "iparams.h"
        !            24: #include <errno.h>
        !            25: 
        !            26: /* local defines for inews */
        !            27: 
        !            28: #define OPTION 0       /* pick up an option string */
        !            29: #define STRING 1       /* pick up a string of arguments */
        !            30: 
        !            31: #define UNKNOWN 0001   /* possible modes for news program */
        !            32: #define UNPROC 0002    /* Unprocessed input */
        !            33: #define PROC   0004    /* Processed input */
        !            34: #define        CANCEL  0010    /* Cancel an article */
        !            35: #define        CREATENG 0020   /* Create a new newsgroup */
        !            36: 
        !            37: char   forgedname[NAMELEN];    /* A user specified -f option. */
        !            38: extern char histline[];
        !            39: /* Fake sys line in case they forget their own system */
        !            40: struct srec dummy_srec = { "MEMEME", "", "all", "", "" };
        !            41: 
        !            42: char *Progname = "inews";      /* used by xerror to identify failing program */
        !            43: 
        !            44: struct {                       /* options table. */
        !            45:        char    optlet;         /* option character. */
        !            46:        char    filchar;        /* if to pickup string, fill character. */
        !            47:        int     flag;           /* TRUE if have seen this opt. */
        !            48:        int     oldmode;        /* OR of legal input modes. */
        !            49:        int     newmode;        /* output mode. */
        !            50:        char    *buf;           /* string buffer */
        !            51: } *optpt, options[] = { /*
        !            52: optlet filchar         flag    oldmode newmode         buf     */
        !            53: 't',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.title,
        !            54: 'n',   NGDELIM,        FALSE,  UNPROC, UNKNOWN,        header.nbuf,
        !            55: 'd',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.distribution,
        !            56: 'e',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.expdate,
        !            57: 'p',   '\0',           FALSE,  UNKNOWN,PROC,           filename,
        !            58: 'f',   '\0',           FALSE,  UNPROC, UNKNOWN,        forgedname,
        !            59: 'F',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.followid,
        !            60: 'c',   '\0',           FALSE,  UNKNOWN,CANCEL,         filename,
        !            61: 'C',   '\0',           FALSE,  UNKNOWN,CREATENG,       header.nbuf,
        !            62: #define hflag  options[9].flag
        !            63: 'h',   '\0',           FALSE,  UNPROC, UNKNOWN,        filename,
        !            64: #define oflag  options[10].flag
        !            65: 'o',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.organization,
        !            66: #define Mflag  options[11].flag
        !            67: 'M',   '\0',           FALSE,  UNPROC, UNKNOWN,        filename,
        !            68: 'a',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.approved,
        !            69: '\0',  '\0',           0,      0,      0,              (char *)NULL
        !            70: };
        !            71: 
        !            72: FILE *mailhdr();
        !            73: char *genversion();
        !            74: extern int errno;
        !            75: 
        !            76: /*
        !            77:  *     Authors:
        !            78:  *             Matt Glickman   [email protected]
        !            79:  *             Mark Horton     [email protected]
        !            80:  *             Stephen Daniels [email protected]
        !            81:  *             Tom Truscott    [email protected]
        !            82:  *     IHCC version adapted by:
        !            83:  *             Larry Marek     [email protected]
        !            84:  */
        !            85: main(argc, argv)
        !            86: int    argc;
        !            87: register char **argv;
        !            88: {
        !            89:        int     state;          /* which type of argument to pick up    */
        !            90:        int     tlen, len;      /* temps for string processing routine  */
        !            91:        register char *ptr;     /* pointer to rest of buffer            */
        !            92:        int     filchar;        /* fill character (state = STRING)      */
        !            93:        char    *user = NULL, *home = NULL;     /* environment temps    */
        !            94:        struct passwd   *pw;    /* struct for pw lookup                 */
        !            95:        struct group    *gp;    /* struct for group lookup              */
        !            96:        register int    i;
        !            97:        FILE    *mfd;           /* mail file file-descriptor            */
        !            98:        char    cbuf[BUFLEN];   /* command buffer                       */
        !            99: 
        !           100:        /* uuxqt doesn't close all it's files */
        !           101:        for (i = 3; !close(i); i++)
        !           102:                ;
        !           103:        /* set up defaults and initialize. */
        !           104:        mode = UNKNOWN;
        !           105:        pathinit();
        !           106:        ptr = rindex(*argv, '/');
        !           107:        if (!ptr)
        !           108:                ptr = *argv - 1;
        !           109:        if (!strncmp(ptr+1, "rnews", 5)) {
        !           110:                mode = PROC;
        !           111: #ifdef NICENESS
        !           112:                nice(NICENESS);
        !           113: #endif /* NICENESS */
        !           114:        } else if (argc < 2)
        !           115:                goto usage;
        !           116: 
        !           117:        state = OPTION;
        !           118:        header.title[0] = header.nbuf[0] = filename[0] = '\0';
        !           119: 
        !           120:        /* check for existence of special files */
        !           121:        if (!rwaccess(ARTFILE)) {
        !           122:                mfd = mailhdr((struct hbuf *)NULL, exists(ARTFILE) ? "Unwritable files!" : "Missing files!");
        !           123:                if (mfd != NULL) {
        !           124: #ifdef HIDDENNET
        !           125:                        fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
        !           126: #else /* !HIDDENNET */
        !           127:                        fprintf(mfd,"System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ARTFILE);
        !           128: #endif /* !HIDDENNET */
        !           129:                        (void) sprintf(cbuf, "touch %s;chmod 666 %s", ARTFILE, ARTFILE);
        !           130:                        (void) system(cbuf);
        !           131:                        if (rwaccess(ARTFILE))
        !           132:                                fprintf(mfd, "The problem has been taken care of.\n");
        !           133:                        else
        !           134:                                fprintf(mfd, "Corrective action failed - check suid bits.\n");
        !           135:                        (void) mclose(mfd);
        !           136:                }
        !           137:        }
        !           138:        if (!rwaccess(ACTIVE)) {
        !           139:                mfd = mailhdr((struct hbuf *)NULL, exists(ACTIVE) ? "Unwritable files!" : "Missing files!");
        !           140:                if (mfd != NULL) {
        !           141: #ifdef HIDDENNET
        !           142:                        fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
        !           143: #else /* !HIDDENNET */
        !           144:                        fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ACTIVE);
        !           145: #endif /* !HIDDENNET */
        !           146:                        (void) sprintf(cbuf, "touch %s;chmod 666 %s", ACTIVE, ACTIVE);
        !           147:                        (void) system(cbuf);
        !           148:                        if (rwaccess(ACTIVE))
        !           149:                                fprintf(mfd, "The problem has been taken care of.\n");
        !           150:                        else
        !           151:                                fprintf(mfd, "Corrective action failed - check suid bits.\n");
        !           152:                        (void) mclose(mfd);
        !           153:                }
        !           154:        }
        !           155:        SigTrap = FALSE;        /* true if a signal has been caught */
        !           156:        if (mode != PROC) {
        !           157:                (void) signal(SIGHUP, onsig);
        !           158:                (void) signal(SIGINT, onsig);
        !           159:        }
        !           160:        savmask = umask(N_UMASK);       /* set up mask */
        !           161:        uid = getuid();
        !           162:        gid = getgid();
        !           163:        duid = geteuid();
        !           164:        dgid = getegid();
        !           165:        if (uid == 0 && duid == 0) {
        !           166:                /*
        !           167:                 * Must go through with this kludge since
        !           168:                 * some systems do not honor the setuid bit
        !           169:                 * when root invokes a setuid program.
        !           170:                 */
        !           171:                if ((pw = getpwnam(NEWSUSR)) == NULL)
        !           172:                        xerror("Cannot get NEWSU pw entry");
        !           173: 
        !           174:                duid = pw->pw_uid;
        !           175:                if ((gp = getgrnam(NEWSGRP)) == NULL)
        !           176:                        xerror("Cannot get NEWSG gr entry");
        !           177:                dgid = gp->gr_gid;
        !           178:                (void) setgid(dgid);
        !           179:                (void) setuid(duid);
        !           180:        }
        !           181: 
        !           182: #ifndef IHCC
        !           183:        /*
        !           184:         * We force the use of 'getuser()' to prevent forgery of articles
        !           185:         * by just changing $LOGNAME
        !           186:         */
        !           187:        if (isatty(fileno(stderr))) {
        !           188:                if ((user = getenv("USER")) == NULL)
        !           189:                        user = getenv("LOGNAME");
        !           190:                if ((home = getenv("HOME")) == NULL)
        !           191:                        home = getenv("LOGDIR");
        !           192:        }
        !           193: #endif
        !           194:        if (user == NULL || home == NULL)
        !           195:                getuser();
        !           196:        else {
        !           197:                if (username == NULL || username[0] == 0) {
        !           198:                        username = AllocCpy(user);
        !           199:                }
        !           200:                userhome = AllocCpy(home);
        !           201:        }
        !           202:        getuser();
        !           203: 
        !           204:        /* loop once per arg. */
        !           205: 
        !           206:        ++argv;         /* skip first arg, which is prog name. */
        !           207: 
        !           208:        while (--argc) {
        !           209:            if (state == OPTION) {
        !           210:                if (**argv != '-') {
        !           211:                        xerror("Bad option string \"%s\"", *argv);
        !           212:                }
        !           213:                while (*++*argv != '\0') {
        !           214:                        for (optpt = options; optpt->optlet != '\0'; ++optpt) {
        !           215:                                if (optpt->optlet == **argv)
        !           216:                                        goto found;
        !           217:                        }
        !           218:                        /* unknown option letter */
        !           219: usage:
        !           220:                        fprintf(stderr, "usage: inews -t title");
        !           221:                        fprintf(stderr, " [ -n newsgroups ]");
        !           222:                        fprintf(stderr, " [ -e expiration date ]\n");
        !           223:                        fprintf(stderr, "\t[ -f sender]\n\n");
        !           224:                        xxit(1);
        !           225: 
        !           226:                    found:;
        !           227:                        if (optpt->flag == TRUE || (mode != UNKNOWN &&
        !           228:                            (mode&optpt->oldmode) == 0)) {
        !           229:                                xerror("Bad %c option", **argv);
        !           230:                        }
        !           231:                        if (mode == UNKNOWN)
        !           232:                                mode = optpt->newmode;
        !           233:                        filchar = optpt->filchar;
        !           234:                        optpt->flag = TRUE;
        !           235:                        state = STRING;
        !           236:                        ptr = optpt->buf;
        !           237:                        len = BUFLEN;
        !           238:                }
        !           239: 
        !           240:                argv++;         /* done with this option arg. */
        !           241: 
        !           242:            } else {
        !           243: 
        !           244:                /*
        !           245:                 * Pick up a piece of a string and put it into
        !           246:                 * the appropriate buffer.
        !           247:                 */
        !           248:                if (**argv == '-') {
        !           249:                        state = OPTION;
        !           250:                        argc++; /* uncount this arg. */
        !           251:                        continue;
        !           252:                }
        !           253: 
        !           254:                if ((tlen = strlen(*argv)) >= len)
        !           255:                        xerror("Argument string too long");
        !           256:                (void) strcpy(ptr, *argv++);
        !           257:                ptr += tlen;
        !           258:                if (*(ptr-1) != filchar)
        !           259:                        *ptr++ = filchar;
        !           260:                len -= tlen + 1;
        !           261:                *ptr = '\0';
        !           262:            }
        !           263:        }
        !           264: 
        !           265:        /*
        !           266:         * ALL of the command line has now been processed. (!)
        !           267:         */
        !           268: 
        !           269:        tty = isatty(fileno(stdin));
        !           270: 
        !           271:        /* This code is really intended to be replaced by the control message. */
        !           272:        if (mode == CANCEL) {
        !           273:                char *p; FILE *f;
        !           274:                f = xfopen(filename, "r");
        !           275:                (void) hread(&header, f, TRUE);
        !           276:                p = index(header.path, ' ');
        !           277:                if (p != NULL)
        !           278:                        *p = 0;
        !           279:                p = header.path;
        !           280:                if (strncmp(username, p, strlen(username))
        !           281:                        && uid != ROOTID && uid != geteuid() && uid)
        !           282:                        xerror("Not contributor");
        !           283:                cancel();
        !           284:                xxit(0);
        !           285:        }
        !           286: 
        !           287:        if (*header.nbuf) {
        !           288:                lcase(header.nbuf);
        !           289:                ptr = index(header.nbuf, '\0');
        !           290:                if (ptr[-1] == NGDELIM)
        !           291:                        *--ptr = '\0';
        !           292:        }
        !           293:        (void) nstrip(header.title);
        !           294:        (void) nstrip(header.expdate);
        !           295:        (void) nstrip(header.followid);
        !           296:        if (mode != PROC) {
        !           297:                getident(&header);
        !           298:                if (hflag) {
        !           299:                        header.path[0] = '\0';
        !           300:                        (void) hread(&header, stdin, FALSE);
        !           301:                        /* there are certain fields we won't let him specify. */
        !           302:                        if (header.from[0])
        !           303:                                (void) strcpy(forgedname, header.from);
        !           304:                        if (!header.approved[0])
        !           305:                                Mflag = FALSE;
        !           306:                        header.from[0] = '\0';
        !           307:                        header.subdate[0] = '\0';
        !           308:                        header.sender[0] = '\0';
        !           309:                }
        !           310: #ifdef MYORG
        !           311:                if (header.organization[0] == '\0' && !Mflag) {
        !           312:                        strncpy(header.organization, MYORG, BUFLEN);
        !           313:                        if (strncmp(header.organization, "Frobozz", 7) == 0)
        !           314:                                header.organization[0] = '\0';
        !           315:                        if (ptr = getenv("ORGANIZATION"))
        !           316:                                strncpy(header.organization, ptr, BUFLEN);
        !           317:                        /*
        !           318:                         * Note that the organization can also be turned off by
        !           319:                         * setting it to the null string, either in MYORG or
        !           320:                         * $ORGANIZATION in the environment.
        !           321:                         */
        !           322:                        if (header.organization[0] == '/') {
        !           323:                                mfd = fopen(header.organization, "r");
        !           324:                                if (mfd) {
        !           325:                                        (void) fgets(header.organization, sizeof header.organization, mfd);
        !           326:                                        (void) fclose(mfd);
        !           327:                                } else {
        !           328:                                        header.organization[0] = '\0';
        !           329:                                        logerr("Couldn't open %s",
        !           330:                                                header.organization);
        !           331:                                }
        !           332:                                ptr = index(header.organization, '\n');
        !           333:                                if (ptr)
        !           334:                                        *ptr = '\0';
        !           335:                        }
        !           336:                }
        !           337: #endif /* MYORG */
        !           338:                if (forgedname[0]) {
        !           339:                        register char *p1;
        !           340:                        if (Mflag)
        !           341:                                sprintf(header.path, "%s!%s",
        !           342:                                        FULLSYSNAME, username);
        !           343:                        else if (!header.path[0]) {
        !           344:                                (void) strcpy(header.path, forgedname);
        !           345: 
        !           346:                                if ((p1 = strpbrk(header.path, "@ (<")) != NULL)
        !           347:                                        *p1 = '\0';
        !           348:                        }
        !           349:                        if (!Mflag && !strpbrk(forgedname, "@ (<"))
        !           350:                                (void) sprintf(header.from,"%s@%s%s",
        !           351:                                        forgedname, FULLSYSNAME, MYDOMAIN);
        !           352:                        else
        !           353:                                (void) strncpy(header.from, forgedname, BUFLEN);
        !           354: 
        !           355:                        (void) sprintf(header.sender, "%s@%s%s",
        !           356:                                username, FULLSYSNAME, MYDOMAIN);
        !           357:                } else {
        !           358:                        gensender(&header, username);
        !           359:                }
        !           360:        }
        !           361: 
        !           362:        /* Authorize newsgroups. */
        !           363:        if (mode == PROC) {
        !           364: #ifdef BATCH
        !           365:                checkbatch();
        !           366: #endif /* BATCH */
        !           367:                (void) signal(SIGHUP, SIG_IGN);
        !           368:                (void) signal(SIGINT, SIG_IGN);
        !           369:                (void) signal(SIGQUIT, SIG_IGN);
        !           370:                header.ident[0] = '\0';
        !           371:                if (hread(&header, stdin, TRUE) == NULL)
        !           372:                        xerror("Inbound news is garbled");
        !           373:                input();
        !           374:                if (history(&header)) {
        !           375:                        log("Duplicate article %s rejected. Path: %s",
        !           376:                                header.ident, header.path);
        !           377:                        xxit(0);
        !           378:                }
        !           379:        }
        !           380: 
        !           381:        /* Easy way to make control messages, since all.all.ctl is unblessed */
        !           382:        if (mode != PROC && prefix(header.title, "cmsg ") && header.ctlmsg[0] == 0)
        !           383:                (void) strcpy(header.ctlmsg, &header.title[5]);
        !           384:        is_ctl = mode != CREATENG &&
        !           385:                (ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]);
        !           386: #ifdef DEBUG
        !           387:        fprintf(stderr,"is_ctl set to %d\n", is_ctl);
        !           388: #endif
        !           389: 
        !           390:                        /* Must end in comma (NGDELIM) */
        !           391: #define MODGROUPS      "mod.all,all.mod,all.announce,"
        !           392:        if (ngmatch(header.nbuf, MODGROUPS) && !header.approved[0]) {
        !           393:                mfd = mailhdr(&header, "Moderated newsgroup");
        !           394:                if (mfd) {
        !           395:                        fprintf(mfd, "This newsgroup is moderated, and cannot be posted to directly.\n");
        !           396:                        fprintf(mfd, "Please mail your article to the moderator for posting.\n");
        !           397:                        hwrite(&header, mfd);
        !           398:                        if (infp)
        !           399:                                while ((i = getc(infp)) != EOF)
        !           400:                                        putc(i, mfd);
        !           401:                        (void) mclose(mfd);
        !           402:                }
        !           403:                xerror("Unapproved moderated newsgroup.");
        !           404:        }
        !           405: 
        !           406:        if (mode != CREATENG) {
        !           407:                if (!*header.title)
        !           408:                        xerror("No title, ng %s from %s", header.nbuf,
        !           409:                                header.from);
        !           410:                if (!*header.nbuf)
        !           411:                        (void) strcpy(header.nbuf, DFLTNG);
        !           412:        }
        !           413: 
        !           414:        if (mode <= UNPROC) {
        !           415: #ifdef FASCIST
        !           416:                if (uid && uid != ROOTID && fascist(user, header.nbuf))
        !           417:                                xerror("User %s is not authorized to post to newsgroup %s", user, header.nbuf);
        !           418: #endif /* FASCIST */
        !           419:                ctlcheck();
        !           420:        }
        !           421: 
        !           422:        if (mode == CREATENG)
        !           423:                createng();
        !           424:        /* Determine input. */
        !           425:        if (mode != PROC)
        !           426:                input();
        !           427: 
        !           428:        /* Do the actual insertion. */
        !           429:        insert();
        !           430: }
        !           431: 
        !           432: /*
        !           433:  *     Create a newsgroup
        !           434:  */
        !           435: createng()
        !           436: {
        !           437: 
        !           438:        /*
        !           439:         * Only certain users are allowed to create newsgroups
        !           440:         */
        !           441:        if (uid != ROOTID && uid != geteuid() && uid) {
        !           442:                fprintf(stderr, "Please contact one of the local netnews people\n\tto create this group for you");
        !           443:                xxit(1);
        !           444:        }
        !           445: 
        !           446:        (void) sprintf(bfr, "%s/inews -n %s.ctl -t cmsg newgroup %s -d local",
        !           447:                LIB, header.nbuf, header.nbuf);
        !           448:        printf("Please type in a paragraph describing the new newsgroup.\n");
        !           449:        printf("End with control D as usual.\n");
        !           450:        printf("%s\n", bfr);
        !           451:        (void) fflush(stdout);
        !           452:        (void) system(bfr);
        !           453:        exit(0);
        !           454:        /*NOTREACHED*/
        !           455: }
        !           456: 
        !           457: char firstbufname[BUFLEN];
        !           458: /*
        !           459:  *     Link ARTICLE into dir for ngname and update active file.
        !           460:  */
        !           461: long
        !           462: localize(ngname)
        !           463: char   *ngname;
        !           464: {
        !           465:        char afline[BUFLEN];
        !           466:        long ngsize;
        !           467:        long fpos;
        !           468:        int e;
        !           469:        char *cp;
        !           470: 
        !           471:        lock();
        !           472:        actfp = xfopen(ACTIVE, "r+");
        !           473: 
        !           474:        for(;;) {
        !           475:                fpos = ftell(actfp);
        !           476:                if (fgets(afline, sizeof afline, actfp) == NULL) {
        !           477:                        unlock();
        !           478:                        (void) fclose(actfp);
        !           479:                        logerr("Can't fine \"%s\" in active file", ngname);
        !           480:                        return FALSE;           /* No such newsgroup locally */
        !           481:                }
        !           482:                if (prefix(afline, ngname)) {
        !           483:                        (void) sscanf(afline, "%s %ld", bfr, &ngsize);
        !           484:                        if (strcmp(bfr, ngname) == 0) {
        !           485:                                if (ngsize < 0 || ngsize > 99998) {
        !           486:                                        logerr("found bad ngsize %ld ng %s, setting to 1", ngsize, bfr);
        !           487:                                        ngsize = 1;
        !           488:                                }
        !           489:                                break;
        !           490:                        }
        !           491:                }
        !           492:        }
        !           493:        for (;;) {
        !           494:                cp = dirname(ngname);
        !           495:                if (!exists(cp))
        !           496:                        mknewsg(cp, ngname);
        !           497: 
        !           498:                (void) sprintf(bfr, "%s/%ld", cp, ngsize+1);
        !           499: #ifdef VMS
        !           500:                if (vmslink(ARTICLE, bfr) == 0)
        !           501:                        break;
        !           502: #else /* !VMS */
        !           503:                if (link(ARTICLE, bfr) == 0)
        !           504:                        break;
        !           505: #endif /* !VMS */
        !           506:                e = errno;      /* keep log from clobbering it */
        !           507:                log("Cannot install article as %s: %s", bfr, errmsg(errno));
        !           508:                if (e != EEXIST) {
        !           509:                        logerr("Link into %s failed (%s); check dir permissions.",
        !           510:                            bfr, errmsg(e));
        !           511:                        unlock();
        !           512:                        (void) fclose(actfp);
        !           513:                        return FALSE;
        !           514:                }
        !           515:                ngsize++;
        !           516:        }
        !           517: 
        !           518:        (void) fflush(actfp);
        !           519: #ifdef VMS
        !           520:        (void) fclose(actfp);
        !           521:        vmstounix(ACTIVE);
        !           522:        actfp = fopen(ACTIVE, "r+");
        !           523: #endif /* VMS */
        !           524: 
        !           525:        /*
        !           526:         * This works around a bug in the 4.1bsd stdio
        !           527:         * on fseeks to non even offsets in r+w files
        !           528:         */
        !           529:        if (fpos&1)
        !           530:                (void) rewind(actfp);
        !           531: 
        !           532:        (void) fseek(actfp, fpos, 0);
        !           533:        /* Has to be same size as old because of %05d.
        !           534:         * This will overflow with 99999 articles.
        !           535:         */
        !           536:        fprintf(actfp, "%s %05ld", ngname, ngsize+1);
        !           537:        if (ferror(actfp))
        !           538:                xerror("Active file write failed");
        !           539:        (void) fclose(actfp);
        !           540: #ifdef VMS
        !           541:        unixtovms(ACTIVE);
        !           542: #endif /* VMS */
        !           543:        unlock();
        !           544:        if (firstbufname[0] == '\0')
        !           545:                (void) strcpy(firstbufname, bfr);
        !           546:        (void) sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
        !           547:        addhist(bfr);
        !           548:        return ngsize+1;
        !           549: }
        !           550: 
        !           551: /*
        !           552:  *     Localize for each newsgroup and broadcast.
        !           553:  */
        !           554: insert()
        !           555: {
        !           556:        register char *ptr;
        !           557:        register FILE *tfp;
        !           558:        register int c;
        !           559:        struct srec srec;       /* struct for sys file lookup   */
        !           560:        struct tm *tm;
        !           561:        int is_invalid = FALSE;
        !           562:        int exitcode = 0;
        !           563:        long now;
        !           564: #ifdef DOXREFS
        !           565:        register char *nextref = header.xref;
        !           566: #endif /* DOXREFS */
        !           567: 
        !           568:        /* Fill up the rest of header. */
        !           569:        if (mode != PROC) {
        !           570:                history(&header);
        !           571:        }
        !           572:        dates(&header);
        !           573:        (void) time(&now);
        !           574:        tm = localtime(&now);
        !           575:        if (header.expdate[0])
        !           576:                addhist(" ");
        !           577: #ifdef USG
        !           578:        sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t",
        !           579: #else /* !USG */
        !           580:        sprintf(bfr,"%02d/%02d/%d %02d:%02d\t",
        !           581: #endif /* !USG */
        !           582:                tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min);
        !           583:        addhist(bfr);
        !           584:        log("%s %s ng %s subj '%s' from %s",
        !           585:                mode==PROC ? "received" : "posted",
        !           586:                header.ident, header.nbuf, header.title, header.from);
        !           587: 
        !           588:        /* Clean up Newsgroups: line */
        !           589:        if (!is_ctl && mode != CREATENG)
        !           590:                is_invalid = ngfcheck(mode == PROC);
        !           591: 
        !           592:        /* Write article to temp file. */
        !           593:        tfp = xfopen(mktemp(ARTICLE), "w");
        !           594: 
        !           595:        if (is_invalid) {
        !           596:                logerr("No valid newsgroups found, moved to junk");
        !           597:                if (localize("junk"))
        !           598:                        savehist(histline);
        !           599:                exitcode = 1;
        !           600:                goto writeout;
        !           601:        }
        !           602: 
        !           603:        if (time((time_t *)0) > (cgtdate(header.subdate) + HISTEXP) ){
        !           604:                logerr("Article too old, moved to junk");
        !           605:                if (localize("junk"))
        !           606:                        savehist(histline);
        !           607:                exitcode = 1;
        !           608:                goto writeout;
        !           609:        }
        !           610: 
        !           611:        if (is_ctl) {
        !           612:                exitcode = control(&header);
        !           613:                if (localize("control") && exitcode != 0)
        !           614:                        savehist(histline);
        !           615:        } else {
        !           616:                if (s_find(&srec, FULLSYSNAME) == FALSE) {
        !           617:                        logerr("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
        !           618:                        srec = dummy_srec;
        !           619:                }
        !           620: #ifdef DOXREFS
        !           621:                (void) strncpy(nextref, FULLSYSNAME, BUFLEN);
        !           622: #endif /* DOXREFS */
        !           623:                for (ptr = nbuf; *ptr;) {
        !           624:                        if (ngmatch(ptr,srec.s_nbuf) || index(ptr,'.') == NULL){
        !           625: #ifdef DOXREFS
        !           626:                                while (*nextref++)
        !           627:                                        ;
        !           628:                                (void) sprintf(--nextref, " %s:%ld", ptr, localize(ptr));
        !           629: #else /* !DOXREFS */
        !           630:                                (void) localize(ptr);
        !           631: #endif /* !DOXREFS */
        !           632:                        }
        !           633:                        while (*ptr++)
        !           634:                                ;
        !           635:                }
        !           636:                if (firstbufname[0] == '\0') {
        !           637:                        logerr("Newsgroups in active, but not sys");
        !           638:                        (void) localize("junk");
        !           639:                }
        !           640:        }
        !           641: #ifdef DOXREFS
        !           642:        if (index(header.nbuf, NGDELIM) == NULL)
        !           643:                header.xref[0] = '\0';
        !           644: #endif /* DOXREFS */
        !           645: 
        !           646: writeout:
        !           647:        /* Part 1 of kludge to get around article truncation problem */
        !           648:        if ( (c=getc(infp)) != EOF) {
        !           649:                ungetc(c, infp);
        !           650:                if (c == ' ' || c == '\t') {
        !           651:                        header.intnumlines++;
        !           652:                        (void) sprintf(header.numlines, "%d",
        !           653:                                header.intnumlines);
        !           654:                }
        !           655:        }
        !           656:        /* End of part 1 */
        !           657:        lhwrite(&header, tfp);
        !           658:        if ((c = getc(infp)) != EOF) {
        !           659:                /* Part 2 of kludge to get around article truncation problem */
        !           660:                if (c == ' ' || c == '\t' )
        !           661:                        putc('\n', tfp);
        !           662:                /* End of part 2 */
        !           663:                ungetc(c, infp);
        !           664:                while (fgets(bfr, BUFLEN, infp) != NULL)
        !           665:                        fputs(bfr, tfp);
        !           666:                if (bfr[strlen(bfr)-1] != '\n')
        !           667:                        putc('\n',tfp);
        !           668:        }
        !           669:        if (ferror(tfp))
        !           670:                xerror("Write failed for temp file");
        !           671:        (void) fclose(tfp);
        !           672:        (void) fclose(infp);
        !           673: 
        !           674:        if(exitcode == 0) {
        !           675:                int pid;
        !           676:                /* article has passed all the checks, so work in background */
        !           677:                if (mode != PROC)
        !           678:                        if ((pid=fork()) < 0)
        !           679:                                xerror("Can't fork");
        !           680:                        else if (pid > 0)
        !           681:                                exit(0);
        !           682: #ifdef SIGTTOU
        !           683:                signal(SIGTTOU, SIG_IGN);
        !           684: #endif /* SIGTTOU */
        !           685:                savehist(histline);
        !           686:                broadcast();
        !           687:        }
        !           688:        xxit(mode == PROC ? 0 : exitcode);
        !           689: }
        !           690: 
        !           691: input()
        !           692: {
        !           693:        register char *cp;
        !           694:        register int c;
        !           695:        register int empty = TRUE;
        !           696:        FILE *tmpfp;
        !           697:        int consec_newlines = 0;
        !           698:        int linecount = 0;
        !           699:        int linserted = 0;
        !           700: 
        !           701:        tmpfp = xfopen(mktemp(INFILE), "w");
        !           702:        if (*filename) {
        !           703:                tty = FALSE;
        !           704:                infp = xfopen(filename, "r");
        !           705:        } else {
        !           706:                infp = stdin;
        !           707:        }
        !           708:        while (!SigTrap && fgets(bfr, BUFLEN, stdin) != NULL) {
        !           709:                if (mode == PROC) {     /* zap trailing empty lines */
        !           710: #ifdef ZAPNOTES
        !           711:                        if (empty && bfr[0] == '#' && bfr[2] == ':'
        !           712:                                && header.nf_id[0] == '\0'
        !           713:                                && header.nf_from[0] == '\0' ) {
        !           714:                                (void) strcpy(header.nf_id, bfr);
        !           715:                                (void) nstrip(header.nf_id);
        !           716:                                (void) fgets(bfr, BUFLEN, stdin);
        !           717:                                (void) strcpy(header.nf_from, bfr);
        !           718:                                (void) nstrip(header.nf_from);
        !           719:                                (void) fgets(bfr, BUFLEN, stdin);
        !           720: 
        !           721:                                if (header.numlines[0]) {
        !           722:                                        header.intnumlines -= 2;
        !           723:                                        (void) sprintf(header.numlines, "%d", header.intnumlines);
        !           724:                                }
        !           725: 
        !           726:                                /* Strip trailing " - (nf)" */
        !           727:                                if ((cp = rindex(header.title, '-')) != NULL
        !           728:                                    && !strcmp(--cp, " - (nf)"))
        !           729:                                        *cp = '\0';
        !           730:                                log("Stripped notes header on %s", header.ident);
        !           731:                                continue;
        !           732:                        }
        !           733: #endif /* ZAPNOTES */
        !           734:                        if (bfr[0] == '\n' ||
        !           735:                                /* Bandage for older versions of inews */
        !           736:                                bfr[1] == '\n' && !isascii(bfr[0])) {
        !           737:                                consec_newlines++;      /* count it, in case */
        !           738:                                continue;               /* but don't write it*/
        !           739:                        }
        !           740:                        /* foo! a non-empty line. write out all saved lines. */
        !           741:                        while (consec_newlines > 0) {
        !           742:                                putc('\n', tmpfp);
        !           743:                                consec_newlines--;
        !           744:                                linecount++;
        !           745:                        }
        !           746:                }
        !           747:                if (mode != PROC && tty && strcmp(bfr, ".\n") == 0)
        !           748:                        break;
        !           749:                for (cp = bfr; c = toascii(*cp); cp++) {
        !           750:                        if (isprint(c) || isspace(c) || c == '\b')
        !           751:                                putc(c, tmpfp);
        !           752:                        if (c == '\n')
        !           753:                                linecount++;
        !           754:                }
        !           755:                if (bfr[0] == '>')
        !           756:                        linserted++;
        !           757:                empty = FALSE;
        !           758:        }
        !           759:        if (*filename)
        !           760:                (void) fclose(infp);
        !           761:        if (mode != PROC && linserted > (linecount-linserted))
        !           762:                xerror("Article rejected: More included text than new text");
        !           763: 
        !           764:        if (mode != PROC && !is_ctl && header.sender[0] == '\0') {
        !           765:                int siglines = 0;
        !           766:                char sbuf[BUFLEN];
        !           767:                (void) sprintf(bfr, "%s/%s", userhome, ".signature");
        !           768:                if (access(bfr, 4) == 0) {
        !           769:                        if ((infp = fopen(bfr, "r")) == NULL) {
        !           770:                                (void) fprintf(stderr,
        !           771:     "inews: \"%s\" left off (must be readable by \"inews\" owner)\n", bfr);
        !           772:                                goto finish;
        !           773:                        }
        !           774: 
        !           775:                        while (fgets(sbuf, sizeof sbuf, infp) != NULL)
        !           776:                                if (++siglines > 4)
        !           777:                                        break;
        !           778:                        if (siglines > 4)
        !           779:                                fprintf(stderr,".signature not included (> 4 lines)\n");
        !           780:                        else {
        !           781:                                rewind(infp);
        !           782:                                fprintf(tmpfp, "-- \n");        /* To separate */
        !           783:                                linecount++;
        !           784:                                while ((c = getc(infp)) != EOF) {
        !           785:                                        putc(c, tmpfp);
        !           786:                                        if (c == '\n')
        !           787:                                                linecount++;
        !           788:                                }
        !           789:                        }
        !           790:                        (void) fclose(infp);
        !           791:                }
        !           792:        }
        !           793: 
        !           794: finish:
        !           795:        if (ferror(tmpfp))
        !           796:                xerror("write failed to temp file");
        !           797:        (void) fclose(tmpfp);
        !           798:        if (SigTrap) {
        !           799:                if (tty)
        !           800:                        fprintf(stderr, "Interrupt\n");
        !           801:                if (tty && !empty)
        !           802:                        fwait(fsubr(newssave, (char *) NULL, (char *) NULL));
        !           803:                if (!tty)
        !           804:                        log("Blown away by an interrupt %d", SigTrap);
        !           805:                xxit(1);
        !           806:        }
        !           807:        if (tty)
        !           808:                fprintf(stderr, "EOT\n");
        !           809:        fflush(stdout);
        !           810:        infp = fopen(INFILE, "r");
        !           811:        if (header.numlines[0]) {
        !           812:                /*
        !           813:                 * Check line count if there's already one attached to
        !           814:                 * the article.  Could make this a fatal error -
        !           815:                 * throwing it away if it got chopped, in hopes that
        !           816:                 * another copy will come in later with a correct
        !           817:                 * line count.  But that seems a bit much for now.
        !           818:                 */
        !           819:                if (linecount != header.intnumlines) {
        !           820:                        if (linecount == 0)
        !           821:                                xerror("%s rejected. linecount expected %d, got 0", header.ident, header.intnumlines);
        !           822:                        if (linecount > header.intnumlines ||
        !           823:                            linecount+consec_newlines < header.intnumlines)
        !           824:                                log("linecount expected %d, got %d", header.intnumlines, linecount+consec_newlines);
        !           825:                }
        !           826:                /* adjust count for blank lines we stripped off */
        !           827:                if (consec_newlines) {
        !           828:                        header.intnumlines -= consec_newlines;
        !           829:                        if (header.intnumlines < 0 )
        !           830:                                header.intnumlines = 0; /* paranoia */
        !           831:                        (void) sprintf(header.numlines, "%d", header.intnumlines);
        !           832:                }
        !           833: 
        !           834:        } else {
        !           835:                /* Attach a line count to the article. */
        !           836:                header.intnumlines = linecount;
        !           837:                (void) sprintf(header.numlines, "%d", linecount);
        !           838:        }
        !           839: }
        !           840: 
        !           841: /*
        !           842:  * Make the directory for a new newsgroup.  ngname should be the
        !           843:  * full pathname of the directory.  Do the other stuff too.
        !           844:  * The various games with setuid and chown are to try to make sure
        !           845:  * the directory is owned by NEWSUSR and NEWSGRP, which is tough to
        !           846:  * do if you aren't root.  This will work on a UCB system (which allows
        !           847:  * setuid(geteuid()) or a USG system (which allows you to give away files
        !           848:  * you own with chown), otherwise you have to change your kernel to allow
        !           849:  * one of these things or run with your dirs 777 so that it doesn't matter
        !           850:  * who owns them.
        !           851:  */
        !           852: mknewsg(fulldir, ngname)
        !           853: char   *fulldir;
        !           854: char   *ngname;
        !           855: {
        !           856: #ifdef USG
        !           857:        register char *p;
        !           858:        char parent[200];
        !           859:        char sysbuf[200];
        !           860:        struct stat sbuf;
        !           861: #endif /* USG */
        !           862: 
        !           863:        if (ngname == NULL || !isalpha(ngname[0]))
        !           864:                xerror("Tried to make illegal newsgroup %s", ngname);
        !           865: 
        !           866: #ifdef USG
        !           867:        /*
        !           868:         * If the parent is 755 the setuid(getuid)
        !           869:         * will fail, and since mkdir is suid, and our real uid is random,
        !           870:         * the mkdir will fail.  So we have to temporarily chmod it to 777.
        !           871:         */
        !           872:        (void) strcpy(parent, fulldir);
        !           873:        while (p = rindex(parent, '/')) {
        !           874:                *p = '\0';
        !           875:                if (stat(parent, &sbuf) == 0) {
        !           876:                        (void) chmod(parent, 0777);
        !           877:                        break;
        !           878:                }
        !           879:        }
        !           880: #endif /* USG */
        !           881: 
        !           882:        /* Create the directory */
        !           883:        mkparents(fulldir);
        !           884:        if (mkdir(fulldir, 0777) < 0)
        !           885:                xerror("Cannot mkdir %s: %s", fulldir, errmsg(errno));
        !           886: 
        !           887: #ifdef USG
        !           888:        (void) chmod(parent, (int)sbuf.st_mode);        /* put it back */
        !           889:        /*
        !           890:         * Give away the directories we just created which were assigned
        !           891:         * our real uid.
        !           892:         */
        !           893:        (void) setuid(uid);
        !           894:        (void) chown(fulldir, duid, dgid);
        !           895:        (void) strcpy(sysbuf, fulldir);
        !           896:        while (p = rindex(sysbuf, '/')) {
        !           897:                *p = '\0';
        !           898:                /* stop when get to last known good parent */
        !           899:                if (strcmp(sysbuf, parent) == 0)
        !           900:                        break;
        !           901:                (void) chown(sysbuf, duid, dgid);
        !           902:        }
        !           903:        (void) setuid(duid);
        !           904: #endif /* USG */
        !           905: 
        !           906:        log("make newsgroup %s in dir %s", ngname, fulldir);
        !           907: }
        !           908: 
        !           909: /*
        !           910:  * If any parent directories of this dir don't exist, create them.
        !           911:  */
        !           912: mkparents(dname)
        !           913: char *dname;
        !           914: {
        !           915:        char buf[200];
        !           916:        register char *p;
        !           917: 
        !           918:        (void) strcpy(buf, dname);
        !           919:        p = rindex(buf, '/');
        !           920:        if (p)
        !           921:                *p = '\0';
        !           922:        if (exists(buf))
        !           923:                return;
        !           924:        mkparents(buf);
        !           925:        if (mkdir(buf, 0777) < 0)
        !           926:                xerror("Can not mkdir %s: %s", buf, errmsg(errno));
        !           927: }
        !           928: 
        !           929: cancel()
        !           930: {
        !           931:        register FILE *fp;
        !           932: 
        !           933:        log("cancel article %s", filename);
        !           934:        fp = fopen(filename, "r");
        !           935:        if (fp == NULL) {
        !           936:                log("article %s not found", filename);
        !           937:                return;
        !           938:        }
        !           939:        if (hread(&header, fp, TRUE) == NULL)
        !           940:                xerror("Article is garbled.");
        !           941:        (void) fclose(fp);
        !           942:        (void) unlink(filename);
        !           943: }

unix.superglobalmegacorp.com

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