Annotation of 43BSD/contrib/news/src/postnews.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:  * Postnews: post a news message to Usenet.  This C version replaces a shell
                     16:  * script, and does more intelligent prompting and filtering than possible
                     17:  * in a shell script.
                     18:  */
                     19: 
                     20: #ifdef SCCSID
                     21: static char    *SccsId = "@(#)postnews.c       1.25    3/19/86";
                     22: #endif /* SCCSID */
                     23: 
                     24: #include "params.h"
                     25: 
                     26: #define APPEND 1
                     27: #define REPLACE 2
                     28: 
                     29: extern char *MAILPARSER;
                     30: 
                     31: char tempfname[50];            /* file name used for making article */
                     32: char original[BUFLEN];         /* file name of original, used in followup */
                     33: char homedir[BUFLEN];          /* HOME environment setting */
                     34: char user[SBUFLEN];            /* user name */
                     35: char ccname[BUFLEN];           /* file name for article copy */
                     36: 
                     37: /* article header information */
                     38: char subject[BUFLEN];
                     39: char distribution[BUFLEN];
                     40: char references[BUFLEN];
                     41: char newsgroups[BUFLEN];
                     42: char moderator[BUFLEN];
                     43: char isfrom[BUFLEN];
                     44: char msgid[BUFLEN];
                     45: char keywords[BUFLEN];
                     46: char summary[BUFLEN];
                     47: int uid;
                     48: 
                     49: char ngsep[] = { NGDELIM, '\0' };      /* == "," */
                     50: 
                     51: char *Progname = "postnews";           /* for xerror */
                     52: 
                     53: time_t fmodtime;
                     54: int ismod = 0;
                     55: char buf[BUFLEN];
                     56: 
                     57: struct distr {
                     58:        char abbr[24];
                     59:        char descr[128];
                     60: } distr[16];
                     61: 
                     62: FILE *xfopen();
                     63: 
                     64: main(argc, argv)
                     65: char *argv[];
                     66: {
                     67:        register int c;
                     68: 
                     69:        init();
                     70: 
                     71:        if (argc == 2) {
                     72:                if (!prefix(argv[1], SPOOL))
                     73:                        xerror("Can only followup to articles in %s", SPOOL);
                     74:                followup(argv[1]);
                     75:                (void) strcpy(original, argv[1]);
                     76:        } else
                     77:        if (askyes("Is this message in response to some other message? ","no")) {
                     78:                char ng[BUFLEN], num[BUFLEN];
                     79:                long i, j, lastnum;
                     80:                register char *p;
                     81:                int fd, dir;
                     82:                char canpost;
                     83: 
                     84:                getpr("In what newsgroup was the article posted? ",ng);
                     85:                if (!valid_ng(ng, &i, &j, &canpost))
                     86:                        if (canpost != 'n' )
                     87:                                byebye("There is no such newsgroup.");
                     88:                        else
                     89:                                byebye("You are not allowed to post to that group.");
                     90: 
                     91:                printf("Valid article numbers are from %ld to %ld\n", j, i);
                     92:                lastnum = i + 1;
                     93:                dir = -1;
                     94: 
                     95:                for(;;) {
                     96:                        getpr("\nWhat was the article number? ", num);
                     97:                        switch(num[0]) {
                     98:                        case '+':
                     99:                                dir = 1;
                    100:                                sprintf(num, "%ld", lastnum + 1);
                    101:                                break;
                    102:                        case '-':
                    103:                                dir = -1;
                    104:                                /* no break */
                    105:                        case '\0':
                    106:                                sprintf(num, "%ld", lastnum + dir);
                    107:                                break;
                    108:                        }
                    109:                        (void) sprintf(original, "%s/%s", SPOOL, ng);
                    110:                        for (p=original+strlen(SPOOL)+1; *p ;++p)
                    111:                                if (*p == '.')
                    112:                                        *p = '/';
                    113:                        (void) strcat(original, "/");
                    114:                        (void) strcat(original, num);
                    115: 
                    116:                        if ((fd=open(original,0)) >= 0) {
                    117:                                (void) close(fd);
                    118:                                printf("\narticle %s\n", original);
                    119:                                if (article_line(original, "From: ", buf))
                    120:                                        printf("%s\n", buf);
                    121:                                if (article_line(original, "Subject: ", buf))
                    122:                                        printf("%s\n", buf);
                    123:                                if (askyes("Is this the one you want? ", "n"))
                    124:                                        break;
                    125:                        } else
                    126:                                printf("I can't find that article.\n");
                    127:                        lastnum = atol(num);
                    128:                }
                    129: 
                    130:                followup(original);
                    131:        } else {
                    132:                do {
                    133:                        getpr("Subject: ", subject);
                    134:                        if (*subject == '?') {
                    135: printf("People read the subject line to learn what your article is about.\n");
                    136: printf("You want it to do the same job as a newspaper headline.\n");
                    137: printf("So type in something both brief and descriptive.\n");
                    138:                                *subject = '\0';
                    139:                        }
                    140:                } while (*subject == '\0');
                    141:                getpr("Keywords: ", keywords);
                    142: 
                    143:                while (!get_newsgroup())
                    144:                        ;
                    145:                check_mod();
                    146:                get_distribution((char *)0);
                    147:        }
                    148: 
                    149:        if (pre_checks())
                    150:                exit(1);
                    151: 
                    152:        prep_article();
                    153:        c = 'e';
                    154:        for (;;) {
                    155:                if (c == 'e') {
                    156:                        edit_article();
                    157:                        post_checks();
                    158:                }
                    159:                do {
                    160:                        do {
                    161:                                getpr("\nWhat now?  [send, edit, list, quit, write] ", buf);
                    162:                                c = buf[0];
                    163:                        } while (c == '\0');
                    164:                        if (isupper(c))
                    165:                                c = tolower(c);
                    166:                        if (c == 'q') {
                    167:                                (void) UNLINK(tempfname);
                    168:                                exit(1);
                    169:                        }
                    170:                        if (c == 'l') {
                    171:                                char *pager = getenv("PAGER");
                    172:                                char lbuf[BUFLEN];
                    173:                                if (pager == NULL || *pager == '\0') {
                    174: #ifdef PAGE
                    175: # ifdef IHCC
                    176:                                        (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE);
                    177: # else /* !IHCC */
                    178:                                        (void) strcpy(lbuf, PAGE);
                    179: # endif /* !IHCC */
                    180:                                        pager = lbuf;
                    181: #else /* !PAGE */
                    182:                                        pager = "cat";
                    183: #endif /* !PAGE */
                    184:                                }
                    185:                                sprintf(buf, "exec %s %s", pager, tempfname);
                    186:                                (void)  system(buf);
                    187:                        }
                    188:                        if (c == 'w') {
                    189:                                register int ifd, ofd, nbytes;
                    190:                                char iobuf[BUFSIZ];
                    191:                                char fname[BUFLEN];
                    192:                                getpr("Filename? ", fname);
                    193:                                if (fname[0] == '\0')
                    194:                                        continue;
                    195:                                ofd = creat(fname, 0666);
                    196:                                if (ofd < 0)
                    197:                                        perror(fname);
                    198:                                else {
                    199:                                        ifd = open(tempfname, 0);
                    200:                                        if (ifd < 0)
                    201:                                                xerror("Can't reopen %s\n", tempfname);
                    202:                                        while ((nbytes = read(ifd, iobuf, BUFSIZ)) > 0 )
                    203:                                                write(ofd, iobuf, nbytes);
                    204:                                        close(ofd);
                    205:                                        close(ifd);
                    206:                                }
                    207:                        }
                    208:                } while (!index("eps", c));
                    209:                if (c != 'e')
                    210:                        post_article(); /* will exit if posted successfully */
                    211:        };
                    212: }
                    213: 
                    214: /*
                    215:  * Find out the topic of interest.
                    216:  */
                    217: get_newsgroup()
                    218: {
                    219:        int n;
                    220:        long i;
                    221:        char canpost;
                    222:        static int first = 1;
                    223: 
                    224:        printf("Newsgroups (enter one at a time, end with a blank line):\n");
                    225:        if (first) {
                    226:                printf("\nThe most relevant newsgroup should be the first, you should\n");
                    227:                printf("add others only if your article really MUST be read by people\n");
                    228:                printf("who choose not to read the appropriate group for your article.\n");
                    229:                printf("But DO use multiple newsgroups rather than posting many times.\n\n");
                    230:                first = 0;
                    231:        }
                    232:        printf("For a list of newsgroups, type ?\n");
                    233:        n = 0;
                    234:        newsgroups[0] = '\0';
                    235: 
                    236:        for(;;) {
                    237:                getpr("> ", buf);
                    238:                if (buf[0] == '\0')
                    239:                        if (n == 0)
                    240:                                return FALSE;
                    241:                        else
                    242:                                return TRUE;
                    243:                if (buf[0] == '?'){
                    244:                        char *pager = getenv("PAGER");
                    245:                        char lbuf[BUFLEN];
                    246:                        if (pager == NULL) {
                    247: #ifdef PAGE
                    248: # ifdef IHCC
                    249:                                (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE);
                    250: # else /* !IHCC */
                    251:                                (void) strcpy(lbuf, PAGE);
                    252: # endif /* !IHCC */
                    253:                                pager = lbuf;
                    254: #else /* !PAGE */
                    255:                                pager = "cat";
                    256: #endif /* !PAGE */
                    257:                        }
                    258:                        printf("These are the currently active groups:\n");
                    259:                        sprintf(buf, "exec %s %s/newsgroups", pager, LIB);
                    260:                        (void) system(buf);
                    261:                        continue;
                    262:                }
                    263:                if (valid_ng(buf, &i, &i, &canpost)) {
                    264:                        if (n++ != 0)
                    265:                                (void) strcat(newsgroups, ngsep);
                    266:                        (void) strcat(newsgroups, buf);
                    267:                } else {
                    268:                        if (canpost == 'n')
                    269:                                printf("You are not allowed to post to %s\n",
                    270:                                        buf);
                    271:                        else
                    272:                                printf("%s is not a valid newsgroup.\n", buf);
                    273:                }
                    274:        }
                    275: }
                    276: 
                    277: /*
                    278:  * Find out how widely the author wants the message distributed.
                    279:  */
                    280: get_distribution(deflt)
                    281:        char *deflt;
                    282: {
                    283:        register int i;
                    284:        register char *r;
                    285:        char def[BUFLEN];
                    286:        char *lastgroup;
                    287: 
                    288:        lastgroup = newsgroups;
                    289:        (void) strcpy(def, newsgroups);
                    290:        r = index(def, NGDELIM);
                    291:        if (r)
                    292:                *r = '\0';
                    293:        r = index(def, '.');
                    294:        if (r) {
                    295:                *r = '\0';
                    296:                if (strcmp(def, "net") == 0)
                    297:                        (void) strcpy(def, "world");
                    298:        } else {
                    299:                distribution[0] = '\0';
                    300:                return;
                    301:        }
                    302: 
                    303:        if (strcmp(def, "to") == 0) {
                    304:                /*
                    305:                 * This only works if "to.xx" is the first (or only)
                    306:                 * newsgroup, but it usually is ..
                    307:                 * Perhaps we should make the distribution be "to.xxx" ??
                    308:                 */
                    309:                distribution[0] = '\0';
                    310:                return;         /* He's probably testing something */
                    311:        }
                    312:        if (deflt != (char *)0)
                    313:                (void) strcpy(def, deflt);
                    314:        if (ngmatch("net.test", newsgroups))
                    315:                (void) strcpy(def, "local");
                    316:        for(;;) {
                    317:                do {
                    318:                        (void) sprintf(buf, "Distribution (default='%s', '?' for help) : ", def);
                    319:                        getpr(buf, distribution);
                    320:                        if (distribution[0] == '\0') {
                    321:                                if (strcmp(def, "*None*") == 0)
                    322:                                        printf("You must enter a distribution, '?' for help.\n");
                    323:                                (void) strcpy(distribution, def);
                    324:                        }
                    325:                } while (strcmp(distribution, "*None*") == 0);
                    326: 
                    327:                /* Did the user ask for help? */
                    328:                if (distribution[0] == '?') {
                    329:                        printf("How widely should your article be distributed?\n\n");
                    330:                        for (i=0; distr[i].abbr[0]; i++)
                    331:                                printf("%s\t%s\n", distr[i].abbr, distr[i].descr);
                    332:                        printf("\nEnter the word that specifies the distribution that you require.\n");
                    333:                        continue;
                    334:                }
                    335: 
                    336:                /* Check that it's a proper distribution */
                    337:                for (i=0; distr[i].abbr[0]; i++) {
                    338:                        if (strncmp(distr[i].abbr, distribution, sizeof(distr[0].abbr)) == 0) {
                    339:                                register int n;
                    340:                                /* Found a match. Do any special rewriting. */
                    341:                                if (strcmp(distribution, "world") == 0)
                    342:                                        strcpy(distribution, "net");
                    343:                                r = newsgroups;
                    344:                                n = strlen(distribution);
                    345:                                /*
                    346:                                 * A distribution of foo is useless
                    347:                                 * if all the newsgroups are in foo.all
                    348:                                 */
                    349:                                for (;;) {
                    350:                                        if (strncmp(r, distribution, n))
                    351:                                                return;
                    352:                                        if ((r = index(r, NGDELIM)) == NULL)
                    353:                                                break;
                    354:                                        ++r;
                    355:                                }
                    356:                                distribution[0] = '\0';
                    357:                                return;
                    358:                        }
                    359:                }
                    360:                if (strcmp(distribution, def) != 0)
                    361:                        printf("Type ? for help.\n");
                    362:                else {
                    363:                        int once = TRUE;
                    364: 
                    365:                        do {
                    366:                                r = lastgroup;
                    367:                                while (r = index(r, NGDELIM))
                    368:                                        if (!prefix(++r, def))
                    369:                                                break;
                    370:                                if (r == NULL) {
                    371:                                        /*
                    372:                                         * no newsgroups are distribution
                    373:                                         * names, and user simply will
                    374:                                         * not type a valid distribution,
                    375:                                         * assume that the default is OK.
                    376:                                         */
                    377:                                        distribution[0] = '\0';
                    378:                                        return;
                    379:                                }
                    380:                                lastgroup = r;
                    381:                                if (once)
                    382:                                        printf("Sorry, '%s' is an unknown distribution.  Type ? for help.\n", def);
                    383:                                once = FALSE;
                    384:                                strcpy(def, r);
                    385:                                r = index(def, NGDELIM);
                    386:                                if (r)
                    387:                                        *r = '\0';
                    388:                                r = index(def, '.');
                    389:                        } while (r == NULL);
                    390:                        *r = '\0';
                    391:                        if (strcmp(def, "net") == 0)
                    392:                                strcpy(def, "world");
                    393:                }
                    394:        }
                    395: }
                    396: 
                    397: /*
                    398:  * Do sanity checks before the author types in the message.
                    399:  */
                    400: pre_checks()
                    401: {
                    402:        if (recording(newsgroups))
                    403:                return 1;
                    404:        return 0;
                    405: }
                    406: 
                    407: /*
                    408:  * Check to see if the newsgroup is moderated.
                    409:  */
                    410: check_mod()
                    411: {
                    412:        register FILE *fd;
                    413:        char ng[BUFLEN], mod[BUFLEN];
                    414: 
                    415:        ismod = 0;
                    416:        (void) sprintf(buf, "%s/%s", LIB, "moderators");
                    417:        fd = xfopen(buf, "r");
                    418: 
                    419:        while (fgets(buf, sizeof buf, fd) != NULL) {
                    420:                twosplit(buf, ng, mod);
                    421:                if (ngmatch(newsgroups, ng)) {
                    422:                        (void) strcpy(moderator, mod);
                    423:                        ismod = 1;
                    424:                }
                    425:        }
                    426:        (void) fclose(fd);
                    427: }
                    428: 
                    429: /*
                    430:  * Set up the temp file with headers.
                    431:  */
                    432: prep_article()
                    433: {
                    434:        FILE *tf, *of;
                    435:        struct stat stbuf;
                    436: 
                    437:        (void) strcpy(tempfname, "/tmp/postXXXXXX");
                    438:        (void) mktemp(tempfname);
                    439: 
                    440:        /* insert a header */
                    441:        tf = xfopen(tempfname, "w");
                    442:        fprintf(tf, "Subject: %s\n", subject);
                    443:        fprintf(tf, "Newsgroups: %s\n", newsgroups);
                    444:        if (distribution[0] != '\0')
                    445:                fprintf(tf, "Distribution: %s\n", distribution);
                    446:        if (ismod)
                    447:                fprintf(tf, "To: %s\n", moderator);
                    448: 
                    449:        if (keywords[0] != '\0')
                    450:                fprintf(tf, "Keywords: %s\n", keywords);
                    451:        if (summary[0] != '\0')
                    452:                fprintf(tf, "Summary: %s\n", summary);
                    453: 
                    454:        if (references[0] != '\0') {
                    455:                fprintf(tf, "References: %s\n\n", references);
                    456: 
                    457:                if (askyes("Do you want to include a copy of the article? ", "no")){
                    458:                        of = xfopen(original, "r");
                    459:                        while (fgets(buf, BUFSIZ, of) != NULL)
                    460:                                if (buf[0] == '\n')     /* skip headers */
                    461:                                        break;
                    462:                        fprintf(tf, "In article %s, %s writes:\n", msgid, isfrom);
                    463:                        while (fgets(buf, BUFSIZ, of) != NULL)
                    464:                                fprintf(tf, "> %s", buf);
                    465:                        (void) fclose(of);
                    466:                        printf("OK, but please edit it to suppress unnecessary verbiage, signatures, etc.\n");
                    467:                }
                    468:        }
                    469: 
                    470:        fprintf(tf, "\n\n");
                    471:        (void) fflush(tf);
                    472:        (void) fstat(fileno(tf), &stbuf);
                    473:        fmodtime = stbuf.st_mtime;
                    474:        (void) fclose(tf);
                    475: }
                    476: 
                    477: edit_article()
                    478: {
                    479:        register char *p;
                    480:        char *editor;
                    481:        char *endflag = "";
                    482:        char *getenv();
                    483: 
                    484:        /* edit the file */
                    485:        editor = getenv("EDITOR");
                    486:        if (editor == NULL)
                    487:                editor = DFTEDITOR;
                    488: 
                    489:        p = editor + strlen(editor) - 2;
                    490:        if (strcmp(p, "vi") == 0)
                    491:                endflag = "+";
                    492: 
                    493:        (void) sprintf(buf, "A=%s;export A;exec %s %s %s",
                    494:                original, editor, endflag, tempfname);
                    495: 
                    496:        (void) system(buf);
                    497: }
                    498: 
                    499: /*
                    500:  * Do sanity checks after the author has typed in the message.
                    501:  */
                    502: post_checks()
                    503: {
                    504:        char group[BUFLEN];
                    505:        register char *c, *p;
                    506:        struct stat stbuf;
                    507: 
                    508:        if (stat(tempfname, &stbuf) < 0) {
                    509:                printf("File deleted - no message posted.\n");
                    510:                (void) UNLINK(tempfname);
                    511:                exit(1);
                    512:        }
                    513: 
                    514:        if (stbuf.st_mtime == fmodtime || stbuf.st_size < 5) {
                    515:                printf("File not modified - no message posted.\n");
                    516:                (void) UNLINK(tempfname);
                    517:                exit(1);
                    518:        }
                    519: 
                    520:        /*
                    521:         * Is this the right number?  Most of the headers are yet to be added
                    522:         */
                    523:        if (stbuf.st_size > 65000) {
                    524:                printf("\nYour message will probably be truncated when it\n");
                    525:                printf("passes through a notesfile site, since it is\n");
                    526:                printf("greater than 65000 characters.\n\n");
                    527:                if (!askyes("Do you still want to post it? ","")) {
                    528:                        sprintf(ccname, "%s/dead.article", homedir);
                    529:                        save_article();
                    530:                        (void) UNLINK(tempfname);
                    531:                        exit(1);
                    532:                }
                    533:        }
                    534: 
                    535:        /*
                    536:         * get the newsgroups from the edited article, in
                    537:         * case they were altered in the editor
                    538:         */
                    539:        if (!article_line(tempfname, "Newsgroups: ", group)) {
                    540:   nogroups:
                    541:                printf("Not sending to any newsgroups - no message posted\n");
                    542:                (void) UNLINK(tempfname);
                    543:                exit(1);
                    544:        }
                    545:        c = &group[11];
                    546:        while (*c == ' ' || *c == '\t')
                    547:                c++;
                    548:        if (*c == '\0')
                    549:                goto nogroups;
                    550:        for (p = newsgroups; *c; c++)   /* copy to newsgroups, w/o blanks */
                    551:                if (*c != ' ' && *c != '\t')
                    552:                        *p++ = *c;
                    553:        *p = '\0';
                    554: 
                    555:        /* Sanity checks for certain newsgroups */
                    556:        if (ngmatch(newsgroups, "all.wanted") && ngmatch(distribution,"net,na,usa,att,btl,eunet,aus")) {
                    557:                printf("Is your message something that might go in your local\n");
                    558:                printf("newspaper, for example a used car ad, or an apartment\n");
                    559:                printf("for rent? ");
                    560:                if (askyes("","")) {
                    561:                        printf("It's pointless to distribute your article widely, since\n");
                    562:                        printf("people more than a hundred miles away won't be interested.\n");
                    563:                        printf("Please use a more restricted distribution.\n");
                    564:                        get_distribution("*None*");
                    565:                        modify_article(tempfname, "Distribution: ", distribution,REPLACE);
                    566:                }
                    567:        }
                    568: 
                    569:        if (ngmatch(newsgroups, "all.jokes")) {
                    570:                if (askyes("Could this be offensive to anyone? ","")) {
                    571:                        getpr("Whom might it offend? ", group);
                    572:                        (void) sprintf(buf," - offensive to %s (rot 13)",group);
                    573:                        modify_article(tempfname, "Subject: ", buf, APPEND);
                    574:                        encode(tempfname);
                    575:                }
                    576:        }
                    577: 
                    578:        if (ngmatch(newsgroups, "net.general")) {
                    579:                if (index(newsgroups, NGDELIM)) {
                    580:                        printf("Everybody in the world reads net.general, so it doesn't make\n");
                    581:                        printf("sense to post to newsgroups in addition to net.general.  If your\n");
                    582:                        printf("article belongs in one of these other newsgroups, then you\n");
                    583:                        printf("should not post to net.general. If it is important enough\n");
                    584:                        printf("for net.general, then you shouldn't post it in other places\n");
                    585:                        printf("as well.        Please reenter the newsgroups.\n");
                    586:                        while (!get_newsgroup())
                    587:                                ;
                    588:                        modify_article(tempfname, "Newsgroups: ", newsgroups,REPLACE);
                    589:                }
                    590:                if (ngmatch(newsgroups, "net.general")) {
                    591:                        printf("net.general is for important announcements.\n");
                    592:                        printf("It is not for items for which you couldn't think\n");
                    593:                        printf("of a better place - those belong in net.misc.\n");
                    594:                        if (!askyes("Are you sure your message belongs in net.general? ","")) {
                    595:                                while (!get_newsgroup())
                    596:                                        ;
                    597:                                modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
                    598:                        }
                    599:                }
                    600:        }
                    601: 
                    602:        if (ngmatch(newsgroups, "net.sources,!net.sources.all")) {
                    603:                if (!article_line(tempfname, "Subject: ", group)) {
                    604:   nosubj:
                    605:                        printf("There seems to be no subject for this article.\n");
                    606:                        getpr("Subject: ", subject);
                    607:                        modify_article(tempfname, "Subject: ", subject, REPLACE);
                    608:                } else {
                    609:                        c = &group[8];
                    610:                        while (*c == ' ' || *c == '\t')
                    611:                                c++;
                    612:                        if (*c == '\0')
                    613:                                goto nosubj;
                    614:                        strcpy(subject, c);
                    615:                }
                    616:                if (ngmatch(newsgroups, "all.wanted") || iswanted(subject)) {
                    617:                        printf("Requests for sources should not be posted to any of\n");
                    618:                        printf("the net.sources newsgroups, please post such requests\n");
                    619:                        printf("to net.wanted.sources only.     Please reenter the newsgroups.\n\n");
                    620:                        while (!get_newsgroup())
                    621:                                ;
                    622:                        modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
                    623:                }
                    624:                if (ngmatch(newsgroups, "net.sources")) {
                    625:                        if (!ngmatch(newsgroups, "net.sources.all") &&
                    626:                            stbuf.st_size < (4*1024)) {
                    627:                                printf("Your article seems rather small to be a source distribution.\n");
                    628:                                if (!askyes("Are you certain that this is really source? ", "")) {
                    629: 
                    630:                                        while (!get_newsgroup())
                    631:                                                ;
                    632:                                        modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
                    633:                                }
                    634:                        }
                    635:                        if (index(newsgroups, NGDELIM)) {
                    636:                                printf("Sources should be posted to one newsgroup only.\n");
                    637:                                printf("Please pick the most appropriate group for your article.\n\n");
                    638:                                while (!get_newsgroup())
                    639:                                        ;
                    640:                                modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
                    641:                        }
                    642:                }
                    643:        }
                    644:        check_mod();
                    645: }
                    646: 
                    647: iswanted(str)
                    648: register char *str;
                    649: {
                    650:        while (*str == ' ')
                    651:                str++;
                    652: 
                    653:        if (prefix(str, "Re:"))
                    654:                return (FALSE);
                    655: 
                    656:        if (isin(str, " wanted ") || isin(str, " can any") ||
                    657:            isin(str, " need ") || isin(str, " please ") || isin(str, " help ")
                    658:            || isin(str, " looking ") || index(str, '?'))
                    659:                return (TRUE);
                    660: 
                    661:        return (FALSE);
                    662: }
                    663: 
                    664: isin(str, words)
                    665: register char *str, *words;
                    666: {
                    667:        register char *p;
                    668:        register sc, wc;
                    669: 
                    670:        p = words;
                    671:        while (sc = *str++) {
                    672:                if ((wc = *p++) == '\0')
                    673:                        return (TRUE);
                    674:                if (wc == ' ') {
                    675:                        if (index(".,!?-; \t\n", sc))
                    676:                                continue;
                    677:                } else {
                    678:                        if (isupper(wc))
                    679:                                wc = tolower(wc);
                    680:                        if (isupper(sc))
                    681:                                sc = tolower(sc);
                    682:                        if (wc == sc)
                    683:                                continue;
                    684:                }
                    685:                str -= p - words - 1;
                    686:                p = words;
                    687:        }
                    688:        if (*p == '\0')
                    689:                return (TRUE);
                    690:        return (FALSE);
                    691: }
                    692: 
                    693: /*
                    694:  * Save a copy of the article in the users NEWSARCHIVE directory.
                    695:  */
                    696: save_article()
                    697: {
                    698:        FILE *in, *out;
                    699:        int c;
                    700:        time_t timenow, time();
                    701:        char *today, *ctime();
                    702:        struct stat stbuf;
                    703:        char filename[BUFLEN];
                    704: 
                    705:        if (stat(ccname, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR) {
                    706:                /*
                    707:                 * It would be much nicer here to write articles
                    708:                 * in MH format (numbered files, in rfc822 format)
                    709:                 *
                    710:                 * one day ..
                    711:                 */
                    712:                (void) sprintf(filename, "%s/author_copy", ccname);
                    713:                (void) strcpy(ccname, filename);
                    714:        }
                    715:        in = xfopen(tempfname, "r");
                    716:        out = xfopen(ccname, "a");
                    717:        timenow = time((time_t)0);
                    718:        today = ctime(&timenow);
                    719:        fprintf(out,"From postnews %s",today);
                    720:        while ((c=getc(in)) != EOF)
                    721:                putc(c, out);
                    722:        putc('\n', out);
                    723:        (void) fclose(in);
                    724:        (void) fclose(out);
                    725: }
                    726: 
                    727: /*
                    728:  * Post the article to the net.
                    729:  */
                    730: post_article()
                    731: {
                    732:        int status;
                    733: 
                    734:        printf("%s article...\n", ismod ? "Mailing" : "Posting" );
                    735:        fflush(stdout);
                    736:        if (ismod)
                    737:                (void) sprintf(buf, "exec %s -t < %s", MAILPARSER, tempfname);
                    738:        else
                    739:                (void) sprintf(buf, "exec %s/%s -h < %s", LIB, "inews", tempfname);
                    740:        status = system(buf);
                    741: 
                    742:        if (status) {
                    743:                printf("Article not %s - exit status %d\n", ismod ? "mailed" : "posted", status);
                    744:                return;
                    745:        } else
                    746:                printf("Article %s successfully.\n", ismod ? "mailed" : "posted" );
                    747: 
                    748:        if (ccname[0]) {
                    749:                printf("A copy has been saved in %s\n", ccname);
                    750:                save_article();
                    751:        }
                    752: 
                    753:        (void) UNLINK(tempfname);
                    754:        exit(0);
                    755: }
                    756: 
                    757: /*
                    758:  * Initialization.
                    759:  */
                    760: init()
                    761: {
                    762:        FILE *fd;
                    763:        register char *p;
                    764:        int i;
                    765:        char *getenv();
                    766:        struct passwd *pw;
                    767: 
                    768:        references[0] = '\0';
                    769:        distribution[0] = '\0';
                    770: 
                    771:        uid = getuid();
                    772:        pw = getpwuid(uid);
                    773:        if (pw == NULL) {
                    774:                fprintf(stderr,"You're not in /etc/passwd\n");
                    775:                exit(1);
                    776:        }
                    777:        p = getenv("HOME");
                    778:        if (p == NULL) {
                    779:                p = getenv("LOGDIR");
                    780:                if (p == NULL) 
                    781:                        p = pw->pw_dir;
                    782:        }
                    783:        (void) strncpy(user, pw->pw_name, SBUFLEN);
                    784:        (void) strcpy(homedir, p);
                    785: 
                    786:        p = getenv("NEWSARCHIVE");
                    787:        if (p != NULL) {
                    788:                if (*p == '\0')
                    789:                        sprintf(ccname, "%s/author_copy", homedir);
                    790:                else
                    791:                        strcpy(ccname, p);
                    792:        }
                    793: 
                    794:        pathinit();
                    795:        (void) sprintf(buf, "%s/%s", LIB, "distributions");
                    796:        fd = xfopen(buf, "r");
                    797:        for (i=0; !feof(fd); i++) {
                    798:                if (fgets(buf, sizeof buf, fd) == NULL)
                    799:                        break;
                    800:                twosplit(buf, distr[i].abbr,distr[i].descr);
                    801:        }
                    802:        (void) fclose(fd);
                    803: }
                    804: 
                    805: /*
                    806:  * Split a line of the form
                    807:  *             text whitespace text
                    808:  * into two strings.   Also trim off any trailing newline.
                    809:  * This is destructive on src.
                    810:  */
                    811: twosplit(src, dest1, dest2)
                    812: char *src, *dest1, *dest2;
                    813: {
                    814:        register char *p;
                    815: 
                    816:        (void) nstrip(src);
                    817:        for (p=src; isalnum(*p) || ispunct(*p); p++)
                    818:                ;
                    819:        *p++ = 0;
                    820:        for ( ; isspace(*p); p++)
                    821:                ;
                    822:        (void) strcpy(dest1, src);
                    823:        (void) strcpy(dest2, p);
                    824: }
                    825: 
                    826: /*
                    827:  * Get a yes or no answer to a question.       A default may be used.
                    828:  */
                    829: askyes(msg, def)
                    830: char *msg, *def;
                    831: {
                    832:        for(;;) {
                    833:                printf("%s", msg);
                    834:                buf[0] = 0;
                    835:                (void) gets(buf);
                    836:                switch(buf[0]) {
                    837:                case 'y':
                    838:                case 'Y':
                    839:                        return TRUE;
                    840:                case 'n':
                    841:                case 'N':
                    842:                        return FALSE;
                    843:                case '\0':
                    844:                        switch(*def) {
                    845:                        case 'y':
                    846:                        case 'Y':
                    847:                                return TRUE;
                    848:                        case 'n':
                    849:                        case 'N':
                    850:                                return FALSE;
                    851:                        }
                    852:                default:
                    853:                        printf("Please answer yes or no.\n");
                    854:                }
                    855:        }
                    856: }
                    857: 
                    858: /*
                    859:  * Get a character string into buf, using prompt msg.
                    860:  */
                    861: getpr(msg, bptr)
                    862: char *msg, *bptr;
                    863: {
                    864:        static int numeof = 0;
                    865:        printf("%s", msg);
                    866:        (void) gets(bptr);
                    867:        (void) nstrip(bptr);
                    868:        if (feof(stdin)) {
                    869:                if (numeof++ > 3) {
                    870:                        fprintf(stderr,"Too many EOFs\n");
                    871:                        exit(1);
                    872:                }
                    873:                clearerr(stdin);
                    874:        }
                    875: }
                    876: 
                    877: byebye(mesg)
                    878: char *mesg;
                    879: {
                    880:        printf("%s\n", mesg);
                    881:        exit(1);
                    882: }
                    883: 
                    884: /*
                    885:  * make a modification to the header of an article
                    886:  *
                    887:  *      fname -- name of article
                    888:  *      field -- header field to modify
                    889:  *      line   -- modification line
                    890:  *      how     -- APPEND or REPLACE
                    891:  *
                    892:  * example:
                    893:  *      modify_article("/tmp/article" , "Subject:" , "new subject" , REPLACE);
                    894:  *
                    895:  *
                    896:  */
                    897: modify_article(fname, field, line, how)
                    898: char *fname, *field, *line;
                    899: {
                    900:        FILE *fpart, *fptmp;
                    901:        char *temp2fname = "/tmp/postXXXXXX";
                    902:        char lbfr[BUFLEN];
                    903:        register found = FALSE;
                    904: 
                    905:        mktemp(temp2fname);
                    906: 
                    907:        fptmp = xfopen(temp2fname, "w");
                    908:        fpart = xfopen(fname, "r");
                    909: 
                    910:        while (fgets(lbfr, BUFLEN, fpart) != NULL) {
                    911:                if (prefix(lbfr, field)) {
                    912:                        found = TRUE;
                    913:                        (void) nstrip(lbfr);
                    914:                        if (how == APPEND) {
                    915:                                /* append to current field */
                    916:                                (void) strcat(lbfr, line);
                    917:                                (void) strcat(lbfr, "\n");
                    918:                        } else
                    919:                                /* replace current field */
                    920:                                (void) sprintf(lbfr, "%s%s\n", field, line);
                    921:                }
                    922:                (void) fputs(lbfr, fptmp);
                    923:        }
                    924: 
                    925:        fclose(fpart);
                    926:        fclose(fptmp);
                    927: 
                    928:        fptmp = xfopen(temp2fname, "r");
                    929:        fpart = xfopen(fname, "w");
                    930: 
                    931:        if (!found)
                    932:                fprintf(fpart, "%s%s\n", field, line);
                    933:        while (fgets(buf,BUFLEN,fptmp) != NULL)
                    934:                (void) fputs(buf, fpart);
                    935: 
                    936:        (void) fclose(fpart);
                    937:        (void) fclose(fptmp);
                    938:        (void) UNLINK(temp2fname);
                    939: }
                    940: 
                    941: 
                    942: /* verify that newsgroup exists, and get number of entries */
                    943: valid_ng(ng, maxart, minart, canpost)
                    944: char *ng;
                    945: long *maxart, *minart;
                    946: char *canpost;
                    947: {
                    948:        char ng_check[BUFLEN], ng_read[BUFLEN];
                    949:        FILE *fp;
                    950: 
                    951:        fp = xfopen(ACTIVE, "r");
                    952:        while (fgets(ng_read, BUFLEN, fp) != NULL) {
                    953:                switch (sscanf(ng_read, "%s %ld %ld %c", ng_check, maxart, minart, canpost)) {
                    954:                case 2:
                    955:                        *minart = 1;
                    956:                        /* fall through */
                    957:                case 3:
                    958:                        *canpost = 'y';
                    959:                        /* fall through */
                    960:                case 4:
                    961:                        break;
                    962: 
                    963:                default:
                    964:                        printf("Active file (%s) corrupted. ", ACTIVE);
                    965:                        byebye("Seek help!");
                    966:                }
                    967:                        
                    968:                if (strcmp(ng_check, ng) == 0) {
                    969:                        (void) fclose(fp);
                    970:                        if (*canpost == 'y') {
                    971: #ifdef FASCIST
                    972:                                if (uid && uid != ROOTID && fascist(user, ng)) {
                    973:                                        *canpost = 'n';
                    974:                                        return FALSE;
                    975:                                }
                    976: #endif FASCIST
                    977:                                return TRUE;
                    978:                        } else
                    979:                                return FALSE;
                    980:                }
                    981:        }
                    982:        *canpost = 'i';
                    983:        *maxart = 0;
                    984:        *minart = 0;
                    985:        (void) fclose(fp);
                    986:        return FALSE;
                    987: }
                    988: 
                    989: /* get the line specified by field from an article */
                    990: article_line(article, field, line)
                    991: char *article, *field, *line;
                    992: {
                    993:        FILE *fp;
                    994:        char *c;
                    995: 
                    996:        fp = xfopen(article,"r");
                    997:        while ((c=fgets(line,BUFLEN,fp)) != NULL && !prefix(line, field))
                    998:                if (line[0] == '\n') {
                    999:                        c = NULL;
                   1000:                        break;
                   1001:                }
                   1002:        (void) fclose(fp);
                   1003:        if (c != NULL) {
                   1004:                (void) nstrip(line);
                   1005:                return TRUE;
                   1006:        } else {
                   1007:                line[0] = '\0';
                   1008:                return FALSE;
                   1009:        }
                   1010: }
                   1011: 
                   1012: /* get the header information for a followup article */
                   1013: followup(baseart)
                   1014: register char *baseart;
                   1015: {
                   1016:        register char *p;
                   1017: 
                   1018:        /* subject */
                   1019:        if (article_line(baseart, "Subject: ", buf)) {
                   1020:                p = buf+9;
                   1021:                for ( ; ; ) {
                   1022:                        while (*p == ' ' || *p == '\t')
                   1023:                                ++p;
                   1024:                        if ((*p != 'r' && *p != 'R') ||
                   1025:                                (p[1] != 'e' && p[1] != 'E') ||
                   1026:                                (p[2] != ':' && p[2] != ' '))
                   1027:                                        break;
                   1028:                        p += 3;
                   1029:                }
                   1030:                (void) sprintf(subject, "Re: %s", p);
                   1031:        } else {
                   1032:                if (article_line(baseart, "From: ", buf))
                   1033:                        (void) sprintf(subject, "Re: orphan response from %s", buf);
                   1034:                else
                   1035:                        (void) strcpy(subject, "Re: orphan response");
                   1036:        }
                   1037: 
                   1038:        /* newsgroup */
                   1039:        if (article_line(baseart, "Newsgroups: ", buf))
                   1040:                (void) strcpy(newsgroups, buf+12);
                   1041:        if (ngmatch(newsgroups, "net.general"))
                   1042:                (void) strcpy(newsgroups,"net.followup");
                   1043:        if (ngmatch(newsgroups, "net.sources,!net.sources.all"))
                   1044:                (void) strcpy(newsgroups,"net.sources.d");
                   1045:        if (ngmatch(newsgroups, "net.jobs")) {
                   1046:                printf("net.jobs is for the direct posting of job announcements and requests.\n");
                   1047:                printf("it is not for discussion. You followup has been directed to net.misc\n");
                   1048:                (void) strcpy(newsgroups,"net.misc");
                   1049:        }
                   1050: 
                   1051:        /* moderator */
                   1052:        check_mod();
                   1053: 
                   1054:        /* distribution */
                   1055:        if (article_line(baseart, "Distribution: ", buf))
                   1056:                (void) strcpy(distribution, buf+14);
                   1057: 
                   1058:        /* references */
                   1059:        if (article_line(baseart, "References: ", buf)) {
                   1060:                register char *rcp;
                   1061:                (void) strcpy(references, buf+12);
                   1062:                (void) strcat(references, " ");
                   1063:                /* keep the number of references to a reasonable number */
                   1064:                rcp = rindex(references, ' '); /* Can not fail */
                   1065:                while ((int)(rcp - references) > 70) {
                   1066:                        while (*--rcp != ' ')
                   1067:                                ;
                   1068:                        rcp[1] = '\0';
                   1069:                }
                   1070:        }
                   1071:        if (article_line(baseart, "Message-ID: ", buf)) {
                   1072:                (void) strcat(references, buf+12);
                   1073:                (void) strcpy(msgid, buf+12);
                   1074:        }
                   1075: 
                   1076:        if (article_line(baseart, "From: ", buf))
                   1077:                (void) strcpy(isfrom, buf+6);
                   1078: 
                   1079:        if (article_line(baseart, "Keywords: ", buf))
                   1080:                (void) strcpy(keywords, buf+10);
                   1081: 
                   1082:        if (article_line(baseart, "Followup-To: ", buf)) {
                   1083:                (void) strcpy(newsgroups, buf+13);
                   1084:                if (strcmp(newsgroups, "poster") == 0)
                   1085:                        byebye("Mail followups directly to poster.");
                   1086:        }
                   1087: 
                   1088:        get_summary();
                   1089: }
                   1090: 
                   1091: get_summary()
                   1092: {
                   1093:        register char *p;
                   1094:        register i;
                   1095: 
                   1096:        printf("Please enter a short summary of your contribution to the discussion\n");
                   1097:        printf("Just one or two lines ...   (end with a blank line)\n");
                   1098:        p = summary;
                   1099:        for (i = 0; i < 3; i++) {       /* 3 * 80 < 256, should be safe .. */
                   1100:                getpr(">\t", p);
                   1101:                if (*p == '\0')
                   1102:                        break;
                   1103:                p = index(p, '\0');
                   1104:                (void) strcpy(p, "\n\t ");
                   1105:                p += 3;
                   1106:        }
                   1107:        if (p > summary)
                   1108:                p[-3] = '\0';
                   1109: }
                   1110: 
                   1111: encode(article)
                   1112: char *article;
                   1113: {
                   1114:        FILE *fpart, *fphead, *fpcoded;
                   1115:        char *headerfile = "/tmp/pheadXXXXXX";
                   1116:        char *codedfile = "/tmp/pcodeXXXXXX";
                   1117: 
                   1118:        (void) mktemp(headerfile);
                   1119:        (void) mktemp(codedfile);
                   1120: 
                   1121:        fpart = xfopen(article, "r");
                   1122: 
                   1123:        /* place article header in "headerfile" file */
                   1124:        fphead = xfopen(headerfile, "w");
                   1125:        while (fgets(buf, BUFLEN, fpart) != NULL) {
                   1126:                (void) fputs(buf, fphead);
                   1127:                if (buf[0] == '\n')
                   1128:                        break;
                   1129:        }
                   1130:        (void) fclose(fphead);
                   1131: 
                   1132:        /* place article body in "codedfile" file */
                   1133:        fpcoded = xfopen(codedfile, "w");
                   1134:        while (fgets(buf, BUFLEN, fpart) != NULL)
                   1135:                (void) fputs(buf, fpcoded);
                   1136:        (void) fclose(fpcoded);
                   1137:        (void) fclose(fpart);
                   1138: 
                   1139:        /* encode body and put back together with header */
                   1140:        (void) rename(headerfile, article);
                   1141: 
                   1142:        (void) sprintf(buf,"exec %s/%s 13 < %s >> %s\n", LIB, "caesar", codedfile, article);
                   1143:        printf("Encoding article -- please stand by\n");
                   1144:        if (system(buf)) {
                   1145:                printf("encoding failed");
                   1146:                exit(2);
                   1147:        }
                   1148:        (void) UNLINK(codedfile);
                   1149: }
                   1150: 
                   1151: 
                   1152: /*
                   1153:  * Print a recorded message warning the poor luser what he is doing
                   1154:  * and demand that he understands it before proceeding.  Only do
                   1155:  * this for newsgroups listed in LIBDIR/recording.
                   1156:  */
                   1157: recording(ngrps)
                   1158: char *ngrps;
                   1159: {
                   1160:        char recbuf[BUFLEN];
                   1161:        FILE *fd;
                   1162:        char nglist[BUFLEN], fname[BUFLEN];
                   1163:        int  c, n, yes, retval = 0;
                   1164: 
                   1165:        (void) sprintf(recbuf, "%s/%s", LIB, "recording");
                   1166:        fd = fopen(recbuf, "r");
                   1167:        if (fd == NULL)
                   1168:                return 0;
                   1169:        while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) {
                   1170:                (void) sscanf(recbuf, "%s %s", nglist, fname);
                   1171:                if (ngmatch(ngrps, nglist)) {
                   1172:                        (void) fclose(fd);
                   1173:                        if (fname[0] == '/')
                   1174:                                (void) strcpy(recbuf, fname);
                   1175:                        else
                   1176:                                (void) sprintf(recbuf, "%s/%s", LIB, fname);
                   1177:                        fd = fopen(recbuf, "r");
                   1178:                        if (fd == NULL)
                   1179:                                return 0;
                   1180:                        while ((c = getc(fd)) != EOF)
                   1181:                                putc(c, stderr);
                   1182:                        fprintf(stderr, "Do you understand this?  Hit <return> to proceed, <BREAK> to abort: ");
                   1183:                        n = read(2, recbuf, 100);
                   1184:                        c = recbuf[0];
                   1185:                        yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
                   1186:                        if (n <= 0 || !yes)
                   1187:                                retval = -1;
                   1188:                }
                   1189:        }
                   1190:        return retval;
                   1191: }
                   1192: 
                   1193: xxit(i)
                   1194: {
                   1195:        exit(i);
                   1196: }
                   1197: 
                   1198: #if !defined(BSD4_2) && !defined(BSD4_1C)
                   1199: rename(from,to)
                   1200: register char *from, *to;
                   1201: {
                   1202:        (void) unlink(to);
                   1203:        if (link(from, to) < 0)
                   1204:                return -1;
                   1205: 
                   1206:        (void) unlink(from);
                   1207:        return 0;
                   1208: }
                   1209: #endif /* !BSD4_2 && ! BSD4_1C */

unix.superglobalmegacorp.com

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