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