|
|
1.1 ! root 1: From cbosg!harpo!npois!ucbvax!ARPAVAX:CAD:teklabs!tekmdp!azure!stevenm Thu Apr 15 16:36:59 1982 ! 2: Subject: Some MH Mail hooks for news ! 3: Newsgroups: net.sources ! 4: ! 5: Here are some modifications to readnews (module readr.c) which ! 6: allow use of the MHMAIL 'comp' program for replying to articles, ! 7: and the similar 'submit' program (just like comp) for submitting ! 8: new or followup articles. The 'submit' program itself is included. ! 9: The modifications enclosed are to 'readr.c', 'header.c', 'defs.h', ! 10: and 'Makefile.v7'. The source and manual page for 'submit' are ! 11: also enclosed. ! 12: ! 13: Note that you will have to have the MH system already for 'submit' ! 14: to compile, because it depends heavily on routines in the MH ! 15: libraries. Also note that we run the Feb 1980 release of MH Mail, ! 16: and if any of the subroutine calls made by 'submit' have changed, ! 17: it may not work. ! 18: ! 19: I would like to hear from anyone who actually uses this code, ! 20: or is working on integrating MH and News, so that we can share ! 21: our work. ! 22: ! 23: S. McGeady ! 24: ! 25: teklabs!stevenm ! 26: ! 27: ! 28: ! 29: ############# ! 30: # readr.c # ! 31: ############# ! 32: ! 33: 32c32 ! 34: < char *ptr1, *ptr2, *ptr3; /* for reply manipulation */ ! 35: --- ! 36: > char *ptr1, *ptr2, *ptr3, *ptr4;/* for reply manipulation */ ! 37: ! 38: [shortly after case 'r':] ! 39: ! 40: 393a394,396 ! 41: > ptr2 = h.ident; ! 42: > ptr3 = h.title; ! 43: > ptr4 = h.subdate; ! 44: 396c399 ! 45: < if (*hbuf1.path) ! 46: --- ! 47: > if (*hbuf1.path) { ! 48: 397a401,404 ! 49: > ptr2 = hbuf1.ident; ! 50: > ptr3 = hbuf1.title; ! 51: > ptr4 = hbuf1.subdate; ! 52: > } ! 53: 428a436,467 ! 54: > #ifdef MHMAIL ! 55: > ! 56: > { ! 57: > char *tmpp; ! 58: > FILE *tfd; ! 59: > extern char *mktemp(); ! 60: > ! 61: > tmpp = mktemp("/tmp/newsXXXXXX"); ! 62: > if ((tfd = fopen(tmpp, "w")) == NULL) { ! 63: > fprintf(ofp, "Can't create tmpfile\n"); ! 64: > break; ! 65: > } ! 66: > ! 67: > fprintf(tfd, "To: %s\n", rcbuf); ! 68: > fprintf(tfd, "Subject: "); ! 69: > ! 70: > if (*bptr == '\0') { ! 71: > if (strncmp(ptr3, "Re: ", 4)) { ! 72: > fprintf(tfd, "Re: "); ! 73: > } ! 74: > fprintf(tfd, "%s\n", ptr3); ! 75: > } else { ! 76: > fprintf(tfd, "%s\n", bptr); ! 77: > } ! 78: > fprintf(tfd, "In-reply-to: Your news article %s of %s\n", ptr2, ptr4); ! 79: > fprintf(tfd, "-----------------\n"); ! 80: > fclose(tfd); ! 81: > sprintf(bfr, "%s %s %s", COMP, DFLAG, tmpp); ! 82: > system(bfr); ! 83: > unlink(tmpp); ! 84: > } ! 85: > #else ! 86: 438a478 ! 87: > #endif ! 88: 440d479 ! 89: < ! 90: ! 91: [shortly after "case 'f':"] ! 92: ! 93: 547a587,592 ! 94: > #ifdef MHMAIL ! 95: > { ! 96: > char *tmpp; ! 97: > FILE *tfd; ! 98: > extern char *mktemp(); ! 99: > ! 100: 550a596 ! 101: > ! 102: 558a605,645 ! 103: > while (isspace(*bptr)) ! 104: > bptr++; ! 105: > ! 106: > launder(ptr2); ! 107: > ! 108: > tmpp = mktemp("/tmp/newsXXXXXX"); ! 109: > if ((tfd = fopen(tmpp, "w")) == NULL) { ! 110: > fprintf(ofp, "Can't create tmpfile\n"); ! 111: > break; ! 112: > } ! 113: > fprintf(tfd, "Newsgroups: %s\n", ptr2); ! 114: > sprintf(bfr, "%s %s %s", SUBMIT, DFLAG, tmpp); ! 115: > fprintf(tfd, "Subject: "); ! 116: > ! 117: > if (*bptr == '\0') { ! 118: > if (strncmp(tfilename, "Re: ", 4)) { ! 119: > fprintf(tfd, "Re: "); ! 120: > } ! 121: > fprintf(tfd, "%s\n", tfilename); ! 122: > } else { ! 123: > fprintf(tfd, "%s\n", bptr); ! 124: > } ! 125: > fprintf(tfd, "Followup-to: %s\n", ptr3); ! 126: > fprintf(tfd, "-----------------\n"); ! 127: > fclose(tfd); ! 128: > ! 129: > system(bfr); ! 130: > unlink(tmpp); ! 131: > } ! 132: > #else ! 133: > tfilename = h.title; ! 134: > ptr2 = h.nbuf; ! 135: > ptr3 = h.ident; ! 136: > if (*bptr == '-') { ! 137: > if (*hbuf1.title && *hbuf1.nbuf) { ! 138: > tfilename = hbuf1.title; ! 139: > ptr2 = hbuf1.nbuf; ! 140: > ptr3 = hbuf1.ident; ! 141: > } ! 142: > bptr++; ! 143: > } ! 144: 617a705 ! 145: > #endif ! 146: 619d706 ! 147: < ! 148: ! 149: ! 150: ############# ! 151: # header.c # ! 152: ############# ! 153: ! 154: 64c64 ! 155: < #define SUBMIT 4 ! 156: --- ! 157: > #define SUBMT 4 ! 158: 104c104 ! 159: < case SUBMIT: ! 160: --- ! 161: > case SUBMT: ! 162: 181c181 ! 163: < return SUBMIT; ! 164: --- ! 165: > return SUBMT; ! 166: ! 167: ! 168: ############# ! 169: # defs.h # ! 170: ############# ! 171: ! 172: [Add these lines] ! 173: ! 174: > #define MHMAIL 1 ! 175: > ! 176: > #ifdef MHMAIL ! 177: > #define SUBMIT "/usr/bin/submit" ! 178: > #define COMP "/usr/bin/comp" ! 179: > #define DFLAG "-form" ! 180: > #endif ! 181: > ! 182: ! 183: ############# ! 184: # submit.c # ! 185: ############# ! 186: ! 187: /* ! 188: * this program uses the MH Mail system subroutine librarys ! 189: * found in subs.a and strings.a in /usr1/src/cmd/mh ! 190: * 'mh.h' is also there ! 191: */ ! 192: ! 193: #include "mh.h" ! 194: #include <stdio.h> ! 195: #include <strings.h> ! 196: #include <signal.h> ! 197: #include <sys/types.h> ! 198: #include <sys/stat.h> ! 199: ! 200: /* ! 201: * submit - submit a note to the Duke NewsNet news service ! 202: * ! 203: ******************************************************************* ! 204: * ! 205: * 27-aug-80 sdg Written ! 206: * 02-nov-80 sdg fixed bug that inserted \n every 512 characters ! 207: * ! 208: * 6/24/81 mcg hacked from the 'post' program ! 209: * ! 210: * 7/27/81 mcg modified to take 'post' entrypoint, and to ! 211: * back the input file up in ',<infile>' ! 212: * changed all error messages to print argv[0] ! 213: * instead of 'submit' ! 214: * ! 215: * 12/29/81 mcg modfied for B news ! 216: * ! 217: * 4/15/82 mcg modified for 2.3 B News ! 218: */ ! 219: ! 220: #define NONE 0 ! 221: #define DEFAULTGROUP "general" ! 222: #define NEWSCOMPS "newscomps" ! 223: #define STDNEWSCOMPS LIBDIR/newscomps" ! 224: #define NEWSDIR SPOOLDIR" ! 225: #define NEWSDRAFT "ndraft" ! 226: ! 227: #define MAXSUBJ 128 ! 228: ! 229: char *newsproc = "inews"; ! 230: char *myname; ! 231: ! 232: char *anyul[] = { ! 233: "no", 0, ! 234: "yes", 0, ! 235: "use", 0, ! 236: "list", 0, ! 237: 0 ! 238: }; ! 239: ! 240: char *any[] = { ! 241: "no", 0, ! 242: "yes", 0, ! 243: 0 ! 244: }; ! 245: ! 246: char *alfeqs[] = { ! 247: "list", 0, /* 0 */ ! 248: "format", 0, /* 1 */ ! 249: "edit [<editor>]", 0, /* 2 */ ! 250: "quit [delete]", 0, /* 3 */ ! 251: "submit", 0, /* 4 */ ! 252: "post", 0, /* same as submit */ ! 253: 0 ! 254: }; ! 255: ! 256: ! 257: struct swit switches[] = { ! 258: "editor editor", 0, /* 0 */ ! 259: "form formfile", 0, /* 1 */ ! 260: "use", 0, /* 2 */ ! 261: "nouse", 0, /* 3 */ ! 262: "dfile draftfile",0, /* 4 */ ! 263: "debug", 0, /* 5 */ ! 264: "help", 4, /* 6 */ ! 265: 0, 0 ! 266: }; ! 267: ! 268: char *rindex(); ! 269: ! 270: int debug = 0; ! 271: ! 272: main(argc, argv) ! 273: char *argv[]; ! 274: { ! 275: register char *cp; ! 276: register int in; ! 277: register int out; ! 278: ! 279: int use; ! 280: int cnt; ! 281: int status; ! 282: int intr; ! 283: ! 284: char buf[BUFSIZ]; ! 285: char *newsgroup; ! 286: char *ed; ! 287: char *file; ! 288: char *form; ! 289: ! 290: static char path[128]; ! 291: ! 292: char **ap; ! 293: char *arguments[50]; ! 294: char **argp; ! 295: ! 296: myname = argv[0]; ! 297: ! 298: form = 0; use = 0; file = 0; ed = 0; ! 299: ! 300: cp = r1bindex(argv[0], '/'); ! 301: ! 302: if((cp = m_find(cp)) != NULL) { ! 303: ap = brkstring(cp = getcpy(cp), " ", '\n'); ! 304: ap = copyip(ap, arguments); ! 305: } else ! 306: ap = arguments; ! 307: ! 308: copyip(argv+1, ap); ! 309: ! 310: argp = arguments; ! 311: ! 312: while(cp = *argp++) { ! 313: if(*cp == '-') { ! 314: switch(smatch(++cp, switches)) { ! 315: ! 316: case -2: ! 317: ambigsw(cp, switches); /* ambiguous */ ! 318: goto leave; /* unknown */ ! 319: ! 320: case -1: ! 321: fprintf(stderr, "%s: -%s unknown\n", myname, cp); ! 322: goto leave; ! 323: ! 324: ! 325: case 0: ! 326: if(!(ed = *argp++)) { /* -editor */ ! 327: missing: fprintf(stderr, "%s: Missing argument ", myname); ! 328: fprintf(stderr, "for %s switch\n", argp[-2]); ! 329: goto leave; ! 330: } ! 331: ! 332: continue; ! 333: ! 334: case 1: ! 335: if(!(form = *argp++)) /* -form */ ! 336: goto missing; ! 337: continue; ! 338: ! 339: case 2: ! 340: use = 1; ! 341: continue; /* -use */ ! 342: ! 343: case 3: ! 344: use = 0; ! 345: continue; /* -nouse */ ! 346: ! 347: case 4: ! 348: if(!(file = *argp++)) /* -dfile */ ! 349: goto missing; ! 350: continue; ! 351: ! 352: case 5: ! 353: debug++; ! 354: continue; /* -debug */ ! 355: ! 356: case 6: ! 357: help("submit/post [switches]", switches); ! 358: goto leave; ! 359: } ! 360: ! 361: } ! 362: ! 363: } ! 364: ! 365: if(form) { ! 366: if((in = open(m_maildir(form), 0)) < 0) { ! 367: fprintf(stderr, "%s: Can't open form file: %s\n", myname, form); ! 368: goto leave; ! 369: } ! 370: } else if((in = open(m_maildir(NEWSCOMPS), 0)) < 0 && ! 371: (in = open(STDNEWSCOMPS, 0)) < 0) { ! 372: fprintf(stderr, "%s: Can't open default components file!!\n", myname); ! 373: goto leave; ! 374: } ! 375: ! 376: if(!file) ! 377: file = NEWSDRAFT; ! 378: ! 379: copy(m_maildir(file), path); ! 380: ! 381: if((out = open(path, 0)) >= 0) { ! 382: ! 383: cp = concat("\n\"", path, "\" exists; delete? ", 0); ! 384: ! 385: if(use || fdcompare(in, out)) ! 386: goto editit; ! 387: ! 388: while((status = gans(cp, anyul)) == 3) ! 389: showfile(path); ! 390: ! 391: if(status == 2) { ! 392: use++; ! 393: goto editit; ! 394: } ! 395: ! 396: if(status == 0) ! 397: goto leave; ! 398: ! 399: close(out); ! 400: ! 401: } else if(use) { ! 402: fprintf(stderr, "%s: \"%s\" doesn't exist!\n", myname, path); ! 403: goto leave; ! 404: } ! 405: ! 406: if((out = creat(path, m_gmprot())) < 0) { ! 407: fprintf(stderr, "%s: Can't create \"%s\"\n", myname, path); ! 408: goto leave; ! 409: } ! 410: ! 411: do { ! 412: if(cnt = read(in, buf, sizeof buf)) ! 413: write(out, buf, cnt); ! 414: } while(cnt == sizeof buf); ! 415: ! 416: close(in); ! 417: ! 418: ! 419: editit: ! 420: ! 421: close(out); ! 422: ! 423: if(m_edit(&ed, path, use, NONE) < 0) ! 424: goto leave; ! 425: ! 426: for(;;) { ! 427: if(!(argp = getans("\nWhat now? ", alfeqs))) ! 428: goto leave; ! 429: ! 430: switch(smatch(*argp, alfeqs)) { ! 431: ! 432: case 0: ! 433: showfile(path); /* list */ ! 434: break; ! 435: ! 436: case 1: ! 437: if (m_format(path, use) == -1) /* format */ ! 438: goto leave; ! 439: break; ! 440: ! 441: case 2: ! 442: if(*++argp) /* edit */ ! 443: ed = *argp; ! 444: ! 445: if(m_edit(&ed, path, use, NONE) == -1) ! 446: goto leave; ! 447: ! 448: break; ! 449: ! 450: case 3: ! 451: if(*++argp && *argp[0] == 'd') /* quit */ ! 452: if(unlink(path) == -1) { ! 453: fprintf(stderr, "Can't unlink %s ", path); ! 454: perror(""); ! 455: } ! 456: goto leave; ! 457: ! 458: ! 459: case 4: /* submit */ ! 460: case 5: /* post */ ! 461: ! 462: if (!postit(path)) ! 463: goto leave; ! 464: ! 465: break; ! 466: ! 467: default: ! 468: fprintf(stderr, "%s: illegal option\n", myname); /*##*/ ! 469: break; ! 470: } ! 471: } ! 472: ! 473: leave: ! 474: ! 475: m_update(); ! 476: done(0); ! 477: } ! 478: ! 479: long convtime(tp) ! 480: register char *tp; ! 481: { ! 482: ! 483: if (tp == NULL) return(0L); ! 484: ! 485: while (*tp == ' ' || *tp == '\t' || *tp == '\n') tp++; ! 486: ! 487: if (*tp == '\0') return(0L); ! 488: ! 489: return(-1L); /* error in processing */ ! 490: } ! 491: ! 492: char *mktemp(); ! 493: ! 494: postit(pathname) ! 495: char *pathname; ! 496: { ! 497: FILE *pfile; ! 498: FILE *tfile; ! 499: char *tmpname; ! 500: extern int errno; ! 501: ! 502: int state; ! 503: int compnum; ! 504: int firstbody; ! 505: int retcode; ! 506: ! 507: char name[NAMESZ]; ! 508: char buf[BUFSIZ]; ! 509: char tmp[BUFSIZ]; ! 510: char yatmp[BUFSIZ]; ! 511: ! 512: char *newsgroup; ! 513: char *p; ! 514: char *expdate; ! 515: char *subjp; ! 516: char *follow; ! 517: ! 518: struct stat statb; ! 519: ! 520: int pid; ! 521: int wpid; ! 522: int status; ! 523: int i; ! 524: ! 525: retcode = 0; ! 526: pfile = 0; ! 527: tfile = 0; ! 528: tmpname = 0; ! 529: ! 530: ! 531: if ((pfile = fopen(pathname, "r")) == NULL) { ! 532: fprintf(stderr, "%s: Can't open %s\n", myname, pathname); ! 533: retcode = 1; ! 534: goto leave; ! 535: } ! 536: ! 537: if (!debug) { ! 538: tmpname = mktemp("/tmp/postXXXXXX"); ! 539: ! 540: if ((tfile = fopen(tmpname, "w")) == NULL) { ! 541: fprintf(stderr, "%s: Can't create %s\n", myname, tmpname); ! 542: retcode = 1; ! 543: goto leave; ! 544: } ! 545: chmod(tmpname, 0644); ! 546: } else { ! 547: tfile = stdout; ! 548: } ! 549: ! 550: state = FLD, compnum = 0, firstbody = 0, expdate = 0, subjp = 0; ! 551: follow = 0; ! 552: ! 553: for(;;) { ! 554: ! 555: state = m_getfld(state, name, buf, sizeof buf, pfile); ! 556: ! 557: switch(state) { ! 558: case FLD: ! 559: case FLDEOF: ! 560: case FLDPLUS: ! 561: if (uleq(name, "subject") || uleq(name, "title")) { ! 562: subjp = add(buf, subjp); ! 563: } else { ! 564: if (uleq(name, "to") || ! 565: uleq(name, "newsgroup") || ! 566: uleq(name, "newsgroups")) { ! 567: newsgroup = add(buf, newsgroup); ! 568: } else { ! 569: if (uleq(name, "followup-to")) { ! 570: follow = add(buf, follow); ! 571: } else { ! 572: fprintf(stderr, "%s: unrecognized field %s\n", ! 573: myname, name); ! 574: retcode = 2; ! 575: goto leave; ! 576: } ! 577: } ! 578: } ! 579: break; ! 580: ! 581: case BODY: ! 582: case BODYEOF: ! 583: ! 584: if (!firstbody++) { ! 585: if (subjp != 0 && strlen(subjp) > MAXSUBJ) { ! 586: fprintf(stderr, "%s: subject field too long\n", myname); ! 587: retcode = 4; ! 588: goto leave; ! 589: } ! 590: } ! 591: ! 592: fputs(buf, tfile); ! 593: break; ! 594: ! 595: case FILEEOF: ! 596: goto process; ! 597: ! 598: case LENERR: ! 599: case FMTERR: ! 600: fprintf(stderr, "%s: ??Message Format Error ", myname); ! 601: fprintf(stderr, "in component #%d.\n", compnum); ! 602: retcode = 6; ! 603: goto leave; ! 604: } ! 605: } ! 606: ! 607: process: ! 608: ! 609: fclose(tfile); ! 610: fclose(pfile); ! 611: m_update(); ! 612: fflush(stdout); ! 613: ! 614: if (follow) { ! 615: for (p = follow; *p; p++) { ! 616: if (*p == '\n') *p = ' '; ! 617: } ! 618: } ! 619: for (p=subjp; *p; p++) { ! 620: if (*p == '\n') *p = ' '; ! 621: } ! 622: ! 623: if (!newsgroup) { ! 624: newsgroup = DEFAULTGROUP; ! 625: } ! 626: ! 627: for(p=newsgroup; *p; p++) { ! 628: if (*p == ' ' || *p == '\t' || *p == '\n') { ! 629: *p = '\0'; ! 630: } ! 631: } ! 632: while (*newsgroup++ == '\0'); ! 633: --newsgroup; ! 634: ! 635: /************ ! 636: * ! 637: * This code no longer needed - mortals can't create newsgroups ! 638: * ! 639: * sprintf(tmp, "%s/%s", NEWSDIR, newsgroup); ! 640: * ! 641: * if (stat(tmp, &statb) < 0) { ! 642: * sprintf(yatmp, "Create new newsgroup '%s'? ", newsgroup); ! 643: * if(gans(yatmp, any) == 0) { ! 644: * goto leave; ! 645: * } ! 646: * } ! 647: * if (strlen(newsgroup) < 2) { ! 648: * fprintf(stderr, "%s: newsgroup name '%s' invalid\n", ! 649: * myname, newsgroup); ! 650: * goto leave; ! 651: * } ! 652: */ ! 653: ! 654: if (debug) { ! 655: sprintf(tmp,"inews -F \"%s\" -t \"%s\" -n %s < %s\n\0",follow,subjp, newsgroup, tmpname); ! 656: printf("command line: ");/*DBG*/ ! 657: printf("%s", tmp);/*DBG*/ ! 658: } ! 659: ! 660: ! 661: if ((pid = fork()) == 0) { ! 662: ! 663: for (i = 3; i < 15; i++) close(i); /* close spurious fd's */ ! 664: ! 665: close(0); /* tmpfile comes in on stdin */ ! 666: ! 667: if(open(tmpname, 0) < 0) { ! 668: fprintf(stderr, "%s: can't open tmp file\n", myname); ! 669: done(-1); ! 670: } ! 671: ! 672: if (follow) { ! 673: execlp(newsproc, newsproc, "-F", follow, "-t", subjp, "-n", newsgroup, 0); ! 674: } else { ! 675: execlp(newsproc, newsproc, "-t", subjp, "-n", newsgroup, 0); ! 676: } ! 677: fprintf(stderr, "%s: can't exec %s\n", myname, newsproc); ! 678: perror(newsproc); ! 679: done(-1); ! 680: ! 681: } else if (pid == -1) { ! 682: fprintf(stderr, "%s: Can't fork.\n", myname); ! 683: retcode = 7; ! 684: goto leave; ! 685: } else { ! 686: int (*istat)(), (*qstat)(); ! 687: ! 688: istat = signal(SIGINT, SIG_IGN); ! 689: qstat = signal(SIGQUIT, SIG_IGN); ! 690: while ((wpid = wait(&status)) != -1 && wpid != pid) ; ! 691: signal(SIGINT, istat); ! 692: signal(SIGQUIT, qstat); ! 693: } ! 694: ! 695: if (status == 0) { ! 696: fprintf(stderr, "[%s to %s]\n", ! 697: myname[0] == 's' ? "submitted" : "posted", ! 698: newsgroup); ! 699: retcode = 0; ! 700: } else { ! 701: retcode = 8; ! 702: goto leave; ! 703: } ! 704: ! 705: suceess: ! 706: retcode = 0; ! 707: backup(pathname); ! 708: leave: ! 709: if (pfile) fclose(pfile); ! 710: if (tfile) fclose(tfile); ! 711: if (tmpname) unlink(tmpname); ! 712: ! 713: return(retcode); ! 714: } ! 715: ! 716: ! 717: ! 718: backup(file) ! 719: char *file; ! 720: { ! 721: char buf[128]; ! 722: register char *cp; ! 723: ! 724: buf[0] = 0; ! 725: if(cp = rindex(file, '/')) ! 726: sprintf(buf, "%.*s", (++cp)-file, file); ! 727: else ! 728: cp = file; ! 729: strcat(buf, ","); ! 730: strcat(buf, cp); ! 731: unlink(buf); ! 732: if(link(file, buf) < 0 || unlink(file) < 0) { ! 733: fprintf(stderr, "Send: Backup rename failure "); ! 734: perror(buf); ! 735: done(1); ! 736: } ! 737: } ! 738: ! 739: ! 740: ######################### ! 741: # additions to makefile # ! 742: ######################### ! 743: ! 744: [You will have to substitute the locations of your MH libraries] ! 745: [Submit also uses 'mh.h' out of the current directory - deal with that] ! 746: ! 747: submit: submit.o ! 748: $(CC) $(CFLAGS) -DSPOOLDIR=\"$(SPOOLDIR) -DLIBDIR=\"$(LIBDIR)\ ! 749: submit submit.o /usr1/src/cmd/mh/subs.a /usr1/src/cmd/mh/strings.a -lc \ ! 750: -o submit ! 751:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.