|
|
1.1 root 1: /* rn -- new readnews program
2: *
3: * From: [email protected] (Larry Wall)
4: * Organization: System Development Corporation, Santa Monica
5: *
6: * begun: 01/14/83
7: * 1.0: 04/08/83
8: * 2.0: 09/01/83
9: */
10:
11: static char rnid[] = "@(#)$Header: rn.c,v 4.3.1.4 85/09/10 11:05:13 lwall Exp $";
12:
13: /* $Log: rn.c,v $
14: * Revision 4.3.1.4 85/09/10 11:05:13 lwall
15: * Improved %m in in_char().
16: *
17: * Revision 4.3.1.3 85/05/16 16:47:10 lwall
18: * Catchup confirmation didn't grok -t.
19: *
20: * Revision 4.3.1.2 85/05/13 09:34:53 lwall
21: * Fixed default after do_newsgroup() returns from Q command.
22: *
23: * Revision 4.3.1.1 85/05/10 11:38:08 lwall
24: * Branch for patches.
25: *
26: * Revision 4.3 85/05/01 11:47:56 lwall
27: * Baseline for release with 4.3bsd.
28: *
29: */
30:
31: #include "INTERN.h"
32: #include "common.h"
33: #include "rn.h"
34: #include "EXTERN.h"
35: #include "rcstuff.h"
36: #include "term.h"
37: #include "final.h"
38: #include "ngdata.h"
39: #include "util.h"
40: #include "only.h"
41: #include "ngsrch.h"
42: #include "help.h"
43: #include "last.h"
44: #include "init.h"
45: #include "intrp.h"
46: #include "rcln.h"
47: #include "sw.h"
48: #include "addng.h"
49: #include "ng.h"
50: #include "INTERN.h"
51:
52: void
53: rn_init()
54: {
55: ;
56: }
57:
58: void
59: main(argc,argv)
60: int argc;
61: char *argv[];
62: {
63: bool foundany = initialize(argc,argv);
64: register char *s;
65: bool oh_for_the_good_old_days = FALSE;
66:
67: if (maxngtodo)
68: starthere = 0;
69: else if (!foundany) { /* nothing to do? */
70: #ifdef VERBOSE
71: if (verbose)
72: fputs("\
73: No unread news in subscribed-to newsgroups. To subscribe to a new\n\
74: newsgroup use the g<newsgroup> command.\n\
75: ",stdout) FLUSH;
76: #endif
77: starthere = nextrcline;
78: }
79:
80: /* loop through all unread news */
81:
82: {
83: char promptbuf[80];
84: bool special = FALSE; /* temporarily allow newsgroup */
85: /* with no unread news? */
86: bool retry; /* cycle back to top of list? */
87: NG_NUM recent_ng = 0;
88:
89: current_ng = 0;
90: do {
91: retry = FALSE;
92: if (findlast) {
93: findlast = FALSE;
94: starthere = 0;
95: if (*lastngname) {
96: if ((ng = find_ng(lastngname)) == nextrcline)
97: ng = 0;
98: else {
99: set_ngname(lastngname);
100: set_toread(ng);
101: if (toread[ng] <= TR_NONE)
102: ng = 0;
103: }
104: }
105: }
106: else {
107: ng = starthere;
108: starthere = 0;
109: }
110: while (ng <= nextrcline) { /* for each newsgroup */
111: mode = 'n';
112: if (ng >= nextrcline) { /* after the last newsgroup? */
113: ng = nextrcline; /* force it to 1 after */
114: #ifdef ONLY
115: if (maxngtodo) {
116: if (retry)
117: #ifdef VERBOSE
118: IF(verbose)
119: printf("\nRestriction %s%s still in effect.\n",
120: ngtodo[0],
121: maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
122: ELSE
123: #endif
124: #ifdef TERSE
125: fputs("\n(\"Only\" mode.)\n",stdout) FLUSH;
126: #endif
127: else {
128: #ifdef VERBOSE
129: IF(verbose)
130: fputs("\nNo articles under restriction.",
131: stdout) FLUSH;
132: ELSE
133: #endif
134: #ifdef TERSE
135: fputs("\nNo \"only\" articles.",stdout) FLUSH;
136: #endif
137: end_only(); /* release the restriction */
138: retry = TRUE;
139: }
140: }
141: #endif
142: dfltcmd = (retry ? "npq" : "qnp");
143: #ifdef VERBOSE
144: IF(verbose)
145: sprintf(promptbuf,
146: "\n******** End of newsgroups--what next? [%s] ",
147: dfltcmd);
148: ELSE
149: #endif
150: #ifdef TERSE
151: sprintf(promptbuf,
152: "\n**** End--next? [%s] ", dfltcmd);
153: #endif
154: }
155: else {
156: bool shoe_fits; /* newsgroup matches restriction? */
157:
158: if (toread[ng] >= TR_NONE) { /* recalc toread? */
159: set_ngname(rcline[ng]);
160: if (shoe_fits = (special || inlist(ngname)))
161: set_toread(ng);
162: if (paranoid) {
163: recent_ng = current_ng;
164: current_ng = ng;
165: cleanup_rc();
166: /* this may move newsgroups around */
167: ng = current_ng;
168: set_ngname(rcline[ng]);
169: }
170: }
171: if (toread[ng] < (maxngtodo||special ? TR_NONE : TR_ONE) || !shoe_fits) {
172: /* unwanted newsgroup? */
173: ng++; /* then skip it */
174: continue;
175: }
176: dfltcmd = "ynq";
177: #ifdef VERBOSE
178: IF(verbose)
179: sprintf(promptbuf,
180: "\n******** %3ld unread article%c in %s--read now? [%s] ",
181: (long)toread[ng], (toread[ng]==TR_ONE ? ' ' : 's'),
182: ngname, dfltcmd); /* format prompt string */
183: ELSE
184: #endif
185: #ifdef TERSE
186: sprintf(promptbuf,
187: "\n**** %3ld in %s--read? [%s] ",
188: (long)toread[ng],
189: ngname,dfltcmd); /* format prompt string */
190: #endif
191: }
192: special = FALSE; /* go back to normal mode */
193: if (ng != current_ng) {
194: recent_ng = current_ng;
195: /* remember previous newsgroup */
196: current_ng = ng; /* remember current newsgroup */
197: }
198: reask_newsgroup:
199: unflush_output(); /* disable any ^O in effect */
200: fputs(promptbuf,stdout) FLUSH;/* print prompt */
201: fflush(stdout);
202: reinp_newsgroup:
203: eat_typeahead();
204: getcmd(buf);
205: if (errno || *buf == '\f') {
206: putchar('\n') FLUSH; /* if return from stop signal */
207: goto reask_newsgroup; /* give them a prompt again */
208: }
209: setdef(buf,dfltcmd);
210: #ifdef VERIFY
211: printcmd();
212: #endif
213: switch (*buf) {
214: case 'p': /* find previous unread newsgroup */
215: do {
216: if (ng <= 0)
217: break;
218: ng--;
219: if (toread[ng] == TR_NONE)
220: set_toread(ng);
221: } while (toread[ng] <= TR_NONE);
222: break;
223: case 'P': /* goto previous newsgroup */
224: do {
225: if (ng <= 0)
226: break;
227: ng--;
228: } while (toread[ng] < TR_NONE);
229: special = TRUE; /* don't skip it if toread==0 */
230: break;
231: case '-':
232: ng = recent_ng; /* recall previous newsgroup */
233: special = TRUE; /* don't skip it if toread==0 */
234: break;
235: case 'q': case 'Q': case 'x': /* quit? */
236: oh_for_the_good_old_days = (*buf == 'x');
237: putchar('\n') FLUSH;
238: ng = nextrcline+1; /* satisfy */
239: retry = FALSE; /* loop conditions */
240: break;
241: case '^':
242: putchar('\n') FLUSH;
243: ng = 0;
244: break;
245: case 'n': case '+': /* find next unread newsgroup */
246: if (ng == nextrcline) {
247: putchar('\n') FLUSH;
248: retry = TRUE;
249: }
250: else if (toread[ng] > TR_NONE)
251: retry = TRUE;
252: ng++;
253: break;
254: case 'N': /* goto next newsgroup */
255: ng++;
256: special = TRUE; /* and don't skip it if toread==0 */
257: break;
258: case '1': /* goto 1st newsgroup */
259: ng = 0;
260: special = TRUE; /* and don't skip it if toread==0 */
261: break;
262: case '$':
263: ng = nextrcline; /* goto last newsgroup */
264: retry = TRUE;
265: break;
266: case 'L':
267: list_newsgroups();
268: goto reask_newsgroup;
269: case '/': case '?': /* scan for newsgroup pattern */
270: #ifdef NGSEARCH
271: switch (ng_search(buf,TRUE)) {
272: case NGS_ABORT:
273: goto reinp_newsgroup;
274: case NGS_INTR:
275: #ifdef VERBOSE
276: IF(verbose)
277: fputs("\n(Interrupted)\n",stdout) FLUSH;
278: ELSE
279: #endif
280: #ifdef TERSE
281: fputs("\n(Intr)\n",stdout) FLUSH;
282: #endif
283: ng = current_ng;
284: goto reask_newsgroup;
285: case NGS_FOUND:
286: special = TRUE; /* don't skip it if toread==0 */
287: break;
288: case NGS_NOTFOUND:
289: #ifdef VERBOSE
290: IF(verbose)
291: fputs("\n\nNot found--use g to add newsgroups\n",
292: stdout) FLUSH;
293: ELSE
294: #endif
295: #ifdef TERSE
296: fputs("\n\nNot found\n",stdout) FLUSH;
297: #endif
298: goto reask_newsgroup;
299: }
300: #else
301: notincl("/");
302: #endif
303: break;
304: case 'm':
305: #ifndef RELOCATE
306: notincl("m");
307: break;
308: #endif
309: case 'g': /* goto named newsgroup */
310: if (!finish_command(FALSE))
311: /* if they didn't finish command */
312: goto reinp_newsgroup; /* go try something else */
313: for (s = buf+1; *s == ' '; s++);
314: /* skip leading spaces */
315: if (!*s)
316: strcpy(s,ngname);
317: #ifdef RELOCATE
318: if (!get_ng(s,*buf=='m')) /* try to find newsgroup */
319: #else
320: if (!get_ng(s,FALSE)) /* try to find newsgroup */
321: #endif
322: ng = current_ng;/* if not found, go nowhere */
323: special = TRUE; /* don't skip it if toread==0 */
324: break;
325: #ifdef DEBUGGING
326: case 'D':
327: printf("\nTries: %d Hits: %d\n",
328: softtries,softtries-softmisses) FLUSH;
329: goto reask_newsgroup;
330: #endif
331: case '!': /* shell escape */
332: if (escapade()) /* do command */
333: goto reinp_newsgroup;
334: /* if rubbed out, re input */
335: goto reask_newsgroup;
336: case Ctl('k'): /* edit global KILL file */
337: edit_kfile();
338: goto reask_newsgroup;
339: case 'c': /* catch up */
340: #ifdef CATCHUP
341: reask_catchup:
342: #ifdef VERBOSE
343: IF(verbose)
344: in_char("\nDo you really want to mark everything as read? [yn] ", 'C');
345: ELSE
346: #endif
347: #ifdef TERSE
348: in_char("\nReally? [ynh] ", 'C');
349: #endif
350: putchar('\n') FLUSH;
351: setdef(buf,"y");
352: if (*buf == 'h') {
353: #ifdef VERBOSE
354: printf("Type y or SP to mark all articles as read.\n");
355: printf("Type n to leave articles marked as they are.\n");
356: #else
357: printf("y or SP to mark all read.\n");
358: printf("n to forget it.\n");
359: #endif
360: goto reask_catchup;
361: }
362: else if (*buf!=' ' && *buf!='y' && *buf!='n' && *buf!='q') {
363: printf(hforhelp);
364: settle_down();
365: goto reask_catchup;
366: } else if ( (*buf == ' ' || *buf == 'y') && ng<nextrcline )
367: catch_up(ng);
368: else
369: retry = TRUE;
370: ng++;
371: #else
372: notincl("c");
373: #endif
374: break;
375: case 'u': /* unsubscribe */
376: if (ng < nextrcline && toread[ng] >= TR_NONE) {
377: /* unsubscribable? */
378: printf(unsubto,rcline[ng]) FLUSH;
379: rcchar[ng] = NEGCHAR;
380: /* unsubscribe to (from?) it */
381: toread[ng] = TR_UNSUB;
382: /* and make line invisible */
383: ng++; /* do an automatic 'n' */
384: }
385: break;
386: case 'h': { /* help */
387: int cmd;
388:
389: if ((cmd = help_ng()) > 0)
390: pushchar(cmd);
391: goto reask_newsgroup;
392: }
393: case 'a':
394: #ifndef FINDNEWNG
395: notincl("a");
396: goto reask_newsgroup;
397: #else
398: /* FALL THROUGH */
399: #endif
400: case 'o':
401: #ifdef ONLY
402: {
403: #ifdef FINDNEWNG
404: bool doscan = (*buf == 'a');
405: #endif
406:
407: if (!finish_command(TRUE)) /* get rest of command */
408: goto reinp_newsgroup; /* if rubbed out, try something else */
409: end_only();
410: if (buf[1]) {
411: bool minusd = instr(buf+1,"-d") != Nullch;
412:
413: sw_list(buf+1);
414: if (minusd)
415: cwd_check();
416: putchar('\n') FLUSH;
417: #ifdef FINDNEWNG
418: if (doscan && maxngtodo)
419: scanactive();
420: #endif
421: }
422: ng = 0; /* simulate ^ */
423: retry = FALSE;
424: break;
425: }
426: #else
427: notincl("o");
428: goto reask_newsgroup;
429: #endif
430: case '&':
431: if (switcheroo()) /* get rest of command */
432: goto reinp_newsgroup; /* if rubbed out, try something else */
433: goto reask_newsgroup;
434: case 'l': { /* list other newsgroups */
435: if (!finish_command(TRUE)) /* get rest of command */
436: goto reinp_newsgroup; /* if rubbed out, try something else */
437: for (s = buf+1; *s == ' '; s++);
438: /* skip leading spaces */
439: sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s);
440: resetty();
441: if (doshell(sh,cmd_buf))
442: #ifdef VERBOSE
443: IF(verbose)
444: fputs(" (Error from newsgroups program)\n",
445: stdout) FLUSH;
446: ELSE
447: #endif
448: #ifdef TERSE
449: fputs("(Error)\n",stdout) FLUSH;
450: #endif
451: noecho();
452: crmode();
453: goto reask_newsgroup;
454: }
455: case '.': case '=':
456: case 'y': case 'Y': /* do normal thing */
457: if (ng >= nextrcline) {
458: fputs("\nNot on a newsgroup.",stdout) FLUSH;
459: goto reask_newsgroup;
460: }
461: if (*buf == '=')
462: s = savestr("=");
463: else if (*buf == '.') { /* start command? */
464: if (!finish_command(FALSE)) /* get rest of command */
465: goto reinp_newsgroup;
466: s = savestr(buf+1);
467: /* do_newsgroup will free it */
468: }
469: else
470: s = Nullch;
471: if (toread[ng])
472: retry = TRUE;
473: switch (do_newsgroup(s)) {
474: case NG_ERROR:
475: case NG_NORM:
476: ng++;
477: break;
478: case NG_ASK:
479: dfltcmd = "ynq";
480: goto reask_newsgroup;
481: case NG_MINUS:
482: ng = recent_ng; /* recall previous newsgroup */
483: special = TRUE; /* don't skip it if toread==0 */
484: break;
485: }
486: break;
487: #ifdef STRICTCR
488: case '\n':
489: fputs(badcr,stdout) FLUSH;
490: goto reask_newsgroup;
491: #endif
492: case 'v':
493: printf("\n%s\n",rnid) FLUSH;
494: goto reask_newsgroup;
495: default:
496: printf("\n%s",hforhelp) FLUSH;
497: settle_down();
498: goto reask_newsgroup;
499: }
500: }
501: } while (retry);
502: }
503:
504: /* now write .newsrc back out */
505:
506: write_rc();
507:
508: if (oh_for_the_good_old_days)
509: get_old_rc();
510:
511: finalize(0); /* and exit */
512: }
513:
514: /* set current newsgroup */
515:
516: void
517: set_ngname(what)
518: char *what;
519: {
520: int len = strlen(what)+1;
521:
522: growstr(&ngname,&ngnlen,len);
523: strcpy(ngname,what);
524: growstr(&ngdir,&ngdlen,len);
525: strcpy(ngdir,getngdir(ngname));
526: }
527:
528: static char *myngdir;
529: static int ngdirlen = 0;
530:
531: char *
532: getngdir(ngnam)
533: char *ngnam;
534: {
535: register char *s;
536:
537: growstr(&myngdir,&ngdirlen,strlen(ngnam)+1);
538: strcpy(myngdir,ngnam);
539: for (s = myngdir; *s; s++)
540: if (*s == '.')
541: *s = '/';
542: return myngdir;
543: }
544:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.