Annotation of 43BSD/contrib/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.43    3/19/86";
                     23: #endif /* SCCSID */
                     24: 
                     25: #include "iparams.h"
                     26: 
                     27: #define eq(msg) (strcmp(msg, cargv[0]) == 0)
                     28: 
                     29: int cargc;
                     30: char **cargv;
                     31: 
                     32: FILE *hfopen();
                     33: FILE *popen(), *mhopen(), *mailhdr();
                     34: 
                     35: char *senderof();
                     36: #ifdef u370
                     37: static struct hbuf htmp;
                     38: #endif /* u370 */
                     39: 
                     40: control(h)
                     41: struct hbuf *h;
                     42: {
                     43:        register char *ctlmsgtext;
                     44: 
                     45:        if (strncmp(h->title, "cmsg ", 5) == 0) {
                     46:                register char *cp1, *cp2;
                     47:                cp1 = h->title;
                     48:                cp2 = h->title + 5;
                     49:                while (*cp1++ = *cp2++)
                     50:                        ;
                     51:        }
                     52: 
                     53:        if (*h->ctlmsg)
                     54:                ctlmsgtext = h->ctlmsg;
                     55:        else
                     56:                ctlmsgtext = h->title;
                     57:        log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext);
                     58:        /*
                     59:         * Control messages have the standard format
                     60:         *      command [args]
                     61:         * much like shell commands.  Each site has the option
                     62:         * of customizing this code to deal with control messages
                     63:         * as they see fit, but we would like to buy back the
                     64:         * code, ifdeffed or otherwise parameterized, to simplify
                     65:         * the maintenence issues.
                     66:         */
                     67:        argparse(ctlmsgtext);
                     68:        
                     69:        if (eq("cancel"))
                     70:                return c_cancel(cargc, cargv);
                     71:        else if (eq("newgroup"))
                     72:                c_newgroup(cargc, cargv);
                     73:        else if (eq("ihave"))
                     74:                c_ihave(cargc, cargv);
                     75:        else if (eq("sendme"))
                     76:                c_sendme(cargc, cargv);
                     77:        else if (eq("sendbad"))
                     78:                c_sendme(cargc, cargv);
                     79:        else if (eq("rmgroup"))
                     80:                c_rmgroup(cargc, cargv);
                     81:        else if (eq("sendsys"))
                     82:                c_sendsys(cargc, cargv);
                     83:        else if (eq("senduuname"))
                     84:                c_senduuname(cargc, cargv);
                     85:        else if (eq("version"))
                     86:                c_version(cargc, cargv);
                     87:        else if (eq("checkgroups"))
                     88:                c_checkgroups(cargc, cargv);
                     89:        else if (eq("delsub"))
                     90:                c_unimp(cargc, cargv);
                     91:        else
                     92:                c_unknown(h, ctlmsgtext);
                     93:        return 0;
                     94: }
                     95: 
                     96: /*
                     97:  * Parse the string str into separate words in cargc and cargv
                     98:  * as per the usual UNIX convention.  Nothing fancy here, just
                     99:  * blanks and tabs separating words.
                    100:  */
                    101: argparse(str)
                    102: char *str;
                    103: {
                    104:        static char *cavpbuf[20];
                    105:        static char cavbuf[256];
                    106:        char *nextfree = cavbuf;
                    107: 
                    108:        if (str == '\0')
                    109:                xerror("Control message %s has no title", header.ident);
                    110:        cargc = (*str != '\0');
                    111:        cargv = cavpbuf;
                    112:        cargv[0] = cavbuf;
                    113: 
                    114:        while (*str) {
                    115:                if (*str <= ' ') {
                    116:                        *nextfree++ = 0;
                    117:                        cargv[cargc] = nextfree;
                    118:                        cargc++;
                    119:                        /* skip over white space */
                    120:                        while (*str != '\0' && *str <= ' ')
                    121:                                str++;
                    122:                        if (*str == '\0')       /* line ends in white space */
                    123:                                return;
                    124:                } else
                    125:                        *nextfree++ = *str++;
                    126:        }
                    127: }
                    128: 
                    129: /*
                    130:  * ihave <artid> <remotesys>
                    131:  * The other system is telling you it has article <artid>, in case
                    132:  * you decide you want it to transmit it to you.
                    133:  */
                    134: c_ihave(argc, argv)
                    135: char **argv;
                    136: {
                    137:        char tl[256], ng[256];
                    138: #ifndef u370
                    139:        struct hbuf htmp;
                    140: #endif /* !u370 */
                    141: 
                    142:        if (argc < 2)
                    143:                xerror("ihave: Not enough arguments.");
                    144:        /*
                    145:         * Check that we haven't already seen it (history)
                    146:         * and then send back a "sendme" message if we subscribe.
                    147:         */
                    148:        (void) strncpy(htmp.ident, argv[1], BUFLEN);
                    149:        if (history(&htmp) == 0) {
                    150:                /* Should probably check SUBFILE here. */
                    151:                (void) sprintf(tl, "sendme %s %s", argv[1], FULLSYSNAME);
                    152:                (void) sprintf(ng, "to.%s.ctl", argv[2]);
                    153:                xmitmsg(argv[2], tl, ng);
                    154:        }
                    155: }
                    156: 
                    157: /*
                    158:  * sendme <artid> ... <remotesys>
                    159:  * The other system wants me to send him article <artid>.
                    160:  */
                    161: c_sendme(argc, argv)
                    162: char **argv;
                    163: {
                    164:        int i;
                    165:        FILE *fp;
                    166:        struct srec srec;
                    167: #ifndef u370
                    168:        struct hbuf htmp;
                    169: #endif /* !u370 */
                    170: 
                    171:        if (argc < 2)
                    172:                xerror("sendme: Not enough arguments.");
                    173:        /* Don't ask for it from myself */
                    174:        if (strncmp(FULLSYSNAME, argv[argc], SNLN) == 0)
                    175:                return;
                    176:        /* Find the sys record */
                    177:        s_openr();
                    178:        while (s_read(&srec)) {
                    179:                if (strncmp(srec.s_name, argv[argc], SNLN))
                    180:                        continue;
                    181:                /* It's the right one.  Send them. */
                    182:                for (i=1; i<argc; i++) {
                    183:                        fp = hfopen(argv[i]);
                    184:                        htmp.unrec[0] = NULL;
                    185:                        if (hread(&htmp, fp, TRUE) == NULL) {
                    186:                                if (bfr[0] == '/') {
                    187:                                        fp = xfopen(bfr, "r");
                    188:                                        if (hread(&htmp, fp, TRUE) == NULL)
                    189:                                                xerror("Article %s is garbled.", bfr);
                    190:                                } else
                    191:                                        xerror("Article %s is garbled.", argv[i]);
                    192:                        }
                    193:                        (void) fseek(fp, 0L, 0);
                    194:                        if (strcmp(argv[0], "sendme") == 0) {
                    195:                                /* check that other sys subscribes. */
                    196:                                if (!ngmatch(htmp.nbuf, srec.s_nbuf) || 
                    197:                                        !(htmp.distribution[0] == '\0' ||
                    198:                                        ngmatch(htmp.distribution, srec.s_nbuf)))
                    199:                                        continue;
                    200:                        }
                    201:                        transmit(&srec, fp, 0, (char **)0, 0);
                    202:                        /* transmit does fclose(fp) */
                    203:                }
                    204:                return;
                    205:        }
                    206:        xerror("Cannot find system %s to send article %s to.", argv[argc],
                    207:                argv[1]);
                    208: }
                    209: 
                    210: /*
                    211:  * newgroup <groupname>
                    212:  * A new newsgroup has been created.
                    213:  * The body of the article, if present, is a description of the
                    214:  * purpose of the newsgroup.
                    215:  *
                    216:  */
                    217: c_newgroup(argc, argv)
                    218: char **argv;
                    219: {
                    220:        FILE *fd;
                    221:        int didcreate = 0;
                    222: 
                    223:        if (argc < 1)
                    224:                xerror("newgroup: Not enough arguments.");
                    225:        if (validng(argv[1]))
                    226:                return;
                    227:        if (header.approved[0] == '\0')
                    228:                xerror("newgroup: %s not approved", argv[1]);
                    229: 
                    230: #ifndef NONEWGROUPS
                    231: #ifdef ORGDISTRIB
                    232:        if (!strcmp(ORGDISTRIB, header.distribution)) {
                    233:                didcreate++;
                    234: #endif /* ORGDISTRIB */
                    235:                actfp = xfopen(ACTIVE, "a");
                    236:                fprintf(actfp, "%s 00000 00001 y\n", argv[1]);
                    237:                (void) fclose(actfp);
                    238: #ifdef ORGDISTRIB
                    239:        }
                    240: #endif /* ORGDISTRIB */
                    241: #endif /* !NONEWGROUPS */
                    242: 
                    243: #ifdef NOTIFY
                    244:        fd = mailhdr((struct hbuf *)NULL, "creation of new newsgroup");
                    245:        if (fd != NULL) {
                    246:                if (didcreate) 
                    247:                        fprintf(fd, "A new newsgroup called '%s' has been created by %s.\n",
                    248:                        argv[1], header.path);
                    249:                else
                    250:                        fprintf(fd, "%s requested that a new newsgroup called '%s' be created.\n",
                    251:                        header.path, argv[1]);
                    252:                fprintf(fd, "It was approved by %s\n\n", header.approved);
                    253: #ifdef ORGDISTRIB
                    254:                    fprintf(fd, "You can accomplish this by sending a newgroup control message with a\n");
                    255:                    fprintf(fd, "distribution code of %s; in other words, by executing the command:\n", ORGDISTRIB);
                    256:                    fprintf(fd, "%s/inews -n net.news -d %s -t \"cmsg newgroup %s\"\n", 
                    257:                        LIB, ORGDISTRIB, argv[1]);
                    258: #endif /* ORGDISTRIB */
                    259:                (void) mclose(fd);
                    260:        }
                    261: }
                    262: #endif /* NOTIFY */
                    263: 
                    264: 
                    265: /*
                    266:  * rmgroup <groupname>
                    267:  * An old newsgroup is being cancelled on a network wide basis.
                    268:  */
                    269: c_rmgroup(argc, argv)
                    270: char **argv;
                    271: {
                    272:        FILE *fd;
                    273:        int shouldremove = 0;
                    274: 
                    275:        if (argc < 1)
                    276:                xerror("rmgroup: Not enough arguments.");
                    277:        if (!validng(argv[1]))
                    278:                return;
                    279:        if (header.approved[0] == '\0')
                    280:                xerror("rmgroup: %s not approved", argv[1]);
                    281: 
                    282: #ifndef MANUALLY
                    283: #ifdef ORGDISTRIB
                    284:        if (!strcmp(ORGDISTRIB, header.distribution))
                    285: #endif /* ORGDISTRIB */                
                    286:        shouldremove++;
                    287: #endif /* !MANUALLY */
                    288: #ifdef NOTIFY
                    289:        fd = mailhdr((struct hbuf *)NULL, "rmgroup control message");
                    290:        if (fd != NULL) {
                    291:                if (shouldremove) {
                    292:                        fprintf(fd, "A newsgroup called '%s' has been removed by %s.\n\n",
                    293:                                argv[1], header.path);
                    294: #  ifdef USG
                    295:                        fprintf(fd, "You may need to remove the directory %s by hand\n",
                    296:                                dirname(argv[1]));
                    297: #  endif
                    298:                } else {
                    299:                        fprintf(fd, "%s has requested that newsgroup %s be removed.\n",
                    300:                                header.path, argv[1]);
                    301:                        fprintf(fd, "You should remove it by hand\n");
                    302:                        fprintf(fd, "To do this, execute the command\n");
                    303:                        fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]);
                    304:                }
                    305:                (void) mclose(fd);
                    306:        }
                    307: #endif /* NOTIFY */
                    308: 
                    309:        if (shouldremove) {
                    310:                int rc;
                    311:                /* We let the shell do all the work.
                    312:                 * See the rmgrp shell script. */
                    313:                (void) setuid(geteuid()); /* otherwise it won't rmdir the dir */
                    314:                (void) sprintf(bfr, "exec %s/rmgroup %s", LIB, argv[1]);
                    315:                rc = system(bfr);
                    316:                log("system(%s) status %d", bfr, rc);
                    317:        }
                    318: }
                    319: 
                    320: /*
                    321:  * cancel <artid>
                    322:  * Cancel the named article
                    323:  */
                    324: c_cancel(argc, argv)
                    325: char **argv;
                    326: {
                    327:        char *line, *p, *q, *r, *poster;
                    328:        char *findhist();
                    329:        register FILE *fp;
                    330:        char whatsisname[BUFLEN], nfilename[BUFLEN];
                    331:        time_t t;
                    332:        int su = 0;
                    333: #ifndef u370
                    334:        struct hbuf htmp;
                    335: #endif /* !u370 */
                    336: 
                    337:        if (argc < 1)
                    338:                xerror("cancel: Not enough arguments.");
                    339:        (void) strcpy(whatsisname, senderof(&header));
                    340:        line = findhist(argv[1]);
                    341:        if (line == NULL) {
                    342:                struct tm *tm;
                    343:                log("Can't cancel %s:  non-existent", argv[1]);
                    344:                (void) time(&t);
                    345:                tm = localtime(&t);
                    346: #ifdef USG
                    347:                sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled",
                    348: #else /* !USG */
                    349:                sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled",
                    350: #endif /* !USG */
                    351:                   argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour,
                    352:                   tm->tm_min);
                    353:                savehist(bfr);
                    354:                return 1;
                    355:        }
                    356: 
                    357:        q = index(line, '\t');
                    358:        p = index(q+1, '\t');
                    359:        if (p == NULL || *++p == '\0' || *p == '\n') {
                    360:                *q = '\0';
                    361:                log("Expired article %s", line);
                    362:                return 1;
                    363:        }
                    364:        if (strcmp(p, "cancelled") == 0) {
                    365:                *q = '\0';
                    366:                log("Already Cancelled %s", line);
                    367:                return 1;
                    368:        } else
                    369:                log("Cancelling %s", line);
                    370:        if ((uid == ROOTID||uid == 0) && strcmp(header.distribution, "local") == 0)
                    371:                su = 1;
                    372:        while (*p) {
                    373:                q = index(p, ' ');
                    374:                if (q)
                    375:                        *q = '\0';
                    376:                (void) strcpy(nfilename, dirname(p));
                    377:                fp = fopen(nfilename, "r");
                    378:                if (fp == NULL) {
                    379:                        log("Already Cancelled %s", line);
                    380:                        return 1;
                    381:                }
                    382:                htmp.unrec[0] = NULL;
                    383:                if (hread(&htmp, fp, TRUE) == NULL) {
                    384:                        if (bfr[0] == '/') {
                    385:                                fp = fopen(bfr, "r");
                    386:                                if (fp == NULL
                    387:                                        || hread(&htmp, fp, TRUE) == NULL)
                    388:                                        xerror("Article is garbled.");
                    389:                        } else 
                    390:                                xerror("Article is garbled.");
                    391:                }
                    392:                (void) fclose(fp);
                    393:                poster = senderof(&htmp);
                    394:                /* only compare up to '.' or ' ' */
                    395:                r = index(poster,'.');
                    396:                if (r == NULL)
                    397:                        r = index(poster,' ');
                    398:                if (r != NULL)
                    399:                        *r = '\0';
                    400:                if (!su && strncmp(whatsisname, poster,strlen(poster))) {
                    401:                        xerror("Not contributor: posted by %s, and you are %s", poster, whatsisname);
                    402:                }
                    403: 
                    404:                (void) unlink(nfilename);
                    405:                p = q+1;
                    406:        }
                    407:        return 0;
                    408: }
                    409: 
                    410: /*
                    411:  * sendsys     (no arguments)
                    412:  *
                    413:  * Mail the sys file to the person submitting the article.
                    414:  * POLICY: the contents of your sys file are public information
                    415:  * and as such, you should not change this code.  You may feel
                    416:  * free to arrange for it to manually notify you, in the event
                    417:  * that you want to do something to clean it up before it goes out.
                    418:  * Secret sites on the net are expressly frowned on.
                    419:  * 
                    420:  * The purpose of this command is for making a network map.  The
                    421:  * details of your link and which newsgroups are forwarded are not
                    422:  * important, in case you want to sanitize them.  Since the definition
                    423:  * of USENET is those sites getting net.announce, you can disable this
                    424:  * on sites not getting net articles, but if you take out the list of
                    425:  * forwarded newsgroups, and you have sites that only get local newsgroups,
                    426:  * you should make this clear, or remove those sites from what you send out.
                    427:  */
                    428: /* ARGSUSED */
                    429: c_sendsys(argc, argv)
                    430: char **argv;
                    431: {
                    432:        register FILE *f, *u;
                    433:        int c;
                    434: 
                    435: #ifdef NOTIFY
                    436:        f = mailhdr((struct hbuf *)NULL, "sendsys control message");
                    437:        if (f != NULL) {
                    438:                fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB);
                    439:                fprintf(f, "It has been sent.\n");
                    440:                (void) mclose(f);
                    441:        }
                    442: #endif
                    443:        f = mailhdr(&header, "response to your sendsys request");
                    444:        u = fopen(SUBFILE, "r");
                    445:        if (f != NULL && u != NULL) {
                    446:                while ((c=getc(u)) != EOF)
                    447:                        putc(c, f);
                    448:                (void) fclose(u);
                    449:                (void) mclose(f);
                    450:        }
                    451: }
                    452: 
                    453: /*
                    454:  * senduuname  (no arguments)
                    455:  *
                    456:  * Run the "uuname" command and send it back to the person who submitted
                    457:  * the article.  The purpose of this control message is for attempting to
                    458:  * make a uucp net map.
                    459:  *
                    460:  * POLICY: If you view this information as not public (because you have
                    461:  * a connection you consider secret, or know a site that considers itself
                    462:  * secret) you can feel free to change this code in whatever way is
                    463:  * appropriate, so long as it sends some response back to the sender.  If
                    464:  * you don't run uucp, this code does not make sense, and so an error
                    465:  * message (or garbage, such as "research") will be mailed back.
                    466:  *
                    467:  * If you wish to add or remove sites from the output of uuname, you
                    468:  * may wish to use the euuname.sh shell script here.
                    469:  */
                    470: /* ARGSUSED */
                    471: c_senduuname(argc, argv)
                    472: char **argv;
                    473: {
                    474:        char buf[256];
                    475:        FILE *fd, *u;
                    476:        int c;
                    477: 
                    478: #ifdef NOTIFY
                    479:        fd = mailhdr((struct hbuf *)NULL, "uuname control message");
                    480:        fprintf(fd, "%s requested your uuname output\n", header.path);
                    481:        (void) mclose(fd);
                    482: #endif
                    483:        fd = mailhdr(&header, "response to your senduuname request");
                    484: #ifdef UUPROG
                    485:        if (UUPROG[0] == '/')
                    486:                (void) strcpy(buf, UUPROG);
                    487:        else
                    488:                (void) sprintf(buf, "%s/%s", LIB, UUPROG);
                    489: #else
                    490:        (void) strcpy(buf, "uuname");
                    491: #endif
                    492:        u = popen(buf, "r");
                    493:        if (fd != NULL && u != NULL) {
                    494:                while ((c=getc(u)) != EOF)
                    495:                        putc(c, fd);
                    496:                (void) pclose(u);
                    497:                (void) mclose(fd);
                    498:        }
                    499: }
                    500: 
                    501: /*
                    502:  * Send the version number to the right person.
                    503:  */
                    504: /* ARGSUSED */
                    505: c_version(argc, argv)
                    506: char **argv;
                    507: {
                    508:        register FILE *f;
                    509: 
                    510:        f = mailhdr(&header, "Our news version");
                    511:        if (f == NULL)
                    512:                xerror("Cannot send back error message");
                    513:        fprintf(f, "Currently running news version %s.\n\n", news_version);
                    514:        fprintf(f, "The header of your message follows:\n\n");
                    515:        (void) hwrite(&header, f);
                    516:        (void) mclose(f);
                    517: }
                    518: 
                    519: /*
                    520:  * Check the active file for old or missing newsgroups
                    521:  * Body of article is list of valid groups
                    522:  */
                    523: /* ARGSUSED */
                    524: c_checkgroups(argc, argv)
                    525: char **argv;
                    526: {
                    527:        int rc;
                    528: 
                    529:        (void) setuid(geteuid());
                    530:        /* dont change the cat %s| to < %s, it breaks some "unix" systems */
                    531:        (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB,
                    532: #ifdef NOTIFY
                    533:                (TELLME && *TELLME) ? TELLME : NEWSUSR );
                    534: #else /* !NOTIFY */
                    535:                NEWSUSR);
                    536: #endif /* !NOTIFY */
                    537:        rc = system(bfr);
                    538:        log("system(%s) status %d", bfr, rc);
                    539: }
                    540: 
                    541: /*
                    542:  * An unknown control message has been received.
                    543:  */
                    544: c_unknown(h, ctlmsgtext)
                    545: struct hbuf *h;
                    546: char *ctlmsgtext;
                    547: {
                    548:        register FILE *f;
                    549: 
                    550:        log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path);
                    551: #ifdef NOTIFY
                    552:        f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message");
                    553:        if (f != NULL) {
                    554:                fprintf(f, "Currently running news version %s.\n\n", news_version);
                    555:                fprintf(f, "The header of the message follows:\n\n");
                    556:                (void) hwrite(h, f);
                    557:                (void) mclose(f);
                    558:        }
                    559: #endif /* NOTIFY */
                    560: }
                    561: 
                    562: /* ARGSUSED */
                    563: c_unimp(argc, argv)
                    564: char **argv;
                    565: {
                    566:        register FILE *f;
                    567: 
                    568: #ifdef NOTIFY
                    569:        f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message");
                    570:        if (f != NULL) {
                    571:                fprintf(f, "Currently running news version B %s.\n\n", news_version);
                    572:                fprintf(f, "The header of the message follows:\n\n");
                    573:                (void) hwrite(&header, f);
                    574:                (void) mclose(f);
                    575:        }
                    576: #endif /* NOTIFY */
                    577: }
                    578: 
                    579: xmitmsg(tosys, title, ng)
                    580: char *tosys, *title, *ng;
                    581: {
                    582: #ifndef u370
                    583:        struct hbuf htmp;
                    584: #endif /* !u370 */
                    585:        struct srec srec;
                    586:        FILE *tfp;
                    587:        char *fname;
                    588: 
                    589:        /* Make an article called ARTICLE */
                    590:        (void) sprintf(htmp.from, "%s@%s%s", "usenet", FULLSYSNAME, MYDOMAIN);
                    591:        (void) strcpy(htmp.path, NEWSUSR);
                    592:        (void) strcpy(htmp.nbuf, ng);
                    593:        (void) strcpy(htmp.title, title);
                    594:        (void) strcpy(htmp.ctlmsg, title);
                    595:        (void) strcpy(htmp.subdate, "");
                    596:        (void) strcpy(htmp.expdate, "");
                    597:        getident(&htmp);
                    598:        dates(&htmp);
                    599:        tfp = xfopen(fname = mktemp("/tmp/xmsgXXXXXX"), "w");
                    600:        hwrite(&htmp, tfp);
                    601:        (void) fclose(tfp);
                    602: 
                    603:        /* Find the sys record */
                    604:        s_openr();
                    605:        while (s_read(&srec)) {
                    606:                if (strncmp(srec.s_name, tosys, SNLN))
                    607:                        continue;
                    608:                tfp = xfopen(fname, "r");
                    609:                (void) transmit(&srec, tfp, 0, (char **)0, 0);
                    610:                (void) unlink(fname);
                    611:                return;
                    612:        }
                    613:        log("Can't find sys record for %s", tosys);
                    614:        xerror("Cannot find sys record");
                    615: }
                    616: 
                    617: /*
                    618:  * This is a modified version of popen, made more secure.  Rather than
                    619:  * forking off a shell, you get a bare process.  You must have exactly
                    620:  * one argument, and the command must be mail (or sendmail if you have it).
                    621:  */
                    622: #define        RDR     0
                    623: #define        WTR     1
                    624: static int     mopen_pid[20];
                    625: char *replyname();
                    626: 
                    627: FILE *
                    628: mhopen(hptr)
                    629: struct hbuf *hptr;
                    630: {
                    631:        int p[2];
                    632:        register myside, hisside, pid;
                    633:        char *sendto = "usenet";
                    634: 
                    635:        if (hptr)
                    636:                sendto = replyname(hptr);
                    637:        else {
                    638: #ifdef NOTIFY
                    639:                if (TELLME && *TELLME)
                    640:                        sendto = TELLME;
                    641: #endif /* NOTIFY */
                    642:                if (sendto == NULL)
                    643:                        return NULL;
                    644:        }
                    645:        verifyname(sendto);
                    646:        if(pipe(p) < 0)
                    647:                return NULL;
                    648:        myside = p[WTR];
                    649:        hisside = p[RDR];
                    650:        if((pid = fork()) == 0) {
                    651:                /* myside and hisside reverse roles in child */
                    652:                (void) close(myside);
                    653:                (void) close(0);
                    654:                (void) dup(hisside);
                    655:                (void) close(hisside);
                    656:                (void) setgid(gid);
                    657:                (void) setuid(uid);
                    658: #ifdef SENDMAIL
                    659:                execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL);
                    660: #endif /* SENDMAIL */
                    661: #ifdef MMDF
                    662:                execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL);
                    663: #endif /* MMDF */
                    664:                execl("/bin/mail", "mail", sendto, (char *)NULL);
                    665:                execl("/usr/bin/mail", "mail", sendto, (char *)NULL);
                    666:                execl("/usr/ucb/mail", "mail", sendto, (char *)NULL);
                    667:                _exit(1);
                    668:        }
                    669:        if(pid == -1)
                    670:                return NULL;
                    671:        mopen_pid[myside] = pid;
                    672:        (void) close(hisside);
                    673:        return(fdopen(myside, "w"));
                    674: }
                    675: 
                    676: mclose(ptr)
                    677: FILE *ptr;
                    678: {
                    679:        register f, r, (*hstat)(), (*istat)(), (*qstat)();
                    680:        int status;
                    681: 
                    682:        f = fileno(ptr);
                    683:        (void) fclose(ptr);
                    684:        istat = signal(SIGINT, SIG_IGN);
                    685:        qstat = signal(SIGQUIT, SIG_IGN);
                    686:        hstat = signal(SIGHUP, SIG_IGN);
                    687:        while((r = wait(&status)) != mopen_pid[f] && r != -1)
                    688:                ;
                    689:        if(r == -1)
                    690:                status = -1;
                    691:        signal(SIGINT, istat);
                    692:        signal(SIGQUIT, qstat);
                    693:        signal(SIGHUP, hstat);
                    694:        return status;
                    695: }
                    696: 
                    697: /*
                    698:  * mhopen a pipe to mail, write out a std header, and return the file ptr.
                    699:  *
                    700:  * We don't include a From: field because this is probably uucp, i.e.
                    701:  * explicitly routed.  Leave it up to the recipient's mailer.
                    702:  * Always include the To: field because if we ge back failed mail, we
                    703:  * might be able to deliver it by hand if we know to wom it was addressed.
                    704:  * By convention, hptr==NULL means to send the message to the local contact person.
                    705:  */
                    706: FILE *
                    707: mailhdr(hptr, subject)
                    708: struct hbuf *hptr;
                    709: char  *subject;
                    710: {
                    711:        FILE *fp;
                    712:        time_t now;
                    713:        char *to = "usenet";
                    714: 
                    715: #ifdef NOTIFY
                    716:        if (TELLME && *TELLME)
                    717:                to = TELLME;
                    718: #endif /* NOTIFY */
                    719:        if (hptr)
                    720:                to = replyname(hptr);
                    721: 
                    722:        if ((fp = mhopen(hptr)) != NULL) {
                    723:                (void) time(&now);
                    724:                fprintf(fp, "Date: %s\n", arpadate(&now));
                    725: #ifdef MMDF
                    726:                fprintf(fp, "From: The News System <usenet@%s%s>\n",
                    727:                                FULLSYSNAME, MYDOMAIN);
                    728: #endif /* MMDF */
                    729:                fprintf(fp, "To: %s\n", to);
                    730:                fprintf(fp, "Subject: %s\n", subject);
                    731: #ifdef HIDDENNET
                    732:                if (strcmp(LOCALSYSNAME, FULLSYSNAME))
                    733:                        fprintf(fp, "Responding-System: %s.%s%s\n\n",
                    734:                                LOCALSYSNAME, FULLSYSNAME, MYDOMAIN);
                    735: #endif /* !HIDDENNET */
                    736:                        fprintf(fp, "Responding-System: %s%s\n\n",
                    737:                                FULLSYSNAME, MYDOMAIN);
                    738:        }
                    739:        return fp;
                    740: }
                    741: 
                    742: /*
                    743:  * verify that the name mail is being sent to does not contain any
                    744:  * nasty hooks to invoke funny functions from the shell or the like.
                    745:  */
                    746: verifyname(sendto)
                    747: char *sendto;
                    748: {
                    749:        /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
                    750:        char *nasty = "\"'\\`^|;& <>/~";
                    751:        register char *p;
                    752: 
                    753:        if (sendto[0] <= ' ') {
                    754:                log("nasty mail name %s from %s", sendto, header.path);
                    755:                xxit(1);
                    756:        }
                    757:        for (p=sendto; *p; p++) {
                    758:                if (*p == ' ') {
                    759:                        *p = 0;
                    760:                        break;
                    761:                }
                    762:        }
                    763:        if (strpbrk(sendto, nasty) != NULL)
                    764:                xerror("nasty mail name %s from %s", sendto, header.path);
                    765: 
                    766:        for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) {
                    767:                if (*++nasty == '.')    /* check for .. */
                    768:                        xerror("nasty mail name %s from %s", sendto, header.path);
                    769:        }
                    770: }
                    771: 
                    772: /*
                    773:  * Checks to make sure the control message is OK to post.
                    774:  */
                    775: ctlcheck()
                    776: {
                    777:        char msg[BUFLEN];
                    778:        char *p;
                    779: 
                    780:        if (!is_ctl)
                    781:                return;
                    782: 
                    783:        if (header.ctlmsg[0])
                    784:                (void) strcpy(msg, header.ctlmsg);
                    785:        else
                    786:                (void) strcpy(msg, header.title);
                    787: 
                    788:        p = index(msg, ' ');
                    789:        if (p)
                    790:                *p = 0;
                    791:        
                    792:        if (strcmp(msg, "ihave") == 0) {
                    793:        } else if (strcmp(msg, "sendme") == 0) {
                    794:                return; /* no restrictions */
                    795:        } else if (strcmp(msg, "newgroup") == 0) {
                    796:                suser();
                    797:        } else if (strcmp(msg, "rmgroup") == 0) {
                    798:                suser();
                    799:        } else if (strcmp(msg, "sendsys") == 0) {
                    800:                suser();
                    801:        } else if (strcmp(msg, "senduuname") == 0) {
                    802:                suser();
                    803:        } else if (strcmp(msg, "checkgroups") == 0) {
                    804:                suser();
                    805:        } else if (strcmp(msg, "version") == 0) {
                    806:                return; /* no restrictions */
                    807:        } else if (strcmp(msg, "cancel") == 0) {
                    808:                return; /* no restrictions at this level */
                    809:        } else if (strcmp(msg, "delsub") == 0) {
                    810:                if (!prefix(header.nbuf, "to.")) {
                    811:                        printf("Must be in a 'to.system' newsgroup.");
                    812:                        xxit(0);
                    813:                }
                    814:                return;
                    815:        } else {
                    816:                printf("Unrecognized control message - %s\n", msg);
                    817:                xxit(0);
                    818:        }
                    819: }
                    820: 
                    821: /* Make sure this guy is special. */
                    822: suser()
                    823: {
                    824:        if (uid == 0 || uid == ROOTID)
                    825:                return;
                    826:        /*
                    827:         * We assume that since our real uid is the same as NEWSUSR
                    828:         * (the euid) we were run by rootid and it did a setuid.
                    829:         * Too bad we can't set just the effective uid like suid does.
                    830:         */
                    831:        if (uid == geteuid())
                    832:                return;
                    833: #ifdef IHCC
                    834:        printf("Please use the command:\n\ttoolnews providers\n");
                    835:        printf("then call one of the news people.\n");
                    836: #else
                    837:        printf("Get your local netnews contact to do it for you.\n");
                    838: #endif
                    839:        xxit(0);
                    840: }

unix.superglobalmegacorp.com

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