Annotation of 43BSDTahoe/new/news/src/control.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * This software is Copyright (c) 1986 by Rick Adams.
                      3:  *
                      4:  * Permission is hereby granted to copy, reproduce, redistribute or
                      5:  * otherwise use this software as long as: there is no monetary
                      6:  * profit gained specifically from the use or reproduction or this
                      7:  * software, it is not sold, rented, traded or otherwise marketed, and
                      8:  * this copyright notice is included prominently in any copy
                      9:  * made.
                     10:  *
                     11:  * The author make no claims as to the fitness or correctness of
                     12:  * this software for any use whatsoever, and it is provided as is. 
                     13:  * Any use of this software is at the user's own risk.
                     14:  *
                     15:  * Control message handling code.  Deal with messages which are to be
                     16:  * acted on by netnews itself rather than by people.
                     17:  *
                     18:  * See defs.h "news_version" for the real version of netnews.
                     19:  */
                     20: 
                     21: #ifdef SCCSID
                     22: static char    *SccsId = "@(#)control.c        2.55    10/7/87";
                     23: #endif /* SCCSID */
                     24: 
                     25: #include "iparams.h"
                     26: 
                     27: #define eq(msg) (msg[0] == cargv[0][0] && strcmp(msg, cargv[0]) == 0)
                     28: 
                     29: int cargc;
                     30: char **cargv;
                     31: 
                     32: FILE *hfopen();
                     33: FILE *popen(), *mhopen(), *mailhdr();
                     34: 
                     35: #define NCARGS 30
                     36: char *senderof();
                     37: #ifdef u370
                     38: static struct hbuf htmp;
                     39: #endif /* u370 */
                     40: 
                     41: /*
                     42:  * The global structure is initialized to NOTIFY as the default (if defined)
                     43:  * uid to send mail to for every state.  The following conditions are
                     44:  * dealt with (assumes NOTIFY defined):
                     45:  *
                     46:  * 1) LIB/notify exists and is empty (or contains no recognizable control
                     47:  *    message types).
                     48:  *     Action: force TELLME = "";
                     49:  * 2) LIB/notify contains the control message name "all" and no associated
                     50:  *    address.
                     51:  *     Action: force TELLME = "";
                     52:  * 3) LIB/notify contains the control message name "all" and has an address.
                     53:  *     Action: set TELLME = AlloCpy(address);
                     54:  * 4) LIB/notify contains only some of the known control message types.
                     55:  *     Action: initialize all addresses to "" and set declared addresses
                     56:  *             to listed address.
                     57:  */
                     58: 
                     59: 
                     60: control(h)
                     61: struct hbuf *h;
                     62: {
                     63:        register char *ctlmsgtext;
                     64:        register struct msgtype *mp;
                     65: 
                     66:        if (strncmp(h->title, "cmsg ", 5) == 0) {
                     67:                register char *cp1, *cp2;
                     68:                cp1 = h->title;
                     69:                cp2 = h->title + 5;
                     70:                while (*cp1++ = *cp2++)
                     71:                        ;
                     72:        }
                     73: 
                     74:        if (*h->ctlmsg)
                     75:                ctlmsgtext = h->ctlmsg;
                     76:        else
                     77:                ctlmsgtext = h->title;
                     78:        log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext);
                     79:        /*
                     80:         * Control messages have the standard format
                     81:         *      command [args]
                     82:         * much like shell commands.  Each site has the option
                     83:         * of customizing this code to deal with control messages
                     84:         * as they see fit, but we would like to buy back the
                     85:         * code, ifdeffed or otherwise parameterized, to simplify
                     86:         * the maintenence issues.
                     87:         */
                     88:        argparse(ctlmsgtext);
                     89:        
                     90:        /*
                     91:         * We look for a match of the control message name and then
                     92:         * set TELLME to the value parsed from the LIB/notify file
                     93:         * (if any).
                     94:         */
                     95:        for(mp=msgtype; mp->m_name; mp++) {
                     96:                if(eq(mp->m_name) ) {           /* hit */
                     97: #ifdef NOTIFY
                     98:                        TELLME = mp->m_who_to;  /* reset whom to tell */
                     99: #endif /* NOTIFY */
                    100:                        return (*mp->m_func)(cargc, cargv); /* do it */
                    101:                }
                    102:        }
                    103:        if( !mp->m_name ) {
                    104: #ifdef NOTIFY
                    105:                TELLME = NOTIFY;
                    106: #endif /* NOTIFY */
                    107:                c_unknown(h, ctlmsgtext);
                    108:        }
                    109:        return 0;
                    110: }
                    111: 
                    112: /*
                    113:  * Parse the string str into separate words in cargc and cargv
                    114:  * as per the usual UNIX convention.  Nothing fancy here, just
                    115:  * blanks and tabs separating words.
                    116:  */
                    117: argparse(str)
                    118: char *str;
                    119: {
                    120:        static char *cavpbuf[NCARGS];
                    121:        static char cavbuf[256];
                    122:        char *nextfree = cavbuf;
                    123: 
                    124:        if (str == '\0')
                    125:                error("Control message %s has no title", header.ident);
                    126:        cargc = (*str != '\0');
                    127:        cargv = cavpbuf;
                    128:        cargv[0] = cavbuf;
                    129: 
                    130:        while (*str) {
                    131:                if (*str <= ' ') {
                    132:                        /* skip over white space */
                    133:                        while (*str != '\0' && *str <= ' ')
                    134:                                str++;
                    135:                        if (*str == '\0')       /* line ends in white space */
                    136:                                return;
                    137:                        *nextfree++ = 0;
                    138:                        cargv[cargc] = nextfree;
                    139:                        if (cargc++ >= NCARGS)
                    140:                                xerror("Too many arguments to control message %s",
                    141:                                                header.ident);
                    142:                } else
                    143:                        *nextfree++ = *str++;
                    144:        }
                    145: }
                    146: 
                    147: /*
                    148:  * ihave <artid> ... <remotesys>
                    149:  *     or
                    150:  * ihave <remotesys>
                    151:  *     with <artid>s in message body.
                    152:  *
                    153:  * The other system is telling you it has article <artid>, in case
                    154:  * you decide you want it to transmit it to you.
                    155:  * The assumption is that the other system only tells you about articles
                    156:  * in newsgroups you subscribe to.
                    157:  *
                    158:  * We turn the incoming ihave into an outgoing sendme on the fly.
                    159:  * It then gets saved in the SPOOL directory and transmitted to the
                    160:  * remote system.  (This way the sendme messages can be batched.)
                    161:  */
                    162: c_ihave(argc, argv)
                    163: register char **       argv;
                    164: {
                    165:        register int    i;
                    166:        char            list[sizeof header.title];
                    167:        extern char *   findhist();
                    168:        extern char *   mydomain();
                    169: 
                    170:        if (argc < 2)
                    171:                error("ihave: Too few arguments.");
                    172:        if (strncmp(PATHSYSNAME, argv[argc - 1], SNLN) == 0)
                    173:                return 0;
                    174:        list[0] = '\0';
                    175:        if (argc > 2) {
                    176:                for (i = 1; i < (argc - 1); ++i)
                    177:                        if (findhist(argv[i]) == NULL) {
                    178:                                (void) strcat(list, " ");
                    179:                                (void) strcat(list, argv[i]);
                    180:                        }
                    181:                if (list[0] == '\0')
                    182:                        return 0;
                    183:        } else {
                    184:                register FILE * outfp;
                    185:                register long   outpos, inpos;
                    186:                char            myid[256];
                    187: 
                    188:                outfp = xfopen(INFILE, "a");
                    189:                outpos = ftell(outfp);
                    190:                inpos = ftell(infp);
                    191:                while (ftell(infp) < outpos) {
                    192:                        if (fgets(myid, sizeof myid, infp) != myid)
                    193:                                error("iline: Can't reread article");
                    194:                        myid[strlen(myid) - 1] = '\0';
                    195:                        if (findhist(myid) == NULL)
                    196:                                (void) fprintf(outfp, "%s\n", myid);
                    197:                }
                    198:                if (outpos == ftell(outfp)) {   /* if nothing is wanted */
                    199:                        (void) fclose(outfp);
                    200:                        (void) fseek(infp, inpos, 0);
                    201:                        return 0;
                    202:                }
                    203:                (void) fclose(outfp);
                    204:                /*
                    205:                ** The close and open may just be paranoia.
                    206:                */
                    207:                (void) fclose(infp);
                    208:                infp = xfopen(INFILE, "r");
                    209:                (void) fseek(infp, outpos, 0);
                    210:        }
                    211:        /*
                    212:        ** Turn the ihave into a sendme.
                    213:        */
                    214:        (void) sprintf(header.nbuf, "to.%s.ctl", argv[argc - 1]);
                    215:        (void) sprintf(header.title, "sendme%s %s", list, PATHSYSNAME);
                    216:        (void) strcpy(header.ctlmsg, header.title);
                    217:        getident(&header);
                    218:        (void) sprintf(header.from, "%s@%s", "usenet", FROMSYSNAME);
                    219:        (void) strcpy(header.path, NEWSUSR);
                    220:        header.subdate[0] = header.expdate[0] = '\0';
                    221:        dates(&header);
                    222:        /*
                    223:        ** What else of this kind should be done?
                    224:        */
                    225:        header.organization[0] = header.distribution[0] = '\0';
                    226:        header.numlines[0] = '\0';
                    227:        for (i = 0; i < NUNREC && header.unrec[i] != NULL; ++i) {
                    228:                free(header.unrec[i]);
                    229:                header.unrec[i] = NULL;
                    230:        }
                    231:        /*
                    232:        ** Note that we do *not* change the history line
                    233:        ** so that if the "ihave" message comes in again it gets rejected.
                    234:        */
                    235:        return 0;
                    236: }
                    237: 
                    238: /*
                    239:  * sendme <artid> ... <remotesys>
                    240:  *     or
                    241:  * sendme <remotesys>
                    242:  *     with <artid>s in message body.
                    243:  * The other system wants me to send out article <artid>.
                    244:  * Give it to them with no fuss.
                    245:  */
                    246: #ifdef MULTICAST
                    247: static int     c_mc;
                    248: static char ** c_sysnames;
                    249: #endif /* MULTICAST */
                    250: c_sendme(argc, argv)
                    251: register char **argv;
                    252: {
                    253:        struct srec     srec;
                    254: 
                    255:        if (argc < 2)
                    256:                error("sendme: Too few arguments.");
                    257:        if (strncmp(PATHSYSNAME, argv[argc - 1], SNLN) == 0)
                    258:                return 0;
                    259:        if (s_find(&srec, argv[argc - 1]) != TRUE)
                    260:                error("sendme: Can't find sys record for %s", argv[argc - 1]);
                    261: #ifdef MULTICAST
                    262:        c_mc = index(srec.s_flags, 'M') != 0;
                    263:        if (c_mc) {
                    264:                struct srec     trec;
                    265: 
                    266:                c_sysnames = &argv[argc - 1];
                    267:                if (s_find(&trec, srec.s_xmit) != TRUE)
                    268:                        error("sendme: Can't find sys record for %s for %s",
                    269:                                srec.s_xmit, argv[argc - 1]);
                    270:                srec = trec;
                    271:        } else  c_sysnames = NULL;
                    272: #endif /* MULTICAST */
                    273:        /* Send the articles. */
                    274:        if (argc == 2) {
                    275:                register FILE * fp;
                    276:                char            buf[256];
                    277: 
                    278:                fp = xfopen(INFILE, "r");
                    279:                while (fgets(buf, sizeof buf, fp) == buf) {
                    280:                        buf[strlen(buf) - 1] = '\0';    /* zap trailing '\n' */
                    281:                        sendmefunc(buf, &srec);
                    282:                }
                    283:                (void) fclose(fp);
                    284:        } else {        /* argc > 2 */
                    285:                register int    i;
                    286: 
                    287:                for (i = 1; i < (argc - 1); ++i)
                    288:                        sendmefunc(argv[i], &srec);
                    289:        }
                    290:        return 0;
                    291: }
                    292: 
                    293: static
                    294: sendmefunc(id, sp)
                    295: register char *                id;
                    296: register struct srec * sp;
                    297: {
                    298:        register FILE * fp;
                    299:        register char * cp;
                    300:        char            savedbufname[256];
                    301:        extern char     firstbufname[];
                    302:        extern char *   dirname();
                    303:        extern char *   findfname();
                    304: 
                    305:        cp = findfname(id);
                    306:        if (cp == NULL) {
                    307:                log("System %s wants unavailable article %s.",
                    308: #ifdef MULTICAST
                    309:                        (c_mc ? c_sysnames[0] : sp->s_name), id);
                    310: #else /* !MULTICAST */
                    311:                        sp->s_name, id);
                    312: #endif /* !MULTICAST */
                    313:                return;
                    314:        }
                    315:        cp = dirname(cp);
                    316:        fp = fopen(cp, "r");
                    317:        if (fp == NULL) {
                    318:                logerr("Article %s unopenable as %s.", id, cp);
                    319:                return;
                    320:        }
                    321:        (void) strcpy(savedbufname, firstbufname);
                    322:        (void) strcpy(firstbufname, cp);
                    323: #ifdef MULTICAST
                    324:        transmit(sp, fp, FALSE, c_sysnames, c_mc);
                    325: #else /* !MULTICAST */
                    326:        transmit(sp, fp, FALSE, (char **) NULL, 0);
                    327: #endif /* !MULTICAST */
                    328:        /* transmit closes fp */
                    329:        (void) strcpy(firstbufname, savedbufname);
                    330: }
                    331: 
                    332: /*
                    333:  * newgroup <groupname>
                    334:  * A new newsgroup has been created.
                    335:  * The body of the article, if present, is a description of the
                    336:  * purpose of the newsgroup.
                    337:  *
                    338:  */
                    339: c_newgroup(argc, argv)
                    340: char **argv;
                    341: {
                    342:        FILE *fd;
                    343:        char abuf[BUFLEN], subjline[BUFLEN];
                    344:        int didcreate = 0;
                    345:        register char *p, *q;
                    346: # ifdef NONEWGROUPS
                    347: #  ifdef ORGDISTRIB
                    348:        /* local or ORGDISTRIB */
                    349:        int can_change = (strcmp(header.distribution, "local") == 0) ||
                    350:                                (strcmp(header.distribution, ORGDISTRIB) == 0);
                    351: #  else /* ! ORGDISTRIB */
                    352:        /* local only */
                    353:        int can_change = strcmp(header.distribution, "local") == 0;
                    354: #  endif /* ORGDISTRIB */
                    355: # else /* ! NONEWGROUPS */
                    356:        int can_change = 1;     /* allow changes for all distributions */
                    357: # endif /* NONEWGROUPS */
                    358: 
                    359:        if (argc < 2)
                    360:                error("newgroup: Too few arguments.");
                    361: 
                    362:        if (header.approved[0] == '\0') {
                    363:                logerr("newgroup: %s not approved", argv[1]);
                    364:                return 1;
                    365:        }
                    366: 
                    367:        lock();
                    368:        /* see if it already exists */
                    369:        (void) rewind(actfp); clearerr(actfp);
                    370:        while(fgets(abuf, BUFLEN, actfp) != NULL) {
                    371:                p = abuf;
                    372:                q = argv[1];
                    373:                while (*p++ == *q++)
                    374:                        ;
                    375:                if (*--q == '\0' && *--p == ' ') {
                    376:                        /* Now check if it's correctly moderated/unmoderated */
                    377:                        while (*p++)
                    378:                                ;
                    379:                        p -= 3;
                    380:                        if (argc > 2 && strcmp(argv[2], "moderated") == 0) {
                    381:                                if (*p == 'm') {
                    382:                                        unlock();
                    383:                                        return 0;
                    384:                                }
                    385:                                *p = 'm';
                    386:                        } else {
                    387:                                if (*p != 'm') {
                    388:                                        unlock();
                    389:                                        return 0;
                    390:                                }
                    391:                                *p = 'y';
                    392:                        }
                    393: # ifdef NOTIFY
                    394:                        (void) sprintf(subjline,
                    395:                        "Newsgroup %s changed from %smoderated to %smoderated",
                    396:                                argv[1], *p=='y' ? "" : "un",
                    397:                                *p=='y' ? "un" : "");
                    398:                        fd = mailhdr((struct hbuf *)NULL, subjline);
                    399:                        if (fd != NULL) {
                    400:                                if(can_change)
                    401:                                        fprintf(fd,
                    402: "%s has been changed from %smoderated to %smoderated as requested by\n%s\n",
                    403:                                                argv[1], *p=='y' ? "" : "un", 
                    404:                                                *p=='y' ? "un":"", header.path);
                    405:                                else {
                    406:                                        fprintf(fd,
                    407: "%s\nhas requested that %s be changed from %smoderated to %smoderated\n",
                    408:                                                header.path, argv[1], 
                    409:                                                *p=='y' ? "" : "un",
                    410:                                                *p=='y' ? "un" : "");
                    411: #ifdef ORGDISTRIB
                    412:                                        fprintf(fd,
                    413: "You can accomplish this by re-creating the newsgroup with a distribution\n");
                    414:                                        fprintf(fd,
                    415: "of '%s' by executing the command:\n", ORGDISTRIB);
                    416:                                        fprintf(fd,
                    417:                                "%s/inews -d %s -C %s%s\n",
                    418:                                                LIB, ORGDISTRIB, argv[1],
                    419:                                                *p=='y' ? "" : " moderated");
                    420: #else /* !ORGDISTRIB */
                    421:                                        fprintf(fd,
                    422: "You can accomplish this by re-creating the newsgroup by executing the command:\n");
                    423:                                        fprintf(fd, "%s/inews -C %s%s\n",
                    424:                                                LIB, argv[1],
                    425:                                                *p=='y' ? "" : " moderated");
                    426: #endif /* !ORGDISTRIB */
                    427:                                }
                    428:                                (void) mclose(fd);
                    429:                        }
                    430: # endif /* NOTIFY */
                    431: # ifdef NONEWGROUPS
                    432:                        /*
                    433:                         * No permission to change
                    434:                         */
                    435:                        if(!can_change) {
                    436:                                unlock();
                    437:                                return 0;
                    438:                        }
                    439: # endif /* NONEWGROUPS */
                    440:                        /* The active file was wrong about the state of the
                    441:                         * group. Rewrite the active file
                    442:                         */
                    443:                        (void) fseek(actfp, -2L, 1); /* back up 2 characters */
                    444:                        putc(*p, actfp);
                    445:                        fflush(actfp);
                    446:                        if (*p != 'm')
                    447:                                logerr("Newsgroup %s changed from moderated to unmoderated",
                    448:                                argv[1]);
                    449:                        else
                    450:                                logerr("Newsgroup %s changed from unmoderated to moderated",
                    451:                                argv[1]);
                    452:                        unlock();
                    453:                        return 0;
                    454:                }
                    455:        }
                    456: 
                    457:        /* It doesn't already exist, we must create it */
                    458: 
                    459:        if(can_change) {
                    460:                didcreate++;
                    461:                (void) fseek(actfp, 0L, 2); clearerr(actfp);
                    462:                fprintf(actfp, "%s 00000 00001 %c\n", argv[1],
                    463:                        (argc > 2 && strcmp(argv[2], "moderated") == 0) 
                    464:                                ? 'm' : 'y');
                    465: #if defined(USG) || defined(MG1)
                    466:                /*
                    467:                 * U G L Y   K L U D G E
                    468:                 * This utter piece of tripe is the only way I know of
                    469:                 * to get around the fact that ATT BROKE standard IO
                    470:                 * in System 5.2. Basically, you can't open a file for
                    471:                 * "r+" and then try and write to it. This hack works
                    472:                 * on all "real" USG Unix systems, It will probably
                    473:                 * break on some obscure look alike that doesnt use the
                    474:                 * real ATT stdio.h
                    475:                 * also broken in WCW MG-1 42nix 2.0
                    476:                 * Don't blame me, blame ATT. stdio should have
                    477:                 * already done the following line for us, but it didn't
                    478:                 */
                    479:                actfp->_flag |= _IOWRT;
                    480: #endif /* USG */
                    481:                fflush(actfp);
                    482:        }
                    483: 
                    484: # ifdef NOTIFY
                    485:        (void) sprintf(subjline, "Newsgroup %s created", argv[1]);
                    486:        fd = mailhdr((struct hbuf *)NULL, subjline);
                    487:        if (fd != NULL) {
                    488:                if (didcreate) 
                    489:                        fprintf(fd, 
                    490:                "A new %snewsgroup called '%s' has been created by %s.\n",
                    491:                                argc > 2 ? "moderated " : "", argv[1],
                    492:                                header.path);
                    493:                else {
                    494:                        fprintf(fd, 
                    495:                "%s requested that a new %snewsgroup called '%s' be created.\n",
                    496:                        header.path, argc > 2 ? "moderated " : "", argv[1]);
                    497:                        fprintf(fd,"It was approved by %s\n\n",header.approved);
                    498:                        fprintf(fd, 
                    499:                "You can accomplish this by creating the newgroup yourself\n");
                    500: #  ifdef ORGDISTRIB
                    501:                        fprintf(fd,"with a distribution of '%s'.\n",
                    502:                                ORGDISTRIB);
                    503:                        fprintf(fd,
                    504:                                "In other words, by executing the command:\n");
                    505:                        fprintf(fd, "%s/inews -d %s -C %s %s\n", LIB, 
                    506:                                ORGDISTRIB, argv[1], argc > 2 ? argv[2] : "");
                    507: #  else /* !ORGDISTRIB */
                    508:                        fprintf(fd, "In other words, by executing the command:\n");
                    509:                        fprintf(fd, "%s/inews -C %s %s\n", LIB, argv[1],
                    510:                                argc > 2 ? argv[2] : "");
                    511: #  endif /* !ORGDISTRIB */
                    512:                }
                    513:                (void) mclose(fd);
                    514:        }
                    515: # endif /* NOTIFY */
                    516:        unlock();
                    517:        return 0;
                    518: }
                    519: 
                    520: /*
                    521:  * rmgroup <groupname>
                    522:  * An old newsgroup is being cancelled on a network wide basis.
                    523:  */
                    524: c_rmgroup(argc, argv)
                    525: char **argv;
                    526: {
                    527:        FILE *fd;
                    528:        int shouldremove = 0;
                    529: #ifdef NOTIFY
                    530:        char subjline[BUFLEN];
                    531: #endif /* NOTIFY */
                    532: 
                    533:        if (argc < 2)
                    534:                error("rmgroup: Too few arguments.");
                    535:        if (!validng(argv[1]))
                    536:                return 0;
                    537:        if (header.approved[0] == '\0') {
                    538:                logerr("rmgroup: %s not approved", argv[1]);
                    539:                return 1;
                    540:        }
                    541: 
                    542: #ifdef MANUALLY
                    543: #ifdef ORGDISTRIB
                    544:        /*
                    545:         * Allow local as well as organizational removals
                    546:         */
                    547:        if (!strcmp(ORGDISTRIB, header.distribution)
                    548:           || !strcmp("local", header.distribution))
                    549: #else  /* !ORGDISTRIB */               
                    550:        if (!strcmp("local", header.distribution))
                    551: #endif /* !ORGDISTRIB */               
                    552: #endif /* MANUALLY */
                    553:                shouldremove++;
                    554: #ifdef NOTIFY
                    555:        sprintf(subjline, "Received rmgroup for %s", argv[1]);
                    556:        fd = mailhdr((struct hbuf *)NULL, subjline);
                    557:        if (fd != NULL) {
                    558:                if (shouldremove) {
                    559:                    fprintf(fd, "Newsgroup '%s' has been removed by %s.\n\n",
                    560:                                argv[1], header.path);
                    561: #  ifdef USG
                    562:                    fprintf(fd, "You may need to remove the directory %s by hand\n",
                    563:                                dirname(argv[1]));
                    564: #  endif
                    565:                } else {
                    566:                    fprintf(fd, "%s requested that newsgroup %s be removed.\n",
                    567:                                header.path, argv[1]);
                    568:                    fprintf(fd, "You should remove it by hand\n");
                    569:                    fprintf(fd, "To do this, execute the command\n");
                    570:                    fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]);
                    571:                }
                    572:                (void) mclose(fd);
                    573:        }
                    574: #endif /* NOTIFY */
                    575: 
                    576:        if (shouldremove) {
                    577:                int pid, status;
                    578:                /* We let the shell do all the work.
                    579:                 * See the rmgrp shell script.
                    580:                 */
                    581:                lock();
                    582:                (void) sprintf(bfr, "%s/rmgroup", LIB);
                    583: 
                    584:                if (pid = fork()) {
                    585:                        status = fwait(pid);
                    586:                } else {
                    587:                        register int i;
                    588:                        for (i =3; i<20; i++)
                    589:                                if (close(i) < 0)
                    590:                                        break;
                    591:                        (void) setuid(duid);
                    592:                        execvp(bfr, argv);
                    593:                }
                    594:                unlock();
                    595:                if (status)
                    596:                        log("rmgroup status %d", status);
                    597:        }
                    598:        return 0;
                    599: }
                    600: 
                    601: /*
                    602:  * cancel <artid>
                    603:  * Cancel the named article
                    604:  */
                    605: c_cancel(argc, argv)
                    606: char **argv;
                    607: {
                    608:        char *line, *p, *q, *r, *poster;
                    609:        char *findhist();
                    610:        register FILE *fp;
                    611:        char whatsisname[BUFLEN], nfilename[BUFLEN];
                    612:        time_t t;
                    613:        int su = 0;
                    614: #ifndef u370
                    615:        struct hbuf htmp;
                    616: #endif /* !u370 */
                    617: 
                    618:        if (argc < 2)
                    619:                error("cancel: Too few arguments.");
                    620:        (void) strcpy(whatsisname, senderof(&header));
                    621:        line = findhist(argv[1]);
                    622:        if (line == NULL) {
                    623:                struct tm *tm;
                    624:                log("Can't cancel %s:  non-existent", argv[1]);
                    625:                (void) time(&t);
                    626:                tm = localtime(&t);
                    627: #ifdef USG
                    628:                sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled",
                    629: #else /* !USG */
                    630:                sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled",
                    631: #endif /* !USG */
                    632:                   argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour,
                    633:                   tm->tm_min);
                    634:                savehist(bfr);
                    635:                return -1;
                    636:        }
                    637: 
                    638:        q = index(line, '\t');
                    639:        p = index(q+1, '\t');
                    640:        if (p == NULL || *++p == '\0' || *p == '\n') {
                    641:                *q = '\0';
                    642:                log("Expired article %s", line);
                    643:                return -1;
                    644:        }
                    645:        if (strcmp(p, "cancelled") == 0) {
                    646:                *q = '\0';
                    647:                log("Already Cancelled %s", line);
                    648:                return -1;
                    649:        } else
                    650:                log("Cancelling %s", line);
                    651:        if ((uid == ROOTID||uid == 0) && (
                    652: #ifdef ORGDISTRIB
                    653:                strcmp(header.distribution, ORGDISTRIB) == 0 ||
                    654: #endif /* ORGDISTRIB */
                    655:                strcmp(header.distribution, "local") == 0))
                    656:                su = 1;
                    657:        while (*p) {
                    658:                q = index(p, ' ');
                    659:                if (q)
                    660:                        *q = '\0';
                    661:                (void) strcpy(nfilename, dirname(p));
                    662:                fp = fopen(nfilename, "r");
                    663:                if (fp == NULL) {
                    664:                        log("Can't cancel %s: %s", line, errmsg(errno));
                    665:                        return -1;
                    666:                }
                    667:                htmp.unrec[0] = NULL;
                    668:                if (hread(&htmp, fp, TRUE) == NULL) {
                    669:                        if (bfr[0] == '/') {
                    670:                                fp = fopen(bfr, "r");
                    671:                                if (fp == NULL
                    672:                                        || hread(&htmp, fp, TRUE) == NULL)
                    673:                                        error("Article is garbled.");
                    674:                        } else 
                    675:                                error("Article is garbled.");
                    676:                }
                    677:                (void) fclose(fp);
                    678:                poster = senderof(&htmp);
                    679:                /* only compare up to '.' or ' ' */
                    680:                r = index(poster,'.');
                    681:                if (r == NULL)
                    682:                        r = index(poster,' ');
                    683:                if (r != NULL)
                    684:                        *r = '\0';
                    685:                if (!su && strncmp(whatsisname, poster,strlen(poster))) {
                    686:                        error("Not contributor: posted by %s, and you are %s", poster, whatsisname);
                    687:                }
                    688: 
                    689:                (void) unlink(nfilename);
                    690:                p = q+1;
                    691:        }
                    692:        return 0;
                    693: }
                    694: 
                    695: /*
                    696:  * sendsys     (no arguments)
                    697:  *
                    698:  * Mail the sys file to the person submitting the article.
                    699:  * POLICY: the contents of your sys file are public information
                    700:  * and as such, you should not change this code.  You may feel
                    701:  * free to arrange for it to manually notify you, in the event
                    702:  * that you want to do something to clean it up before it goes out.
                    703:  * Secret sites on the net are expressly frowned on.
                    704:  * 
                    705:  * The purpose of this command is for making a network map.  The
                    706:  * details of your link and which newsgroups are forwarded are not
                    707:  * important, in case you want to sanitize them.  Since the definition
                    708:  * of USENET is those sites getting net.announce, you can disable this
                    709:  * on sites not getting net articles, but if you take out the list of
                    710:  * forwarded newsgroups, and you have sites that only get local newsgroups,
                    711:  * you should make this clear, or remove those sites from what you send out.
                    712:  */
                    713: /* ARGSUSED */
                    714: c_sendsys(argc, argv)
                    715: char **argv;
                    716: {
                    717:        register FILE *f, *u;
                    718:        int c;
                    719: 
                    720: #ifdef NOTIFY
                    721:        f = mailhdr((struct hbuf *)NULL, "sendsys control message");
                    722:        if (f != NULL) {
                    723:                fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB);
                    724:                fprintf(f, "It has been sent.\n");
                    725:                (void) mclose(f);
                    726:        }
                    727: #endif /* NOTIFY */
                    728:        f = mailhdr(&header, "response to your sendsys request");
                    729:        u = fopen(SUBFILE, "r");
                    730:        if (f != NULL && u != NULL) {
                    731:                while ((c=getc(u)) != EOF)
                    732:                        putc(c, f);
                    733:                (void) fclose(u);
                    734:                (void) mclose(f);
                    735:        }
                    736:        return 0;
                    737: }
                    738: 
                    739: /*
                    740:  * Send the version number to the right person.
                    741:  */
                    742: /* ARGSUSED */
                    743: c_version(argc, argv)
                    744: char **argv;
                    745: {
                    746:        register FILE *f;
                    747: 
                    748:        f = mailhdr(&header, "Our news version");
                    749:        if (f == NULL)
                    750:                error("Cannot send back error message");
                    751:        fprintf(f, "Currently running news version %s.\n\n", news_version);
                    752:        fprintf(f, "The header of your message follows:\n\n");
                    753:        (void) hwrite(&header, f);
                    754:        (void) mclose(f);
                    755:        return 0;
                    756: }
                    757: 
                    758: /*
                    759:  * Check the active file for old or missing newsgroups
                    760:  * Body of article is list of valid groups
                    761:  */
                    762: /* ARGSUSED */
                    763: c_checkgroups(argc, argv)
                    764: char **argv;
                    765: {
                    766:        int rc;
                    767: 
                    768:        (void) setuid(geteuid());
                    769:        /* dont change the cat %s| to < %s, it breaks some "unix" systems */
                    770:        (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB,
                    771: #ifdef NOTIFY
                    772:                (TELLME && *TELLME) ? TELLME : NEWSUSR );
                    773: #else /* !NOTIFY */
                    774:                NEWSUSR);
                    775: #endif /* !NOTIFY */
                    776:        rc = system(bfr);
                    777:        log("system(%s) status %d", bfr, rc);
                    778:        return 0;
                    779: }
                    780: 
                    781: /*
                    782:  * An unknown control message has been received.
                    783:  */
                    784: c_unknown(h, ctlmsgtext)
                    785: struct hbuf *h;
                    786: char *ctlmsgtext;
                    787: {
                    788:        register FILE *f;
                    789: 
                    790:        log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path);
                    791: #ifdef NOTIFY
                    792:        f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message");
                    793:        if (f != NULL) {
                    794:                fprintf(f, "Currently running news version %s.\n\n", news_version);
                    795:                fprintf(f, "The header of the message follows:\n\n");
                    796:                (void) hwrite(h, f);
                    797:                (void) mclose(f);
                    798:        }
                    799: #endif /* NOTIFY */
                    800:        return 0;
                    801: }
                    802: 
                    803: /* ARGSUSED */
                    804: c_unimp(argc, argv)
                    805: char **argv;
                    806: {
                    807:        register FILE *f;
                    808: 
                    809: #ifdef NOTIFY
                    810:        f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message");
                    811:        if (f != NULL) {
                    812:                fprintf(f, "Currently running news version B %s.\n\n", news_version);
                    813:                fprintf(f, "The header of the message follows:\n\n");
                    814:                (void) hwrite(&header, f);
                    815:                (void) mclose(f);
                    816:        }
                    817: #endif /* NOTIFY */
                    818:        return 0;
                    819: }
                    820: 
                    821: /*
                    822:  * This is a modified version of popen, made more secure.  Rather than
                    823:  * forking off a shell, you get a bare process.  You must have exactly
                    824:  * one argument, and the command must be mail (or sendmail if you have it).
                    825:  */
                    826: #define        RDR     0
                    827: #define        WTR     1
                    828: static int     mopen_pid[20];
                    829: char *replyname();
                    830: 
                    831: FILE *
                    832: mhopen(hptr)
                    833: struct hbuf *hptr;
                    834: {
                    835:        int p[2];
                    836:        register myside, hisside, pid;
                    837:        char *sendto = "usenet";
                    838: 
                    839:        if (hptr)
                    840:                sendto = replyname(hptr);
                    841:        else {
                    842: #ifdef NOTIFY
                    843:                if (TELLME)
                    844:                        sendto = TELLME;
                    845: #endif /* NOTIFY */
                    846:                if (sendto == NULL || *sendto == '\0')
                    847:                        return NULL;
                    848:        }
                    849:        verifyname(sendto);
                    850:        if(pipe(p) < 0)
                    851:                return NULL;
                    852:        myside = p[WTR];
                    853:        hisside = p[RDR];
                    854:        if((pid = vfork()) == 0) {
                    855:                /* myside and hisside reverse roles in child */
                    856:                (void) close(myside);
                    857:                (void) close(0);
                    858:                (void) dup(hisside);
                    859:                (void) close(hisside);
                    860:                (void) setgid(gid);
                    861:                (void) setuid(uid);
                    862: #ifdef SENDMAIL
                    863:                execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL);
                    864: #endif /* SENDMAIL */
                    865: #ifdef MMDF
                    866:                execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL);
                    867: #endif /* MMDF */
                    868:                execl("/usr/bin/mailx", "mail", sendto, (char *)NULL);
                    869:                execl("/usr/bin/mail", "mail", sendto, (char *)NULL);
                    870:                execl("/usr/ucb/mail", "mail", sendto, (char *)NULL);
                    871:                execl("/bin/mail", "mail", sendto, (char *)NULL);
                    872:                _exit(1);
                    873:        }
                    874:        if(pid == -1)
                    875:                return NULL;
                    876:        mopen_pid[myside] = pid;
                    877:        (void) close(hisside);
                    878:        return(fdopen(myside, "w"));
                    879: }
                    880: 
                    881: mclose(ptr)
                    882: FILE *ptr;
                    883: {
                    884:        register f, r, (*hstat)(), (*istat)(), (*qstat)();
                    885:        int status;
                    886: 
                    887:        f = fileno(ptr);
                    888:        (void) fclose(ptr);
                    889:        istat = signal(SIGINT, SIG_IGN);
                    890:        qstat = signal(SIGQUIT, SIG_IGN);
                    891:        hstat = signal(SIGHUP, SIG_IGN);
                    892:        while((r = wait(&status)) != mopen_pid[f] && r != -1)
                    893:                ;
                    894:        if(r == -1)
                    895:                status = -1;
                    896:        signal(SIGINT, istat);
                    897:        signal(SIGQUIT, qstat);
                    898:        signal(SIGHUP, hstat);
                    899:        return status;
                    900: }
                    901: 
                    902: /*
                    903:  * mhopen a pipe to mail, write out a std header, and return the file ptr.
                    904:  *
                    905:  * We don't include a From: field because this is probably uucp, i.e.
                    906:  * explicitly routed.  Leave it up to the recipient's mailer.
                    907:  * Always include the To: field because if we ge back failed mail, we
                    908:  * might be able to deliver it by hand if we know to wom it was addressed.
                    909:  * By convention, hptr==NULL means to send the message to the local contact person.
                    910:  */
                    911: FILE *
                    912: mailhdr(hptr, subject)
                    913: struct hbuf *hptr;
                    914: char  *subject;
                    915: {
                    916:        FILE *fp;
                    917:        time_t now;
                    918:        char *to = "usenet";
                    919:        extern char *mydomain();
                    920: 
                    921: #ifdef NOTIFY
                    922:        if (TELLME && *TELLME)
                    923:                to = TELLME;
                    924: #endif /* NOTIFY */
                    925:        if (hptr)
                    926:                to = replyname(hptr);
                    927: 
                    928:        if ((fp = mhopen(hptr)) != NULL) {
                    929:                (void) time(&now);
                    930:                fprintf(fp, "Date: %s\n", arpadate(&now));
                    931: #ifdef MMDF
                    932:                fprintf(fp, "From: The News System <usenet@%s>\n",
                    933:                                FROMSYSNAME);
                    934: #endif /* MMDF */
                    935:                fprintf(fp, "To: %s\n", to);
                    936:                fprintf(fp, "Subject: %s\n", subject);
                    937:                fprintf(fp, "Responding-System: %s\n\n", LOCALSYSNAME);
                    938:        }
                    939:        return fp;
                    940: }
                    941: 
                    942: /*
                    943:  * verify that the name mail is being sent to does not contain any
                    944:  * nasty hooks to invoke funny functions from the shell or the like.
                    945:  */
                    946: verifyname(sendto)
                    947: char *sendto;
                    948: {
                    949:        /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
                    950:        char *nasty = "\"'\\`^|;& <>/~";
                    951:        register char *p;
                    952: 
                    953:        if (sendto[0] <= ' ') {
                    954:                xerror("nasty mail name %s from %s", sendto, header.path);
                    955:        }
                    956:        for (p=sendto; *p; p++) {
                    957:                if (*p == ' ') {
                    958:                        *p = 0;
                    959:                        break;
                    960:                }
                    961:        }
                    962:        if (strpbrk(sendto, nasty) != NULL)
                    963:                error("nasty mail name %s from %s", sendto, header.path);
                    964: 
                    965:        for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) {
                    966:                if (*++nasty == '.')    /* check for .. */
                    967:                        error("nasty mail name %s from %s", sendto, header.path);
                    968:        }
                    969: }
                    970: 
                    971: /*
                    972:  * Checks to make sure the control message is OK to post.
                    973:  */
                    974: ctlcheck()
                    975: {
                    976:        char msg[BUFLEN];
                    977:        char *p;
                    978: 
                    979:        if (!is_ctl)
                    980:                return;
                    981: 
                    982:        if (header.ctlmsg[0])
                    983:                (void) strcpy(msg, header.ctlmsg);
                    984:        else
                    985:                (void) strcpy(msg, header.title);
                    986: 
                    987:        p = index(msg, ' ');
                    988:        if (p)
                    989:                *p = 0;
                    990:        
                    991:        if (strcmp(msg, "ihave") == 0 || strcmp(msg, "sendbad") == 0 ||
                    992:                strcmp(msg, "sendme") == 0) {
                    993:                return; /* no restrictions */
                    994:        } else if (strcmp(msg, "newgroup") == 0) {
                    995:                suser();
                    996:        } else if (strcmp(msg, "rmgroup") == 0) {
                    997:                suser();
                    998:        } else if (strcmp(msg, "sendsys") == 0) {
                    999:                suser();
                   1000:        } else if (strcmp(msg, "checkgroups") == 0) {
                   1001:                suser();
                   1002:        } else if (strcmp(msg, "version") == 0) {
                   1003:                return; /* no restrictions */
                   1004:        } else if (strcmp(msg, "cancel") == 0) {
                   1005:                return; /* no restrictions at this level */
                   1006:        } else if (strcmp(msg, "delsub") == 0) {
                   1007:                if (!PREFIX(header.nbuf, "to.")) {
                   1008:                        log("Must be in a 'to.system' newsgroup.");
                   1009:                        xxit(0);
                   1010:                }
                   1011:                return;
                   1012:        } else {
                   1013:                log("Unrecognized control message - %s\n", msg);
                   1014:                xxit(0);
                   1015:        }
                   1016: }
                   1017: 
                   1018: /* Make sure this guy is special. */
                   1019: suser()
                   1020: {
                   1021:        if (uid == 0 || uid == ROOTID)
                   1022:                return;
                   1023:        /*
                   1024:         * We assume that since our real uid is the same as NEWSUSR
                   1025:         * (the euid) we were run by rootid and it did a setuid.
                   1026:         * Too bad we can't set just the effective uid like suid does.
                   1027:         */
                   1028:        if (uid == geteuid())
                   1029:                return;
                   1030: #ifdef IHCC
                   1031:        printf("Please use the command:\n\ttoolnews providers\n");
                   1032:        printf("then call one of the news people.\n");
                   1033: #else
                   1034:        printf("Get your local netnews contact to do it for you.\n");
                   1035: #endif
                   1036:        xxit(0);
                   1037: }

unix.superglobalmegacorp.com

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