Annotation of 43BSD/contrib/news/src/inews.c, revision 1.1.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.