Annotation of researchv10no/cmd/netnews/src/inews.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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