|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.