|
|
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.