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