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