Annotation of 43BSDTahoe/new/news/src/inews.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This software is Copyright (c) 1986 by Rick Adams.
        !             3:  *
        !             4:  * Permission is hereby granted to copy, reproduce, redistribute or
        !             5:  * otherwise use this software as long as: there is no monetary
        !             6:  * profit gained specifically from the use or reproduction or this
        !             7:  * software, it is not sold, rented, traded or otherwise marketed, and
        !             8:  * this copyright notice is included prominently in any copy
        !             9:  * made.
        !            10:  *
        !            11:  * The author make no claims as to the fitness or correctness of
        !            12:  * this software for any use whatsoever, and it is provided as is. 
        !            13:  * Any use of this software is at the user's own risk.
        !            14:  *
        !            15:  * inews - insert, receive, and transmit news articles.
        !            16:  *
        !            17:  */
        !            18: 
        !            19: #ifdef SCCSID
        !            20: static char    *SccsId = "@(#)inews.c  2.82    10/15/87";
        !            21: #endif /* SCCSID */
        !            22: 
        !            23: #include "iparams.h"
        !            24: 
        !            25: # ifdef LOCKF
        !            26: # include <unistd.h>
        !            27: # include <fcntl.h>
        !            28: 
        !            29: # if defined(F_RDLCK) && defined(F_SETLK)
        !            30: struct flock news_lock;
        !            31: #  endif /* F_RDLCK  && F_SETLK */
        !            32: # endif /* LOCKF */
        !            33: 
        !            34: #ifdef BSD4_2
        !            35: # include <sys/file.h>
        !            36: #else  /* !BSD4_2 */
        !            37: # if defined(USG) && !defined(LOCKF)
        !            38: # include <fcntl.h>
        !            39: # endif /* USG */
        !            40: #endif /* !BSD4_2 */
        !            41: /* local defines for inews */
        !            42: 
        !            43: #define OPTION 0       /* pick up an option string */
        !            44: #define STRING 1       /* pick up a string of arguments */
        !            45: 
        !            46: #define UNKNOWN 0001   /* possible modes for news program */
        !            47: #define UNPROC 0002    /* Unprocessed input */
        !            48: #define PROC   0004    /* Processed input */
        !            49: #define        CONTROL 0010    /* Control Message */
        !            50: #define        CREATENG 0020   /* Create a new newsgroup */
        !            51: 
        !            52: #define DONT_SPOOL     0
        !            53: #define        DO_SPOOL        1
        !            54: #define        EXPIRE_RUNNING  2
        !            55: int spool_news = DONT_SPOOL;
        !            56: 
        !            57: extern char histline[];
        !            58: char   forgedname[NAMELEN];    /* A user specified -f option. */
        !            59: /* Fake sys line in case they forget their own system */
        !            60: struct srec dummy_srec = { "MEMEME", "", "all", "", "" };
        !            61: 
        !            62: char *Progname = "inews";      /* used by xerror to identify failing program */
        !            63: 
        !            64: struct {                       /* options table. */
        !            65:        char    optlet;         /* option character. */
        !            66:        char    filchar;        /* if to pickup string, fill character. */
        !            67:        int     flag;           /* TRUE if have seen this opt. */
        !            68:        int     oldmode;        /* OR of legal input modes. */
        !            69:        int     newmode;        /* output mode. */
        !            70:        char    *buf;           /* string buffer */
        !            71: } *optpt, options[] = { /*
        !            72: optlet filchar         flag    oldmode newmode         buf     */
        !            73: 't',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.title,
        !            74: 'n',   NGDELIM,        FALSE,  UNPROC, UNKNOWN,        header.nbuf,
        !            75: 'd',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.distribution,
        !            76: 'e',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.expdate,
        !            77: 'p',   '\0',           FALSE,  UNKNOWN|PROC,   PROC,   filename,
        !            78: 'f',   '\0',           FALSE,  UNPROC, UNKNOWN,        forgedname,
        !            79: 'F',   ' ',            FALSE,  UNPROC, UNKNOWN,        header.followid,
        !            80: 'c',   ' ',            FALSE,  UNKNOWN,UNKNOWN,        header.ctlmsg,
        !            81: 'C',   ' ',            FALSE,  UNKNOWN,CREATENG,       header.ctlmsg,
        !            82: #define hflag  options[9].flag
        !            83: 'h',   '\0',           FALSE,  UNPROC, UNKNOWN,        filename,
        !            84: #define oflag  options[10].flag
        !            85: 'o',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.organization,
        !            86: #define Mflag  options[11].flag
        !            87: 'M',   '\0',           FALSE,  UNPROC, UNKNOWN,        filename,
        !            88: 'a',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.approved,
        !            89: 'U',   '\0',           FALSE,  PROC, PROC,             filename,
        !            90: #define Sflag  options[14].flag
        !            91: 'S',   '\0',           FALSE,  UNKNOWN|PROC,   UNPROC, filename,
        !            92: 'x',   '\0',           FALSE,  UNPROC, UNKNOWN,        not_here,
        !            93: 'r',   '\0',           FALSE,  UNPROC, UNKNOWN,        header.replyto,
        !            94: '\0',  '\0',           0,      0,      0,              (char *)NULL
        !            95: };
        !            96: 
        !            97: FILE *mailhdr();
        !            98: extern int errno;
        !            99: 
        !           100: struct timeb Now;
        !           101: 
        !           102: /*
        !           103:  *     Authors:
        !           104:  *             Matt Glickman   [email protected]
        !           105:  *             Mark Horton     [email protected]
        !           106:  *             Stephen Daniels [email protected]
        !           107:  *             Tom Truscott    [email protected]
        !           108:  *             Rick Adams      [email protected]
        !           109:  *     IHCC version adapted by:
        !           110:  *             Larry Marek     [email protected]
        !           111:  */
        !           112: main(argc, argv)
        !           113: int    argc;
        !           114: register char **argv;
        !           115: {
        !           116:        int     state;          /* which type of argument to pick up    */
        !           117:        int     tlen, len;      /* temps for string processing routine  */
        !           118:        register char *ptr;     /* pointer to rest of buffer            */
        !           119:        int     filchar;        /* fill character (state = STRING)      */
        !           120:        char    *user = NULL, *home = NULL;     /* environment temps    */
        !           121:        struct passwd   *pw;    /* struct for pw lookup                 */
        !           122:        struct group    *gp;    /* struct for group lookup              */
        !           123:        register int    i;
        !           124:        FILE    *mfd;           /* mail file file-descriptor            */
        !           125: 
        !           126:        /* uuxqt doesn't close all its files */
        !           127:        for (i = 3; !close(i); i++)
        !           128:                ;
        !           129:        /* set up defaults and initialize. */
        !           130:        mode = UNKNOWN;
        !           131:        infp = stdin;
        !           132:        pathinit();
        !           133:        savmask = umask(N_UMASK);       /* set up mask */
        !           134:        ptr = rindex(*argv, '/');
        !           135:        if (!ptr)
        !           136:                ptr = *argv - 1;
        !           137:        actfp = xfopen(ACTIVE, "r+");
        !           138: #ifdef LOCKF
        !           139: # if   defined(F_RDLCK) && defined(F_SETLK)
        !           140:        news_lock.l_type = F_RDLCK;
        !           141:        if (fcntl(fileno(actfp), F_SETLK, &news_lock) < 0) {
        !           142: # else /* !F_RDLCK */
        !           143:        if (lockf(fileno(actfp), F_TLOCK, 0L) < 0) {
        !           144: # endif /* !F_RDLCK */
        !           145:                if (errno != EAGAIN && errno != EACCES)
        !           146: #else  /* !LOCKF */
        !           147: #ifdef BSD4_2
        !           148:        if (flock(fileno(actfp), LOCK_SH|LOCK_NB) < 0) {
        !           149:                if (errno != EWOULDBLOCK)
        !           150: #else  /* !BSD4_2 */
        !           151:        sprintf(bfr, "%s.lock", ACTIVE);
        !           152:        if (LINK(ACTIVE, bfr) < 0) {
        !           153:                if (errno != EEXIST)
        !           154: #endif /* V7 */
        !           155: #endif /* !BSD4_2 */
        !           156:                        xerror("Can't lock %s: %s", ACTIVE, errmsg(errno));
        !           157:                spool_news = EXPIRE_RUNNING;
        !           158:        } else {
        !           159: #ifdef SPOOLNEWS
        !           160:                if (argc > 1 && !strcmp(*(argv+1), "-S")) {
        !           161:                        argc--;
        !           162:                        argv++;
        !           163:                        Sflag = 1;
        !           164:                } else
        !           165:                        spool_news = DO_SPOOL;
        !           166: 
        !           167: #endif /* SPOOLNEWS */
        !           168:        }
        !           169:        if (spool_news != EXPIRE_RUNNING) {
        !           170:                /* only unlock if we locked */
        !           171: #ifdef LOCKF
        !           172:                (void) lockf(fileno(actfp), F_ULOCK, 0L);
        !           173: #else  /* !LOCKF */
        !           174: #ifdef         BSD4_2
        !           175:                (void) flock(fileno(actfp), LOCK_UN);
        !           176: #else  /* !BSD4_2 */
        !           177:                (void) UNLINK(bfr);
        !           178: #endif         /* V7 */
        !           179: #endif /* !BSD4_2 */
        !           180:        } else {        /* expire is running */
        !           181:                if (argc > 1 && !strcmp(*(argv+1), "-S"))
        !           182:                        exit(42);       /* inform rnews -U by exit status */
        !           183:        }
        !           184:        if (argc > 1 && !strcmp(*(argv+1), "-U")) {
        !           185:                /* can't unspool while things are locked */
        !           186:                if (spool_news == EXPIRE_RUNNING)
        !           187:                        xxit(0);
        !           188:                dounspool();
        !           189:                /* NOT REACHED */
        !           190:        }
        !           191: 
        !           192:        if (!STRNCMP(ptr+1, "rnews", 5)) {
        !           193:                mode = PROC;
        !           194:                if (spool_news != DONT_SPOOL) {
        !           195:                        dospool((char *)NULL, FALSE);
        !           196:                        /* NOT REACHED */
        !           197:                }
        !           198: #ifdef NICENESS
        !           199:                if (nice(0) < NICENESS)
        !           200:                        (void) nice(NICENESS);
        !           201: #endif /* NICENESS */
        !           202:        } else {
        !           203:        /* it's not rnews, so it must be inews */
        !           204:                if (argc < 2)
        !           205:                        goto usage;
        !           206: #ifndef SPOOLINEWS
        !           207:                if (spool_news == DO_SPOOL)
        !           208:                        spool_news = DONT_SPOOL;
        !           209: #endif /* SPOOLINEWS */
        !           210:        }
        !           211: 
        !           212:        state = OPTION;
        !           213:        header.title[0] = header.nbuf[0] = filename[0] = '\0';
        !           214: 
        !           215:        /* check for existence of special files */
        !           216: #ifdef DBM
        !           217:        chkfile(ARTFILE);
        !           218: #else
        !           219:        chkdir(ARTFILE);
        !           220: #endif /* DBM */
        !           221:        chkfile(ACTIVE);
        !           222:        SigTrap = FALSE;        /* true if a signal has been caught */
        !           223:        if (mode != PROC) {
        !           224:                (void) signal(SIGHUP, onsig);
        !           225:                (void) signal(SIGINT, onsig);
        !           226:        }
        !           227:        /*
        !           228:         * Catch "filesize exceeded" signals on 4.2BSD systems
        !           229:         * - the history files may exceed this limit.
        !           230:         */
        !           231: #ifdef  SIGXFSZ
        !           232:        (void) signal(SIGXFSZ, SIG_IGN);
        !           233: #endif /* SIGXFSZ */
        !           234:        uid = getuid();
        !           235:        gid = getgid();
        !           236:        duid = geteuid();
        !           237:        dgid = getegid();
        !           238:        (void) ftime(&Now);
        !           239:        if (uid == 0 && duid == 0) {
        !           240:                /*
        !           241:                 * Must go through with this kludge since
        !           242:                 * some systems do not honor the setuid bit
        !           243:                 * when root invokes a setuid program.
        !           244:                 */
        !           245:                if ((pw = getpwnam(NEWSUSR)) == NULL)
        !           246:                        xerror("Cannot get NEWSU pw entry");
        !           247: 
        !           248:                duid = pw->pw_uid;
        !           249:                if ((gp = getgrnam(NEWSGRP)) == NULL)
        !           250:                        xerror("Cannot get NEWSG gr entry");
        !           251:                dgid = gp->gr_gid;
        !           252:                (void) setgid(dgid);
        !           253:                (void) setuid(duid);
        !           254:        }
        !           255: 
        !           256: #ifndef DOGETUSER
        !           257:        /*
        !           258:         * Force the use of 'getuser()' to prevent forgery of articles
        !           259:         * by just changing $LOGNAME
        !           260:         */
        !           261:        if (isatty(fileno(stderr))) {
        !           262:                if ((user = getenv("USER")) == NULL)
        !           263:                        user = getenv("LOGNAME");
        !           264:                if ((home = getenv("HOME")) == NULL)
        !           265:                        home = getenv("LOGDIR");
        !           266:        }
        !           267: #endif /* !DOGETUSER */
        !           268:        if (user == NULL || home == NULL)
        !           269:                getuser();
        !           270:        else {
        !           271:                if (STRCMP(username, "Unknown") == 0 || username[0] == 0) {
        !           272:                        username = AllocCpy(user);
        !           273:                }
        !           274:                userhome = AllocCpy(home);
        !           275:        }
        !           276:        getuser();
        !           277: 
        !           278:        /* loop once per arg. */
        !           279: 
        !           280:        ++argv;         /* skip first arg, which is prog name. */
        !           281: 
        !           282:        while (--argc) {
        !           283:            if (state == OPTION) {
        !           284:                if (**argv != '-') {
        !           285:                        xerror("Bad option string \"%s\"", *argv);
        !           286:                }
        !           287:                while (*++*argv != '\0') {
        !           288:                        for (optpt = options; optpt->optlet != '\0'; ++optpt) {
        !           289:                                if (optpt->optlet == **argv)
        !           290:                                        goto found;
        !           291:                        }
        !           292:                        /* unknown option letter */
        !           293: usage:
        !           294:                        fprintf(stderr, "usage: inews -t title");
        !           295:                        fprintf(stderr, " [ -n newsgroups ]");
        !           296:                        fprintf(stderr, " [ -e expiration date ]\n");
        !           297:                        fprintf(stderr, "\t[ -f sender]\n\n");
        !           298:                        xxit(1);
        !           299: 
        !           300:                    found:;
        !           301:                        if (optpt->flag == TRUE || (mode != UNKNOWN &&
        !           302:                            (mode&optpt->oldmode) == 0)) {
        !           303:                                xerror("Bad %c option", **argv);
        !           304:                        }
        !           305:                        if (mode == UNKNOWN)
        !           306:                                mode = optpt->newmode;
        !           307:                        filchar = optpt->filchar;
        !           308:                        optpt->flag = TRUE;
        !           309:                        state = STRING;
        !           310:                        ptr = optpt->buf;
        !           311:                        len = BUFLEN;
        !           312:                }
        !           313: 
        !           314:                argv++;         /* done with this option arg. */
        !           315: 
        !           316:            } else {
        !           317: 
        !           318:                /*
        !           319:                 * Pick up a piece of a string and put it into
        !           320:                 * the appropriate buffer.
        !           321:                 */
        !           322:                if (**argv == '-') {
        !           323:                        state = OPTION;
        !           324:                        argc++; /* uncount this arg. */
        !           325:                        continue;
        !           326:                }
        !           327: 
        !           328:                if ((tlen = strlen(*argv)) >= len)
        !           329:                        xerror("Argument string too long");
        !           330:                (void) strcpy(ptr, *argv++);
        !           331:                ptr += tlen;
        !           332:                if (*(ptr-1) != filchar)
        !           333:                        *ptr++ = filchar;
        !           334:                len -= tlen + 1;
        !           335:                *ptr = '\0';
        !           336:            }
        !           337:        }
        !           338: 
        !           339:        /*
        !           340:         * ALL of the command line has now been processed. (!)
        !           341:         */
        !           342: 
        !           343:        if (*filename) {
        !           344:                infp = freopen(filename, "r", stdin);
        !           345:                if (infp == NULL)
        !           346:                        xerror("freopen(%s): %s", filename, errmsg(errno));
        !           347:        } else
        !           348:                infp = stdin;
        !           349: 
        !           350:        tty = isatty(fileno(infp));
        !           351: 
        !           352:        if (mode == CREATENG)
        !           353:                createng();
        !           354: 
        !           355:        if (header.ctlmsg[0] != '\0' && header.title[0] == '\0')
        !           356:                (void) strcpy(header.title, header.ctlmsg);
        !           357: 
        !           358:        if (*header.nbuf) {
        !           359:                lcase(header.nbuf);
        !           360:                ptr = index(header.nbuf, '\0');
        !           361:                if (ptr[-1] == NGDELIM)
        !           362:                        *--ptr = '\0';
        !           363:        }
        !           364:        (void) nstrip(header.title);
        !           365:        (void) nstrip(header.expdate);
        !           366:        (void) nstrip(header.followid);
        !           367:        if (mode != PROC) {
        !           368:                if (hflag) {
        !           369:                        header.path[0] = '\0';
        !           370:                        (void) hread(&header, infp, FALSE);
        !           371:                        /* there are certain fields we won't let him specify. */
        !           372:                        if (header.from[0]) {
        !           373:                                (void) fixfrom(&header);
        !           374:                                if (Sflag && !Mflag && !header.approved[0] &
        !           375:                                        !header.sender[0]) {
        !           376:                                        register char *p;
        !           377:                                        strcpy(bfr, header.from);
        !           378:                                        p  = strpbrk(bfr, "@ !");
        !           379:                                        if (p)
        !           380:                                                *p = '\0';
        !           381:                                        if ((pw = getpwnam(bfr)) != NULL) {
        !           382:                                                uid = pw->pw_uid;
        !           383:                                                gid = pw->pw_gid;
        !           384:                                                username = AllocCpy(bfr);
        !           385:                                        }
        !           386:                                } else {
        !           387:                                        (void) strcpy(forgedname, header.from);
        !           388:                                        header.from[0] = '\0';
        !           389:                                }
        !           390:                        }
        !           391:                        if (!header.approved[0])
        !           392:                                Mflag = FALSE;
        !           393:                        header.sender[0] = '\0';
        !           394:                        if (header.subdate[0] && cgtdate(header.subdate) < 0)
        !           395:                                header.subdate[0] = '\0';
        !           396:                }
        !           397: 
        !           398:                if (header.ident[0] == '\0')
        !           399:                        getident(&header);
        !           400: 
        !           401:                if (forgedname[0]) {
        !           402:                        register char *p1;
        !           403:                        if (Mflag)
        !           404:                                sprintf(header.path, "%s!%s",
        !           405:                                        PATHSYSNAME, username);
        !           406:                        else if (!header.path[0]) {
        !           407:                                (void) strcpy(header.path, forgedname);
        !           408: 
        !           409:                                if ((p1 = strpbrk(header.path, " (<")) != NULL)
        !           410:                                        *p1 = '\0';
        !           411:                        }
        !           412:                        if (!Mflag && !strpbrk(forgedname, "@ (<"))
        !           413:                                (void) sprintf(header.from,"%s@%s",
        !           414:                                        forgedname, FROMSYSNAME);
        !           415:                        else
        !           416:                                (void) strncpy(header.from, forgedname, BUFLEN);
        !           417: 
        !           418:                        (void) sprintf(header.sender, "%s@%s",
        !           419:                                username, FROMSYSNAME);
        !           420:                } else {
        !           421:                        gensender(&header, username);
        !           422:                }
        !           423: #ifdef MYORG
        !           424:                if (header.organization[0] == '\0' && !Mflag &&
        !           425:                        header.sender[0] == '\0') {
        !           426:                        strncpy(header.organization, MYORG, BUFLEN);
        !           427:                        if (STRNCMP(header.organization, "Frobozz", 7) == 0)
        !           428:                                header.organization[0] = '\0';
        !           429:                        if (ptr = getenv("ORGANIZATION"))
        !           430:                                strncpy(header.organization, ptr, BUFLEN);
        !           431:                        /*
        !           432:                         * Note that the organization can also be turned off by
        !           433:                         * setting it to the null string, either in MYORG or
        !           434:                         * $ORGANIZATION in the environment.
        !           435:                         */
        !           436:                        if (header.organization[0] == '/') {
        !           437:                                mfd = fopen(header.organization, "r");
        !           438:                                if (mfd) {
        !           439:                                        (void) fgets(header.organization, sizeof header.organization, mfd);
        !           440:                                        (void) fclose(mfd);
        !           441:                                } else {
        !           442:                                        logerr("Couldn't open %s",
        !           443:                                                header.organization);
        !           444:                                        header.organization[0] = '\0';
        !           445:                                }
        !           446:                                ptr = index(header.organization, '\n');
        !           447:                                if (ptr)
        !           448:                                        *ptr = '\0';
        !           449:                        }
        !           450:                }
        !           451: #endif /* MYORG */
        !           452:        }
        !           453: 
        !           454:        /* Authorize newsgroups. */
        !           455:        if (mode == PROC) {
        !           456:                checkbatch();
        !           457:                (void) signal(SIGHUP, SIG_IGN);
        !           458:                (void) signal(SIGINT, SIG_IGN);
        !           459:                (void) signal(SIGQUIT, SIG_IGN);
        !           460:                header.ident[0] = '\0';
        !           461:                if (hread(&header, infp, TRUE) == NULL)
        !           462:                        xerror("%s: Inbound news is garbled", filename);
        !           463:                input(bfr[0] != '\n');
        !           464:        }
        !           465:        /* always check history */
        !           466: 
        !           467:        if (history(&header)) {
        !           468:                log("Duplicate article %s rejected. Path: %s",
        !           469:                        header.ident, header.path);
        !           470:                xxit(0);
        !           471:        }
        !           472: 
        !           473:        /* Easy way to make control messages, since all.all.ctl is unblessed */
        !           474:        if (mode != PROC && PREFIX(header.title, "cmsg ") && header.ctlmsg[0] == 0)
        !           475:                (void) strcpy(header.ctlmsg, &header.title[5]);
        !           476:        is_ctl = mode != CREATENG &&
        !           477:                (ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]);
        !           478: #ifdef DEBUG
        !           479:        fprintf(stderr,"is_ctl set to %d\n", is_ctl);
        !           480: #endif
        !           481: 
        !           482:        if (mode != CREATENG) {
        !           483:                if (!*header.title)
        !           484:                        error("No title, ng %s from %s", header.nbuf,
        !           485:                                header.from);
        !           486:                if (!*header.nbuf)
        !           487:                        (void) strcpy(header.nbuf, DFLTNG);
        !           488:        }
        !           489: 
        !           490:        if (mode <= UNPROC) {
        !           491: #ifdef FASCIST
        !           492:                if (uid && uid != ROOTID && fascist(username, header.nbuf))
        !           493:                        xerror("User %s is not authorized to post to newsgroup %s",
        !           494:                                username, header.nbuf);
        !           495: #endif /* FASCIST */
        !           496:                ctlcheck();
        !           497:        }
        !           498: 
        !           499:        if (mode == CREATENG)
        !           500:                createng();
        !           501: 
        !           502:        /* Determine input. */
        !           503:        if (mode != PROC)
        !           504:                input(FALSE);
        !           505:        if (header.intnumlines == 0 && !is_ctl)
        !           506:                error("%s rejected: no text lines", header.ident);
        !           507: 
        !           508:        dates(&header);
        !           509: 
        !           510:        /* Do the actual insertion. */
        !           511:        insert();
        !           512:        /* NOTREACHED */
        !           513: }
        !           514: 
        !           515: /* check for existence of file */
        !           516: static chkfile(f)
        !           517: char *f;
        !           518: {
        !           519:        FILE    *mfd;           /* mail file file-descriptor            */
        !           520:        char    cbuf[BUFLEN];   /* command buffer                       */
        !           521: 
        !           522:        if (rwaccess(f))
        !           523:                return; /* everything is ok */
        !           524:        mfd = mailhdr((struct hbuf *)NULL,
        !           525:                exists(f) ? "Unwritable files!" : "Missing files!");
        !           526:        if (mfd == NULL)
        !           527:                return;
        !           528:        putc('\n', mfd);
        !           529:        fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n",
        !           530:                LOCALSYSNAME, f);
        !           531:        (void) sprintf(cbuf, "touch %s;chmod 666 %s", f, f);
        !           532:        (void) system(cbuf);
        !           533:        if (rwaccess(f))
        !           534:                fprintf(mfd, "The problem has been taken care of.\n");
        !           535:        else
        !           536:                fprintf(mfd, "Corrective action failed - check suid bits.\n");
        !           537:        (void) mclose(mfd);
        !           538: }
        !           539: 
        !           540: #ifndef DBM
        !           541: /* check for existence of directory */
        !           542: static chkdir(d)
        !           543: char *d;
        !           544: {
        !           545:        FILE    *mfd;           /* mail file file-descriptor            */
        !           546:        char    dir[BUFLEN];    /* holds directory name                 */
        !           547: 
        !           548:        sprintf(dir, "%s.d", d);
        !           549:        if (eaccess(dir, 07) == 0)
        !           550:                return; /* everything is ok */
        !           551:        mfd = mailhdr((struct hbuf *)NULL,
        !           552:                exists(dir) ? "Unwritable directories" : "Missing directories");
        !           553:        if (mfd == NULL)
        !           554:                return;
        !           555:        putc('\n', mfd);
        !           556:        fprintf(mfd, "System: %s\n\nThere was a problem with %s!\n",
        !           557:                LOCALSYSNAME, dir);
        !           558:        (void) mkdir(dir, 0775);
        !           559:        if (eaccess(dir, 07) == 0)
        !           560:                fprintf(mfd, "The problem has been taken care of.\n");
        !           561:        else
        !           562:                fprintf(mfd, "Corrective action failed - check suid bits.\n");
        !           563:        (void) mclose(mfd);
        !           564: }
        !           565: 
        !           566: /*
        !           567:  * This version of access checks against effective uid and effective gid
        !           568:  */
        !           569: eaccess(name, mode)
        !           570: register char *name;
        !           571: register int mode;
        !           572: {      
        !           573:        struct stat statb;
        !           574:        int euserid = geteuid();
        !           575:        int egroupid = getegid();
        !           576: 
        !           577:        if (stat(name, &statb) == 0) {
        !           578:                if (euserid == 0) {
        !           579:                        if ((statb.st_mode&S_IFMT) != S_IFREG || mode != 1)
        !           580:                                return 0;
        !           581:                        /* root needs execute permission for someone */
        !           582:                        mode = (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
        !           583:                }
        !           584:                else if (euserid == statb.st_uid)
        !           585:                        mode <<= 6;
        !           586:                else if (egroupid == statb.st_gid)
        !           587:                        mode <<= 3;
        !           588: #ifdef BSD4_2
        !           589:                /* in BSD4_2 you can be in several groups */
        !           590:                else {
        !           591:                        int groups[NGROUPS];
        !           592:                        register int n;
        !           593:                        n = getgroups(NGROUPS,groups);
        !           594:                        while(--n >= 0) {
        !           595:                                if(groups[n] == statb.st_gid) {
        !           596:                                        mode <<= 3;
        !           597:                                        break;
        !           598:                                }
        !           599:                        }
        !           600:                }
        !           601: #endif /* BSD4_2 */
        !           602: 
        !           603:                if (statb.st_mode & mode)
        !           604:                        return 0;
        !           605:        }
        !           606:        return -1;
        !           607: }
        !           608: #endif /* DBM */
        !           609: 
        !           610: dospool(batchcmd, dolhwrite)
        !           611: char *batchcmd;
        !           612: int dolhwrite;
        !           613: {
        !           614:        register int c;
        !           615:        register FILE *sp;
        !           616:        register struct tm *tp;
        !           617:        time_t t;
        !           618:        char buf[BUFLEN], sfile[BUFLEN];
        !           619:        extern struct tm *gmtime();
        !           620: 
        !           621:        (void) sprintf(sfile, "%s/.spXXXXXX", SPOOL);
        !           622:        sp = xfopen(mktemp(sfile), "w");
        !           623:        if (batchcmd != NULL) {
        !           624:                if (not_here[0] != '\0')
        !           625:                        fprintf(sp, "%s -x %s\n", batchcmd, not_here);
        !           626:                else
        !           627:                        fprintf(sp, "%s\n", batchcmd);
        !           628:        } else
        !           629:                if (not_here[0] != '\0')
        !           630:                        fprintf(sp, "#! inews -x %s -p\n", not_here);
        !           631:        if (dolhwrite)
        !           632:                lhwrite(&header, sp);
        !           633:        while ((c = getc(infp)) != EOF)
        !           634:                putc(c, sp);
        !           635:        fclose(sp);
        !           636: 
        !           637:        (void) time(&t);
        !           638:        tp = gmtime(&t);
        !           639:        /* This file name "has to" be unique  (right?) */
        !           640: #ifdef USG
        !           641:        (void) sprintf(buf, "%s/.rnews/%2.2d%2.2d%2.2d%2.2d%2.2d%x",
        !           642: #else
        !           643: #ifdef VMS
        !           644:        /* Eunice doesn't like dots in directory names */
        !           645:        (void) sprintf(buf, "%s/+rnews/%02d%02d%02d%02d%02d%x",
        !           646: #else /* V7 */
        !           647:        (void) sprintf(buf, "%s/.rnews/%02d%02d%02d%02d%02d%x",
        !           648: #endif /* V7 */
        !           649: #endif /* VMS */
        !           650:                SPOOL,
        !           651:                tp->tm_year, tp->tm_mon+1, tp->tm_mday,
        !           652:                tp->tm_hour, tp->tm_min, getpid());
        !           653: 
        !           654: #ifdef IHCC
        !           655:        log("Spooling %s into %s", header.ident, (rindex(buf,'/') + 1));
        !           656: #endif /* IHCC */
        !           657: 
        !           658:        if (LINK(sfile, buf) < 0) {
        !           659:                char dbuf[BUFLEN];
        !           660: #ifdef VMS
        !           661:                sprintf(dbuf, "%s/+rnews", SPOOL);
        !           662: #else /* !VMS */
        !           663:                sprintf(dbuf, "%s/.rnews", SPOOL);
        !           664: #endif /* !VMS */
        !           665:                if (mkdir(dbuf, 0777&~N_UMASK) < 0)
        !           666:                        xerror("Cannot mkdir %s: %s", dbuf, errmsg(errno));
        !           667:                if (LINK(sfile, buf) < 0) 
        !           668:                        xerror("Cannot link(%s,%s): %s", sfile, buf,
        !           669:                                errmsg(errno));
        !           670:        }
        !           671:        (void) UNLINK(sfile);
        !           672:        xxit(0);
        !           673:        /* NOTREACHED */
        !           674: }
        !           675: 
        !           676: /*
        !           677:  *     Create a newsgroup
        !           678:  */
        !           679: createng()
        !           680: {
        !           681:        register char *cp;
        !           682: 
        !           683:        /*
        !           684:         * Only certain users are allowed to create newsgroups
        !           685:         */
        !           686:        if (uid != ROOTID && uid != duid && uid) {
        !           687:                logerr("Please contact one of the local netnews people");
        !           688:                xerror("to create group \"%s\" for you", header.ctlmsg);
        !           689:        }
        !           690:        if (header.distribution[0] == '\0')
        !           691: #ifdef ORGDISTRIB
        !           692:                strcpy(header.distribution, ORGDISTRIB);
        !           693: #else /* !ORGDISTRIB */
        !           694:                strcpy(header.distribution, "local");
        !           695: #endif /* !ORGDISTRIB */
        !           696: 
        !           697:        (void) strcpy(header.nbuf, header.ctlmsg);
        !           698:        if ((cp=index(header.nbuf, ' ')) != NULL)
        !           699:                *cp = '\0';
        !           700: 
        !           701:        if (header.approved[0] == '\0')
        !           702:                (void) sprintf(header.approved, "%s@%s",
        !           703:                                username, FROMSYSNAME);
        !           704:        (void) sprintf(bfr, "%s/inews -n %s.ctl -c newgroup %s -d %s -a \"%s\"",
        !           705:                LIB, header.nbuf, header.ctlmsg, header.distribution,
        !           706:                header.approved);
        !           707:        if (tty) {
        !           708:                printf("Please type in a paragraph describing the new newsgroup.\n");
        !           709:                printf("End with control D as usual.\n");
        !           710:        }
        !           711:        printf("%s\n", bfr);
        !           712:        (void) fflush(stdout);
        !           713:        (void) system(bfr);
        !           714:        exit(0);
        !           715:        /*NOTREACHED*/
        !           716: }
        !           717: 
        !           718: char firstbufname[BUFLEN];
        !           719: /*
        !           720:  *     Link ARTICLE into dir for ngname and update active file.
        !           721:  */
        !           722: long
        !           723: localize(ngname)
        !           724: char   *ngname;
        !           725: {
        !           726:        char afline[BUFLEN];
        !           727:        long ngsize;
        !           728:        long fpos;
        !           729:        int e;
        !           730:        char *cp;
        !           731: 
        !           732:        lock();
        !           733:        (void) rewind(actfp); clearerr(actfp);
        !           734: 
        !           735:        for(;;) {
        !           736:                fpos = ftell(actfp);
        !           737:                if (fgets(afline, sizeof afline, actfp) == NULL) {
        !           738:                        unlock();
        !           739:                        logerr("Can't find \"%s\" in active file", ngname);
        !           740:                        return FALSE;           /* No such newsgroup locally */
        !           741:                }
        !           742:                if (PREFIX(afline, ngname)) {
        !           743:                        (void) sscanf(afline, "%s %ld", bfr, &ngsize);
        !           744:                        if (STRCMP(bfr, ngname) == 0) {
        !           745:                                if (ngsize < 0 || ngsize > 99998) {
        !           746:                                        logerr("found bad ngsize %ld ng %s, setting to 1", ngsize, bfr);
        !           747:                                        ngsize = 1;
        !           748:                                }
        !           749:                                break;
        !           750:                        }
        !           751:                }
        !           752:        }
        !           753:        for (;;) {
        !           754:                cp = dirname(ngname);
        !           755: 
        !           756:                (void) sprintf(bfr, "%s/%ld", cp, ngsize+1);
        !           757: #ifdef VMS
        !           758:                /*
        !           759:                 * The effect of this code is to store the article in the first
        !           760:                 * newsgroup's directory and to put symbolic links elsewhere.
        !           761:                 * If this is the first group, firstbufname is not yet filled
        !           762:                 * in. It should be portable to other link-less systems.
        !           763:                 * epimass!jbuck
        !           764:                 */
        !           765:                if (firstbufname[0]) {
        !           766:                        if (vmslink(firstbufname, bfr) == 0)
        !           767:                                break;
        !           768:                } else if (rename(ARTICLE, bfr) == 0)
        !           769:                        break;
        !           770: #else /* !VMS */
        !           771:                if (link(ARTICLE, bfr) == 0)
        !           772:                        break;
        !           773: #endif /* !VMS */
        !           774:                if (!exists(cp))
        !           775:                        mknewsg(cp, ngname);
        !           776: #ifdef VMS
        !           777:                if (firstbufname[0]) {
        !           778:                        if (vmslink(firstbufname, bfr) == 0)
        !           779:                                break;
        !           780:                } else if (rename(ARTICLE, bfr) == 0) 
        !           781:                        break;
        !           782: #else /* !VMS */
        !           783:                if (link(ARTICLE, bfr) == 0)
        !           784:                        break;
        !           785: #endif /* !VMS */
        !           786:                e = errno;      /* keep log from clobbering it */
        !           787:                log("Cannot install article as %s: %s", bfr, errmsg(errno));
        !           788:                if (e != EEXIST) {
        !           789:                        logerr("Link into %s failed (%s); check dir permissions.",
        !           790:                            bfr, errmsg(e));
        !           791:                        unlock();
        !           792:                        return FALSE;
        !           793:                }
        !           794:                ngsize++;
        !           795:        }
        !           796: 
        !           797:        /*
        !           798:         * This works around a bug in the 4.1bsd stdio
        !           799:         * on fseeks to non even offsets in r+w files
        !           800:         */
        !           801:        if (fpos&1)
        !           802:                (void) rewind(actfp);
        !           803: 
        !           804:        (void) fseek(actfp, fpos, 0);
        !           805:        /*
        !           806:         * Has to be same size as old because of %05d.
        !           807:         * This will overflow with 99999 articles.
        !           808:         */
        !           809:        fprintf(actfp, "%s %05ld", ngname, ngsize+1);
        !           810: #if defined(USG) || defined(MG1)
        !           811:        /*
        !           812:         * U G L Y   K L U D G E
        !           813:         * This utter piece of tripe is the only way I know of to get
        !           814:         * around the fact that ATT BROKE standard IO in System 5.2.
        !           815:         * Basically, you can't open a file for "r+" and then try and
        !           816:         * write to it. This works on all "real" USGUnix systems, It will
        !           817:         * probably break on some obscure look alike that doesnt use the
        !           818:         * real ATT stdio.h
        !           819:         * Don't blame me, blame ATT. stdio should have already done the
        !           820:         * following line for us, but it doesn't
        !           821:         * also broken in WCW MG-1 42nix 2.0
        !           822:         */
        !           823:         actfp->_flag |= _IOWRT;
        !           824: #endif /* USG */
        !           825:        (void) fflush(actfp);
        !           826:        if (ferror(actfp))
        !           827:                xerror("Active file write failed");
        !           828:        unlock();
        !           829:        if (firstbufname[0] == '\0')
        !           830:                (void) strcpy(firstbufname, bfr);
        !           831:        (void) sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
        !           832:        addhist(bfr);
        !           833:        return ngsize+1;
        !           834: }
        !           835: 
        !           836: /*
        !           837:  *     Localize for each newsgroup and broadcast.
        !           838:  */
        !           839: insert()
        !           840: {
        !           841:        register char *ptr;
        !           842:        register FILE *tfp;
        !           843:        register int c;
        !           844:        struct srec srec;       /* struct for sys file lookup   */
        !           845:        struct tm *tm, *gmtime();
        !           846:        int is_invalid = FALSE;
        !           847:        int exitcode = 0;
        !           848:        long now;
        !           849: #ifdef DOXREFS
        !           850:        register char *nextref = header.xref;
        !           851: #endif /* DOXREFS */
        !           852: 
        !           853:        /* Clean up Newsgroups: line */
        !           854:        if (!is_ctl && mode != CREATENG)
        !           855:                is_invalid = ngfcheck(mode == PROC);
        !           856: 
        !           857:        (void) time(&now);
        !           858:        tm = gmtime(&now);
        !           859:        if (header.expdate[0])
        !           860:                addhist(" ");
        !           861: #ifdef USG
        !           862:        sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t",
        !           863: #else /* !USG */
        !           864:        sprintf(bfr,"%02d/%02d/%d %02d:%02d\t",
        !           865: #endif /* !USG */
        !           866:                tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min);
        !           867:        addhist(bfr);
        !           868:        log("%s %s ng %s subj '%s' from %s", spool_news != DONT_SPOOL
        !           869:                ? "queued" : (mode==PROC ? "received" : "posted"),
        !           870:                header.ident, header.nbuf, header.title, header.from);
        !           871: 
        !           872:        /* Write article to temp file. */
        !           873:        tfp = xfopen(mktemp(ARTICLE), "w");
        !           874: 
        !           875:        if (is_invalid) {
        !           876:                logerr("No valid newsgroups found, moved to junk");
        !           877:                if (localize("junk"))
        !           878:                        savehist(histline);
        !           879:                exitcode = 1;
        !           880:                goto writeout;
        !           881:        }
        !           882: 
        !           883: #ifdef ZAPNOTES
        !           884:        if (STRNCMP(header.title, "Re: Orphaned Response", 21) == 0) {
        !           885:                logerr("Orphaned Response, moved to junk");
        !           886:                if (localize("junk"))
        !           887:                        savehist(histline);
        !           888:                exitcode = 1;
        !           889:                goto writeout;
        !           890:        }
        !           891: #endif /* ZAPNOTES */
        !           892: 
        !           893:        if (time((time_t *)0) > (cgtdate(header.subdate) + HISTEXP) ){
        !           894:                logerr("Article too old, moved to junk");
        !           895:                if (localize("junk"))
        !           896:                        savehist(histline);
        !           897:                exitcode = 1;
        !           898:                goto writeout;
        !           899:        }
        !           900: 
        !           901:        if (is_mod[0] != '\0'   /* one of the groups is moderated */
        !           902:                && header.approved[0] == '\0') { /* and unapproved */
        !           903:                struct hbuf mhdr;
        !           904:                FILE *mfd, *mhopen();
        !           905:                register char *p;
        !           906:                char modadd[BUFLEN], *replyname();
        !           907: #ifdef DONTFOWARD
        !           908:                if(mode == PROC) {
        !           909:                        logerr("Unapproved article in moderated group %s",
        !           910:                                is_mod);
        !           911:                        if (localize("junk"))
        !           912:                                savehist(histline);
        !           913:                        goto writeout;
        !           914:                }
        !           915: #endif /* DONTFORWARD */
        !           916:                fprintf(stderr,"%s is moderated and may not be posted to",
        !           917:                        is_mod);
        !           918:                fprintf(stderr," directly.\nYour article is being mailed to");
        !           919:                fprintf(stderr," the moderator who will post it for you.\n");
        !           920:                /* Let's find a path to the backbone */
        !           921:                sprintf(bfr, "%s/mailpaths", LIB);
        !           922:                mfd = xfopen(bfr, "r");
        !           923:                do {
        !           924:                        if (fscanf(mfd, "%s %s", bfr, modadd) != 2)
        !           925:                                xerror("Can't find backbone in %s/mailpaths",
        !           926:                                        LIB);
        !           927:                } while (STRCMP(bfr, "backbone") != 0 && !ngmatch(is_mod, bfr));
        !           928:                (void) fclose(mfd);
        !           929:                /* fake a header for mailhdr */
        !           930:                mhdr.from[0] = '\0';
        !           931:                mhdr.replyto[0] = '\0';
        !           932:                p = is_mod;
        !           933:                while (*++p)
        !           934:                        if (*p == '.')
        !           935:                                *p = '-';
        !           936:                sprintf(mhdr.path, modadd, is_mod);
        !           937:                mfd = mhopen(&mhdr);
        !           938:                if (mfd == NULL)
        !           939:                        xerror("Can't send mail to %s", mhdr.path);
        !           940:                fprintf(mfd, "To: %s\n", replyname(&mhdr));
        !           941:                lhwrite(&header, mfd);
        !           942:                putc('\n', mfd);
        !           943:                while ((c = getc(infp)) != EOF)
        !           944:                        putc(c, mfd);
        !           945:                mclose(mfd);
        !           946:                log("Article mailed to %s", mhdr.path);
        !           947:                xxit(0);
        !           948:        }
        !           949: 
        !           950:        if (mode != PROC && spool_news != DONT_SPOOL)  {
        !           951:                if (spool_news != EXPIRE_RUNNING
        !           952:                        && ngmatch(header.nbuf,"to.all.ctl"))
        !           953:                                spool_news = DONT_SPOOL;
        !           954:                if (spool_news != DONT_SPOOL) {
        !           955:                        fprintf(stderr,
        !           956:                        "Your article has been spooled for later processing.\n");
        !           957:                        dospool("#! inews -S -h", TRUE);
        !           958:                        /* NOT REACHED */
        !           959:                }
        !           960:        }
        !           961: 
        !           962:        if (is_ctl) {
        !           963:                exitcode = control(&header);
        !           964:                if (localize("control") && exitcode != 0)
        !           965:                        savehist(histline);
        !           966:        } else {
        !           967:                if (s_find(&srec, LOCALPATHSYSNAME) == FALSE) {
        !           968:                        logerr("Cannot find my name '%s' in %s",
        !           969:                                LOCALPATHSYSNAME, SUBFILE);
        !           970:                        srec = dummy_srec;
        !           971:                }
        !           972: #ifdef DOXREFS
        !           973:                (void) strncpy(nextref, PATHSYSNAME, BUFLEN);
        !           974: #endif /* DOXREFS */
        !           975:                for (ptr = nbuf; *ptr;) {
        !           976:                        if (ngmatch(ptr,srec.s_nbuf) || index(ptr,'.') == NULL){
        !           977: #ifdef DOXREFS
        !           978:                                while (*nextref++)
        !           979:                                        ;
        !           980:                                (void) sprintf(--nextref, " %s:%ld", ptr, localize(ptr));
        !           981: #else /* !DOXREFS */
        !           982:                                (void) localize(ptr);
        !           983: #endif /* !DOXREFS */
        !           984:                        }
        !           985:                        while (*ptr++)
        !           986:                                ;
        !           987:                }
        !           988:                if (firstbufname[0] == '\0') {
        !           989:                        logerr("Newsgroups in active, but not sys");
        !           990:                        (void) localize("junk");
        !           991:                }
        !           992:        }
        !           993: #ifdef DOXREFS
        !           994:        if (index(header.nbuf, NGDELIM) == NULL)
        !           995:                header.xref[0] = '\0';
        !           996: #endif /* DOXREFS */
        !           997: 
        !           998: writeout:
        !           999:        /* Part 1 of kludge to get around article truncation problem */
        !          1000:        if ( (c=getc(infp)) != EOF) {
        !          1001:                ungetc(c, infp);
        !          1002:                if (c == ' ' || c == '\t') {
        !          1003:                        header.intnumlines++;
        !          1004:                        (void) sprintf(header.numlines, "%d",
        !          1005:                                header.intnumlines);
        !          1006:                }
        !          1007:        }
        !          1008:        /* End of part 1 */
        !          1009:        if (header.expdate[0] != '\0' && mode != PROC) {
        !          1010:                /* Make sure it's fully qualified */
        !          1011:                long t = cgtdate(header.expdate);
        !          1012:                strcpy(header.expdate, arpadate(&t));
        !          1013:        }
        !          1014: 
        !          1015:        lhwrite(&header, tfp);
        !          1016:        if ((c = getc(infp)) != EOF) {
        !          1017:                /* Part 2 of kludge to get around article truncation problem */
        !          1018:                if (c == ' ' || c == '\t' )
        !          1019:                        putc('\n', tfp);
        !          1020:                /* End of part 2 */
        !          1021:                ungetc(c, infp);
        !          1022:                while (fgets(bfr, BUFLEN, infp) != NULL)
        !          1023:                        fputs(bfr, tfp);
        !          1024:                if (bfr[strlen(bfr)-1] != '\n')
        !          1025:                        putc('\n',tfp);
        !          1026:        }
        !          1027:        if (ferror(tfp))
        !          1028:                xerror("Write failed for temp file");
        !          1029:        (void) fclose(tfp);
        !          1030:        (void) fclose(infp);
        !          1031:        if(exitcode == 0) {
        !          1032:                /* article has passed all the checks, so work in background */
        !          1033:                if (mode != PROC) {
        !          1034:                        int pid;
        !          1035:                        if ((pid=fork()) < 0)
        !          1036:                                xerror("Can't fork");
        !          1037:                        else if (pid > 0)
        !          1038:                                _exit(0);
        !          1039:                }
        !          1040: #ifdef SIGTTOU
        !          1041:                (void) signal(SIGTTOU, SIG_IGN);
        !          1042: #endif /* SIGTTOU */
        !          1043:                savehist(histline);
        !          1044:                if (header.supersedes[0] != '\0') {
        !          1045:                        char *av[2];
        !          1046: 
        !          1047:                        av[0] = "cancel";
        !          1048:                        av[1] = header.supersedes;
        !          1049:                        c_cancel(2, av);
        !          1050:                }
        !          1051:                broadcast(mode==PROC);
        !          1052:        }
        !          1053:        xxit((mode == PROC && filename[0] == '\0') ? 0 :
        !          1054:                (exitcode < 0 ? 0 : exitcode));
        !          1055: }
        !          1056: 
        !          1057: input(usegunk)
        !          1058: {
        !          1059:        register char *cp;
        !          1060:        register int c;
        !          1061:        register int empty = TRUE;
        !          1062:        FILE *tmpfp;
        !          1063:        int consec_newlines = 0;
        !          1064:        int linecount = 0;
        !          1065:        int linserted = 0;
        !          1066: 
        !          1067:        tmpfp = xfopen(mktemp(INFILE), "w");
        !          1068:        for ( ; ; ) {
        !          1069:                if (SigTrap)
        !          1070:                        break;
        !          1071:                if (usegunk)
        !          1072:                        usegunk = FALSE;
        !          1073:                else if (fgets(bfr, BUFLEN, infp) != bfr)
        !          1074:                        break;
        !          1075:                if (mode == PROC) {     /* zap trailing empty lines */
        !          1076: #ifdef ZAPNOTES
        !          1077:                        if (empty && bfr[0] == '#' && bfr[2] == ':'
        !          1078:                                && header.nf_id[0] == '\0'
        !          1079:                                && header.nf_from[0] == '\0' ) {
        !          1080:                                (void) strcpy(header.nf_id, bfr);
        !          1081:                                (void) nstrip(header.nf_id);
        !          1082:                                (void) fgets(bfr, BUFLEN, infp);
        !          1083:                                (void) strcpy(header.nf_from, bfr);
        !          1084:                                (void) nstrip(header.nf_from);
        !          1085:                                (void) fgets(bfr, BUFLEN, infp);
        !          1086: 
        !          1087:                                if (header.numlines[0]) {
        !          1088:                                        header.intnumlines -= 2;
        !          1089:                                        (void) sprintf(header.numlines, "%d", header.intnumlines);
        !          1090:                                }
        !          1091: 
        !          1092:                                /* Strip trailing " - (nf)" */
        !          1093:                                if ((cp = rindex(header.title, '-')) != NULL
        !          1094:                                    && !strcmp(--cp, " - (nf)"))
        !          1095:                                        *cp = '\0';
        !          1096:                                log("Stripped notes header on %s", header.ident);
        !          1097:                                continue;
        !          1098:                        }
        !          1099: #endif /* ZAPNOTES */
        !          1100:                        if (bfr[0] == '\n' ||
        !          1101:                                /* Bandage for older versions of inews */
        !          1102:                                bfr[1] == '\n' && !isascii(bfr[0])) {
        !          1103:                                consec_newlines++;      /* count it, in case */
        !          1104:                                continue;               /* but don't write it*/
        !          1105:                        }
        !          1106:                        /* foo! a non-empty line. write out all saved lines. */
        !          1107:                        while (consec_newlines > 0) {
        !          1108:                                putc('\n', tmpfp);
        !          1109:                                consec_newlines--;
        !          1110:                                linecount++;
        !          1111:                        }
        !          1112:                }
        !          1113:                if (mode != PROC && tty && STRCMP(bfr, ".\n") == 0)
        !          1114:                        break;
        !          1115:                for (cp = bfr; c = toascii(*cp); cp++) {
        !          1116:                        if (isprint(c) || isspace(c) || c == '\b')
        !          1117:                                putc(c, tmpfp);
        !          1118:                        if (c == '\n')
        !          1119:                                linecount++;
        !          1120:                }
        !          1121:                if (bfr[0] == '>')
        !          1122:                        linserted++;
        !          1123:                if (bfr[0] == '<') /* kludge to allow diff's to be posted */
        !          1124:                        linserted--;
        !          1125:                empty = FALSE;
        !          1126:        }
        !          1127:        if (*filename)
        !          1128:                (void) fclose(infp);
        !          1129:        if (mode != PROC &&
        !          1130:                linecount > LNCNT && linserted > (linecount-linserted))
        !          1131:                error("Article rejected: %s included more text than new text",
        !          1132:                        username);
        !          1133: 
        !          1134:        if (mode != PROC && !is_ctl && header.sender[0] == '\0' && !Sflag) {
        !          1135:                int siglines = 0;
        !          1136:                char sbuf[BUFLEN];
        !          1137:                (void) sprintf(bfr, "%s/%s", userhome, ".signature");
        !          1138:                if (access(bfr, 4) == 0) {
        !          1139:                        if ((infp = fopen(bfr, "r")) == NULL) {
        !          1140:                                (void) fprintf(stderr,
        !          1141:     "inews: \"%s\" left off (must be readable by \"inews\" owner)\n", bfr);
        !          1142:                                goto finish;
        !          1143:                        }
        !          1144: 
        !          1145:                        while (fgets(sbuf, sizeof sbuf, infp) != NULL)
        !          1146:                                if (++siglines > 4)
        !          1147:                                        break;
        !          1148:                        if (siglines > 4)
        !          1149:                                fprintf(stderr,".signature not included (> 4 lines)\n");
        !          1150:                        else {
        !          1151:                                rewind(infp);
        !          1152:                                fprintf(tmpfp, "-- \n");        /* To separate */
        !          1153:                                linecount++;
        !          1154:                                while ((c = getc(infp)) != EOF) {
        !          1155:                                        putc(c, tmpfp);
        !          1156:                                        if (c == '\n')
        !          1157:                                                linecount++;
        !          1158:                                }
        !          1159:                        }
        !          1160:                        (void) fclose(infp);
        !          1161:                }
        !          1162:        }
        !          1163: 
        !          1164: finish:
        !          1165:        if (ferror(tmpfp))
        !          1166:                xerror("write failed to temp file");
        !          1167:        (void) fclose(tmpfp);
        !          1168:        if (SigTrap) {
        !          1169:                if (tty)
        !          1170:                        fprintf(stderr, "Interrupt\n");
        !          1171:                if (tty && !empty)
        !          1172:                        fwait(fsubr(newssave, (char *) NULL, (char *) NULL));
        !          1173:                if (!tty)
        !          1174:                        log("Blown away by an interrupt %d", SigTrap);
        !          1175:                xxit(1);
        !          1176:        }
        !          1177:        if (tty)
        !          1178:                fprintf(stderr, "EOT\n");
        !          1179:        fflush(stdout);
        !          1180:        infp = fopen(INFILE, "r");
        !          1181:        if (header.numlines[0]) {
        !          1182:                /*
        !          1183:                 * Check line count if there's already one attached to
        !          1184:                 * the article.  Could make this a fatal error -
        !          1185:                 * throwing it away if it got chopped, in hopes that
        !          1186:                 * another copy will come in later with a correct
        !          1187:                 * line count.  But that seems a bit much for now.
        !          1188:                 */
        !          1189:                if (linecount != header.intnumlines) {
        !          1190:                        if (linecount == 0)
        !          1191:                                error("%s rejected. linecount expected %d, got 0", header.ident, header.intnumlines);
        !          1192:                        if (linecount > header.intnumlines ||
        !          1193:                            linecount+consec_newlines < header.intnumlines)
        !          1194:                                log("linecount expected %d, got %d", header.intnumlines, linecount+consec_newlines);
        !          1195:                }
        !          1196:                /* adjust count for blank lines we stripped off */
        !          1197:                if (consec_newlines) {
        !          1198:                        header.intnumlines -= consec_newlines;
        !          1199:                        if (header.intnumlines < 0 )
        !          1200:                                header.intnumlines = 0; /* paranoia */
        !          1201:                        (void) sprintf(header.numlines, "%d", header.intnumlines);
        !          1202:                }
        !          1203: 
        !          1204:        } else {
        !          1205:                /* Attach a line count to the article. */
        !          1206:                header.intnumlines = linecount;
        !          1207:                (void) sprintf(header.numlines, "%d", linecount);
        !          1208:        }
        !          1209: }
        !          1210: 
        !          1211: /*
        !          1212:  * Make the directory for a new newsgroup.  ngname should be the
        !          1213:  * full pathname of the directory.  Do the other stuff too.
        !          1214:  * The various games with setuid and chown are to try to make sure
        !          1215:  * the directory is owned by NEWSUSR and NEWSGRP, which is tough to
        !          1216:  * do if you aren't root.  This will work on a UCB system (which allows
        !          1217:  * setuid(geteuid()) or a USG system (which allows you to give away files
        !          1218:  * you own with chown), otherwise you have to change your kernel to allow
        !          1219:  * one of these things or run with your dirs 777 so that it doesn't matter
        !          1220:  * who owns them.
        !          1221:  */
        !          1222: mknewsg(fulldir, ngname)
        !          1223: char   *fulldir;
        !          1224: char   *ngname;
        !          1225: {
        !          1226: #ifdef USG
        !          1227:        register char *p;
        !          1228:        char parent[200];
        !          1229:        char sysbuf[200];
        !          1230:        struct stat sbuf;
        !          1231: #endif /* USG */
        !          1232: 
        !          1233:        if (ngname == NULL || !isalpha(ngname[0]))
        !          1234:                xerror("Tried to make illegal newsgroup %s", ngname);
        !          1235: 
        !          1236: #ifdef USG
        !          1237:        /*
        !          1238:         * If the parent is 755 the setuid(getuid)
        !          1239:         * will fail, and since mkdir is suid, and our real uid is random,
        !          1240:         * the mkdir will fail.  So we have to temporarily chmod it to 777.
        !          1241:         */
        !          1242:        (void) strcpy(parent, fulldir);
        !          1243:        while (p = rindex(parent, '/')) {
        !          1244:                *p = '\0';
        !          1245:                if (stat(parent, &sbuf) == 0) {
        !          1246:                        (void) chmod(parent, 0777);
        !          1247:                        break;
        !          1248:                }
        !          1249:        }
        !          1250: #endif /* USG */
        !          1251: 
        !          1252:        /* Create the directory */
        !          1253:        mkparents(fulldir);
        !          1254:        if (mkdir(fulldir, 0777) < 0)
        !          1255:                xerror("Cannot mkdir %s: %s", fulldir, errmsg(errno));
        !          1256: 
        !          1257: #ifdef USG
        !          1258:        /*
        !          1259:         * Give away the directories we just created which were assigned
        !          1260:         * our real uid.
        !          1261:         */
        !          1262:        (void) setuid(uid);
        !          1263:        (void) chown(fulldir, duid, dgid);
        !          1264: 
        !          1265:        (void) strcpy(sysbuf, fulldir);
        !          1266:        while (p = rindex(sysbuf, '/')) {
        !          1267:                *p = '\0';
        !          1268:                /* stop when get to last known good parent */
        !          1269:                if (strcmp(sysbuf, parent) == 0)
        !          1270:                        break;
        !          1271:                (void) chown(sysbuf, duid, dgid);
        !          1272:        }
        !          1273:        (void) setuid(duid);
        !          1274:        (void) chmod(parent, (int)sbuf.st_mode);        /* put it back */
        !          1275: #endif /* USG */
        !          1276: 
        !          1277:        log("make newsgroup %s in dir %s", ngname, fulldir);
        !          1278: }
        !          1279: 
        !          1280: /*
        !          1281:  * If any parent directories of this dir don't exist, create them.
        !          1282:  */
        !          1283: mkparents(dname)
        !          1284: char *dname;
        !          1285: {
        !          1286:        char buf[200];
        !          1287:        register char *p;
        !          1288: 
        !          1289:        (void) strcpy(buf, dname);
        !          1290:        p = rindex(buf, '/');
        !          1291:        if (p)
        !          1292:                *p = '\0';
        !          1293:        if (exists(buf))
        !          1294:                return;
        !          1295:        mkparents(buf);
        !          1296:        if (mkdir(buf, 0777) < 0)
        !          1297:                xerror("Can not mkdir %s: %s", buf, errmsg(errno));
        !          1298: }
        !          1299: 
        !          1300: dounspool()
        !          1301: {
        !          1302:        register DIR    *dirp;
        !          1303:        register struct direct *dir;
        !          1304:        register int foundsome;
        !          1305:        int pid, status, ret;
        !          1306:        char spbuf[BUFLEN];
        !          1307: #ifdef LOCKF
        !          1308:        FILE* LockFd;
        !          1309: #endif /* LOCKF */
        !          1310: #ifdef VMS
        !          1311:        sprintf(spbuf, "%s/+rnews", SPOOL);
        !          1312: #else /* !VMS */
        !          1313:        sprintf(spbuf, "%s/.rnews", SPOOL);
        !          1314: #endif /* !VMS */
        !          1315: 
        !          1316:        if (chdir(spbuf) < 0)
        !          1317:                xerror("chdir(%s):%s", spbuf, errmsg(errno));
        !          1318: 
        !          1319:        dirp = opendir(".");
        !          1320:        if (dirp == NULL)       /* Boy are things screwed up */
        !          1321:                xerror("opendir can't open .:%s", errmsg(errno));
        !          1322: #ifdef LOCKF
        !          1323:        LockFd = xfopen(SEQFILE, "r+w");
        !          1324:        if (lockf(fileno(LockFd), F_TLOCK, 0L) < 0) {
        !          1325:                if (errno != EAGAIN && errno != EACCES)
        !          1326: #else  /* !LOCKF */
        !          1327: #ifdef BSD4_2
        !          1328:        if (flock(dirp->dd_fd, LOCK_EX|LOCK_NB) < 0) {
        !          1329:                if (errno != EWOULDBLOCK)
        !          1330: #else  /* V7 */
        !          1331:        strcat(spbuf, ".lock");
        !          1332:        sprintf(bfr, "%s.tmp", spbuf);
        !          1333:        (void) close(creat(bfr, 0666));
        !          1334:        ret = LINK(bfr, spbuf);
        !          1335:        status = errno;
        !          1336:        (void) UNLINK(bfr);
        !          1337:        errno = status;
        !          1338:        if (ret < 0) {
        !          1339:                if (errno != EEXIST)
        !          1340: #endif /* V7 */
        !          1341: #endif /* !LOCKF */
        !          1342:                        xerror("Can't lock %s: %s", spbuf, errmsg(errno));
        !          1343:                xxit(3); /* another rnews -U is running */
        !          1344:        }
        !          1345: 
        !          1346:        do {
        !          1347:                foundsome = 0;
        !          1348: 
        !          1349:                while ((dir=readdir(dirp)) != NULL) {
        !          1350:                        if (dir->d_name[0] == '.')
        !          1351:                                continue;
        !          1352: 
        !          1353: #ifdef IHCC
        !          1354:                        log("Unspooling from %s", dir->d_name);
        !          1355: #endif /* IHCC */
        !          1356: 
        !          1357:                        if ((pid=vfork()) == -1)
        !          1358:                                xerror("Can't fork: %s", errmsg(errno));
        !          1359:                        if (pid == 0) {
        !          1360: #ifdef LOGDIR
        !          1361:                                char bufr[BUFSIZ];
        !          1362:                                sprintf(bufr, "%s/%s", logdir(HOME), RNEWS);
        !          1363:                                execl(bufr, "rnews", "-S", "-p", dir->d_name,
        !          1364:                                        (char *) NULL);
        !          1365: #else /* !LOGDIR */
        !          1366:                                execl(RNEWS, "rnews", "-S", "-p", dir->d_name,
        !          1367:                                        (char *) NULL);
        !          1368: #endif /* !LOGDIR */
        !          1369:                                _exit(1);
        !          1370:                        }
        !          1371:                        
        !          1372:                        while ((ret=wait(&status)) != pid && ret != -1)
        !          1373:                                /* continue */;
        !          1374: 
        !          1375:                        if (((status>>8)&0177) == 42) {
        !          1376:                                /* expire has started up, shutdown rnews -U */
        !          1377:                                break;
        !          1378:                        }
        !          1379: 
        !          1380:                        if (status != 0) {
        !          1381:                                sprintf(bfr, "../%s", dir->d_name);
        !          1382:                                (void) LINK(dir->d_name, bfr);
        !          1383:                                logerr("rnews failed, status %ld. Batch saved in %s/%s",
        !          1384:                                        (long)status, SPOOL, dir->d_name);
        !          1385:                        }
        !          1386:                        (void) unlink(dir->d_name);
        !          1387:                        foundsome++;
        !          1388:                }
        !          1389:                rewinddir(dirp);
        !          1390:        } while (foundsome); /* keep rereading the directory until it's empty */
        !          1391: #ifndef LOCKF
        !          1392: #ifndef BSD4_2
        !          1393:        (void) UNLINK(spbuf);
        !          1394: #endif
        !          1395: #endif
        !          1396: 
        !          1397:        xxit(0);
        !          1398: }

unix.superglobalmegacorp.com

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