|
|
1.1 ! root 1: /* $Header: ng.c,v 4.3.1.3 85/05/16 16:48:09 lwall Exp $ ! 2: * ! 3: * $Log: ng.c,v $ ! 4: * Revision 4.3.1.3 85/05/16 16:48:09 lwall ! 5: * Fixed unsubsubscribe. ! 6: * ! 7: * Revision 4.3.1.2 85/05/13 09:29:28 lwall ! 8: * Added CUSTOMLINES option. ! 9: * ! 10: * Revision 4.3.1.1 85/05/10 11:36:00 lwall ! 11: * Branch for patches. ! 12: * ! 13: * Revision 4.3 85/05/01 11:43:43 lwall ! 14: * Baseline for release with 4.3bsd. ! 15: * ! 16: */ ! 17: ! 18: #include "EXTERN.h" ! 19: #include "common.h" ! 20: #include "rn.h" ! 21: #include "term.h" ! 22: #include "final.h" ! 23: #include "util.h" ! 24: #include "artsrch.h" ! 25: #include "cheat.h" ! 26: #include "help.h" ! 27: #include "kfile.h" ! 28: #include "rcstuff.h" ! 29: #include "head.h" ! 30: #include "artstate.h" ! 31: #include "bits.h" ! 32: #include "art.h" ! 33: #include "artio.h" ! 34: #include "ngstuff.h" ! 35: #include "intrp.h" ! 36: #include "respond.h" ! 37: #include "ngdata.h" ! 38: #include "backpage.h" ! 39: #include "rcln.h" ! 40: #include "last.h" ! 41: #include "search.h" ! 42: #include "server.h" ! 43: #include "INTERN.h" ! 44: #include "ng.h" ! 45: #include "artstate.h" /* somebody has to do it */ ! 46: ! 47: /* art_switch() return values */ ! 48: ! 49: #define AS_NORM 0 ! 50: #define AS_INP 1 ! 51: #define AS_ASK 2 ! 52: #define AS_CLEAN 3 ! 53: ! 54: ART_NUM recent_art = 0; /* previous article # for '-' command */ ! 55: ART_NUM curr_art = 0; /* current article # */ ! 56: int exit_code = NG_NORM; ! 57: ! 58: void ! 59: ng_init() ! 60: { ! 61: ! 62: #ifdef KILLFILES ! 63: open_kfile(KF_GLOBAL); ! 64: #endif ! 65: #ifdef CUSTOMLINES ! 66: init_compex(&hide_compex); ! 67: init_compex(&page_compex); ! 68: #endif ! 69: } ! 70: ! 71: /* do newsgroup on line ng with name ngname */ ! 72: ! 73: /* assumes that we are chdir'ed to SPOOL, and assures that that is ! 74: * still true upon return, but chdirs to SPOOL/ngname in between ! 75: * ! 76: * If you can understand this routine, you understand most of the program. ! 77: * The basic structure is: ! 78: * for each desired article ! 79: * for each desired page ! 80: * for each line on page ! 81: * if we need another line from file ! 82: * get it ! 83: * if it's a header line ! 84: * do special things ! 85: * for each column on page ! 86: * put out a character ! 87: * end loop ! 88: * end loop ! 89: * end loop ! 90: * end loop ! 91: * ! 92: * (Actually, the pager is in another routine.) ! 93: * ! 94: * The chief problem is deciding what is meant by "desired". Most of ! 95: * the messiness of this routine is due to the fact that people want ! 96: * to do unstructured things all the time. I have used a few judicious ! 97: * goto's where I thought it improved readability. The rest of the messiness ! 98: * arises from trying to be both space and time efficient. Have fun. ! 99: */ ! 100: ! 101: int ! 102: do_newsgroup(start_command) ! 103: char *start_command; /* command to fake up first */ ! 104: { ! 105: #ifdef SERVER ! 106: char ser_line[256]; ! 107: char artname[32]; ! 108: static long our_pid; ! 109: #endif ! 110: char oldmode = mode; ! 111: register long i; /* scratch */ ! 112: int skipstate; /* how many unavailable articles */ ! 113: /* have we skipped already? */ ! 114: ! 115: char *whatnext = "%sWhat next? [%s]"; ! 116: ! 117: #ifdef SERVER ! 118: if (our_pid == 0) /* Agreed, this is gross */ ! 119: our_pid = getpid(); ! 120: #endif ! 121: ! 122: #ifdef ARTSEARCH ! 123: srchahead = (scanon && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0); ! 124: /* did they say -S? */ ! 125: #endif ! 126: ! 127: mode = 'a'; ! 128: recent_art = curr_art = 0; ! 129: exit_code = NG_NORM; ! 130: #ifndef SERVER ! 131: if (eaccess(ngdir,5)) { /* directory read protected? */ ! 132: if (eaccess(ngdir,0)) { ! 133: #ifdef VERBOSE ! 134: IF(verbose) ! 135: printf("\nNewsgroup %s does not have a spool directory!\n", ! 136: ngname) FLUSH; ! 137: ELSE ! 138: #endif ! 139: #ifdef TERSE ! 140: printf("\nNo spool for %s!\n",ngname) FLUSH; ! 141: #endif ! 142: #ifdef CATCHUP ! 143: catch_up(ng); ! 144: #endif ! 145: toread[ng] = TR_NONE; ! 146: } ! 147: else { ! 148: #ifdef VERBOSE ! 149: IF(verbose) ! 150: printf("\nNewsgroup %s is not currently accessible.\n", ! 151: ngname) FLUSH; ! 152: ELSE ! 153: #endif ! 154: #ifdef TERSE ! 155: printf("\n%s not readable.\n",ngname) FLUSH; ! 156: #endif ! 157: toread[ng] = TR_NONE; /* make this newsgroup invisible */ ! 158: /* (temporarily) */ ! 159: } ! 160: mode = oldmode; ! 161: return -1; ! 162: } ! 163: ! 164: /* chdir to newsgroup subdirectory */ ! 165: ! 166: if (chdir(ngdir)) { ! 167: printf(nocd,ngdir) FLUSH; ! 168: mode = oldmode; ! 169: return -1; ! 170: } ! 171: #else /* SERVER */ ! 172: sprintf(ser_line, "GROUP %s", ngname); ! 173: put_server(ser_line); ! 174: if (get_server(ser_line, sizeof(ser_line)) < 0) { ! 175: fprintf(stderr, "rrn: Unexpected close of server socket.\n"); ! 176: finalize(1); ! 177: } ! 178: if (*ser_line != CHAR_OK) ! 179: return (-1); ! 180: #endif /* SERVER */ ! 181: ! 182: #ifdef CACHESUBJ ! 183: subj_list = Null(char **); /* no subject list till needed */ ! 184: #endif ! 185: ! 186: /* initialize control bitmap */ ! 187: ! 188: if (initctl()) { ! 189: mode = oldmode; ! 190: return -1; ! 191: } ! 192: ! 193: /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */ ! 194: ! 195: in_ng = TRUE; /* tell the world we are here */ ! 196: forcelast = TRUE; /* if 0 unread, do not bomb out */ ! 197: art=firstart; ! 198: ! 199: /* remember what newsgroup we were in for sake of posterity */ ! 200: ! 201: writelast(); ! 202: ! 203: /* see if there are any special searches to do */ ! 204: ! 205: #ifdef KILLFILES ! 206: open_kfile(KF_LOCAL); ! 207: #ifdef VERBOSE ! 208: IF(verbose) ! 209: kill_unwanted(firstart,"Looking for articles to kill...\n\n",TRUE); ! 210: ELSE ! 211: #endif ! 212: #ifdef TERSE ! 213: kill_unwanted(firstart,"Killing...\n\n",TRUE); ! 214: #endif ! 215: #endif ! 216: ! 217: /* do they want a special top line? */ ! 218: ! 219: firstline = getval("FIRSTLINE",Nullch); ! 220: ! 221: /* custom line suppression, custom page ending */ ! 222: ! 223: #ifdef CUSTOMLINES ! 224: if (hideline = getval("HIDELINE",Nullch)) ! 225: compile(&hide_compex,hideline,TRUE,TRUE); ! 226: if (pagestop = getval("PAGESTOP",Nullch)) ! 227: compile(&page_compex,pagestop,TRUE,TRUE); ! 228: #endif ! 229: ! 230: /* now read each unread article */ ! 231: ! 232: rc_changed = doing_ng = TRUE; /* enter the twilight zone */ ! 233: skipstate = 0; /* we have not skipped anything (yet) */ ! 234: checkcount = 0; /* do not checkpoint for a while */ ! 235: do_fseek = FALSE; /* start 1st article at top */ ! 236: if (art > lastart) ! 237: art=firstart; /* init the for loop below */ ! 238: for (; art<=lastart+1; ) { /* for each article */ ! 239: ! 240: /* do we need to "grow" the newsgroup? */ ! 241: ! 242: if (art > lastart || forcegrow) ! 243: grow_ctl(); ! 244: check_first(art); /* make sure firstart is still 1st */ ! 245: if (start_command) { /* fake up an initial command? */ ! 246: prompt = whatnext; ! 247: strcpy(buf,start_command); ! 248: free(start_command); ! 249: start_command = Nullch; ! 250: art = lastart+1; ! 251: goto article_level; ! 252: } ! 253: if (art>lastart) { /* are we off the end still? */ ! 254: ART_NUM ucount = 0; /* count of unread articles left */ ! 255: ! 256: for (i=firstart; i<=lastart; i++) ! 257: if (!(ctl_read(i))) ! 258: ucount++; /* count the unread articles */ ! 259: #ifdef DEBUGGING ! 260: /*NOSTRICT*/ ! 261: if (debug && ((ART_NUM)toread[ng]) != ucount) ! 262: printf("(toread=%ld sb %ld)",(long)toread[ng],(long)ucount) ! 263: FLUSH; ! 264: #endif ! 265: /*NOSTRICT*/ ! 266: toread[ng] = (ART_UNREAD)ucount; /* this is perhaps pointless */ ! 267: art = lastart + 1; /* keep bitmap references sane */ ! 268: if (art != curr_art) { ! 269: recent_art = curr_art; ! 270: /* remember last article # (for '-') */ ! 271: curr_art = art; /* remember this article # */ ! 272: } ! 273: if (erase_screen) ! 274: clear(); /* clear the screen */ ! 275: else ! 276: fputs("\n\n",stdout) FLUSH; ! 277: #ifdef VERBOSE ! 278: IF(verbose) ! 279: printf("End of newsgroup %s.",ngname); ! 280: /* print pseudo-article */ ! 281: ELSE ! 282: #endif ! 283: #ifdef TERSE ! 284: printf("End of %s",ngname); ! 285: #endif ! 286: if (ucount) { ! 287: printf(" (%ld article%s still unread)", ! 288: (long)ucount,ucount==1?nullstr:"s"); ! 289: } ! 290: else { ! 291: if (!forcelast) ! 292: goto cleanup; /* actually exit newsgroup */ ! 293: } ! 294: prompt = whatnext; ! 295: #ifdef ARTSEARCH ! 296: srchahead = 0; /* no more subject search mode */ ! 297: #endif ! 298: fputs("\n\n",stdout) FLUSH; ! 299: skipstate = 0; /* back to none skipped */ ! 300: } ! 301: else if (!reread && was_read(art)) { ! 302: /* has this article been read? */ ! 303: art++; /* then skip it */ ! 304: continue; ! 305: } ! 306: else if ! 307: (!reread && !was_read(art) ! 308: && artopen(art) == Nullfp) { /* never read it, & cannot find it? */ ! 309: if (errno != ENOENT) { /* has it not been deleted? */ ! 310: #ifdef VERBOSE ! 311: IF(verbose) ! 312: printf("\n(Article %ld exists but is unreadable.)\n", ! 313: (long)art) FLUSH; ! 314: ELSE ! 315: #endif ! 316: #ifdef TERSE ! 317: printf("\n(%ld unreadable.)\n",(long)art) FLUSH; ! 318: #endif ! 319: skipstate = 0; ! 320: sleep(2); ! 321: } ! 322: switch(skipstate++) { ! 323: case 0: ! 324: clear(); ! 325: #ifdef VERBOSE ! 326: IF(verbose) ! 327: fputs("Skipping unavailable article",stdout); ! 328: ELSE ! 329: #endif ! 330: #ifdef TERSE ! 331: fputs("Skipping",stdout); ! 332: #endif ! 333: for (i = just_a_sec/3; i; --i) ! 334: putchar(PC); ! 335: fflush(stdout); ! 336: sleep(1); ! 337: break; ! 338: case 1: ! 339: fputs("..",stdout); ! 340: fflush(stdout); ! 341: break; ! 342: default: ! 343: putchar('.'); ! 344: fflush(stdout); ! 345: #ifndef SERVER ! 346: #define READDIR ! 347: #ifdef READDIR ! 348: { /* fast skip patch */ ! 349: ART_NUM newart; ! 350: ! 351: if (! (newart=getngmin(".",art))) ! 352: newart = lastart+1; ! 353: for (i=art; i<newart; i++) ! 354: oneless(i); ! 355: art = newart - 1; ! 356: } ! 357: #endif ! 358: #endif ! 359: break; ! 360: } ! 361: oneless(art); /* mark deleted as read */ ! 362: art++; /* try next article */ ! 363: continue; ! 364: } ! 365: else { /* we have a real live article */ ! 366: skipstate = 0; /* back to none skipped */ ! 367: if (art != curr_art) { ! 368: recent_art = curr_art; ! 369: /* remember last article # (for '-') */ ! 370: curr_art = art; /* remember this article # */ ! 371: } ! 372: if (!do_fseek) { /* starting at top of article? */ ! 373: artline = 0; /* start at the beginning */ ! 374: topline = -1; /* and remember top line of screen */ ! 375: /* (line # within article file) */ ! 376: } ! 377: clear(); /* clear screen */ ! 378: artopen(art); /* make sure article file is open */ ! 379: if (artfp == Nullfp) { /* could not find article? */ ! 380: printf("Article %ld of %s is not available.\n\n", ! 381: (long)art,ngname) FLUSH; ! 382: prompt = whatnext; ! 383: #ifdef ARTSEARCH ! 384: srchahead = 0; ! 385: #endif ! 386: } ! 387: else { /* found it, so print it */ ! 388: switch (do_article()) { ! 389: case DA_CLEAN: /* quit newsgroup */ ! 390: goto cleanup; ! 391: case DA_TOEND: /* do not mark as read */ ! 392: goto reask_article; ! 393: case DA_RAISE: /* reparse command at end of art */ ! 394: goto article_level; ! 395: case DA_NORM: /* normal end of article */ ! 396: break; ! 397: } ! 398: } ! 399: mark_as_read(art); /* mark current article as read */ ! 400: reread = FALSE; ! 401: do_hiding = TRUE; ! 402: #ifdef ROTATION ! 403: rotate = FALSE; ! 404: #endif ! 405: } ! 406: ! 407: /* if these gotos bother you, think of this as a little state machine */ ! 408: ! 409: reask_article: ! 410: #ifdef MAILCALL ! 411: setmail(); ! 412: #endif ! 413: setdfltcmd(); ! 414: #ifdef CLEAREOL ! 415: if (erase_screen && can_home_clear) /* PWP was here */ ! 416: clear_rest(); ! 417: #endif CLEAREOL ! 418: unflush_output(); /* disable any ^O in effect */ ! 419: standout(); /* enter standout mode */ ! 420: printf(prompt,mailcall,dfltcmd);/* print prompt, whatever it is */ ! 421: un_standout(); /* leave standout mode */ ! 422: putchar(' '); ! 423: fflush(stdout); ! 424: reinp_article: ! 425: eat_typeahead(); ! 426: #ifdef PENDING ! 427: look_ahead(); /* see what we can do in advance */ ! 428: if (!input_pending()) ! 429: collect_subjects(); /* loads subject cache until */ ! 430: /* input is pending */ ! 431: #endif ! 432: getcmd(buf); ! 433: if (errno || *buf == '\f') { ! 434: if (LINES < 100 && !int_count) ! 435: *buf = '\f'; /* on CONT fake up refresh */ ! 436: else { ! 437: putchar('\n') FLUSH; /* but only on a crt */ ! 438: goto reask_article; ! 439: } ! 440: } ! 441: article_level: ! 442: ! 443: /* parse and process article level command */ ! 444: ! 445: switch (art_switch()) { ! 446: case AS_INP: /* multichar command rubbed out */ ! 447: goto reinp_article; ! 448: case AS_ASK: /* reprompt "End of article..." */ ! 449: goto reask_article; ! 450: case AS_CLEAN: /* exit newsgroup */ ! 451: goto cleanup; ! 452: case AS_NORM: /* display article art */ ! 453: break; ! 454: } ! 455: } /* end of article selection loop */ ! 456: ! 457: /* shut down newsgroup */ ! 458: ! 459: cleanup: ! 460: #ifdef KILLFILES ! 461: kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE); ! 462: /* do cleanup from KILL file, if any */ ! 463: #endif ! 464: in_ng = FALSE; /* leave newsgroup state */ ! 465: if (artfp != Nullfp) { /* article still open? */ ! 466: fclose(artfp); /* close it */ ! 467: artfp = Nullfp; /* and tell the world */ ! 468: #ifdef SERVER ! 469: sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid); ! 470: UNLINK(artname); ! 471: #endif ! 472: openart = 0; ! 473: } ! 474: putchar('\n') FLUSH; ! 475: yankback(); /* do a Y command */ ! 476: restore_ng(); /* reconstitute .newsrc line */ ! 477: doing_ng = FALSE; /* tell sig_catcher to cool it */ ! 478: free(ctlarea); /* return the control area */ ! 479: #ifdef CACHESUBJ ! 480: if (subj_list) { ! 481: for (i=OFFSET(lastart); i>=0; --i) ! 482: if (subj_list[i]) ! 483: free(subj_list[i]); ! 484: #ifndef lint ! 485: free((char*)subj_list); ! 486: #endif lint ! 487: } ! 488: #endif ! 489: write_rc(); /* and update .newsrc */ ! 490: rc_changed = FALSE; /* tell sig_catcher it is ok */ ! 491: if (chdir(spool)) { ! 492: printf(nocd,spool) FLUSH; ! 493: sig_catcher(0); ! 494: } ! 495: #ifdef KILLFILES ! 496: if (localkfp) { ! 497: fclose(localkfp); ! 498: localkfp = Nullfp; ! 499: } ! 500: #endif ! 501: mode = oldmode; ! 502: return exit_code; ! 503: } /* Whew! */ ! 504: ! 505: /* decide what to do at the end of an article */ ! 506: ! 507: int ! 508: art_switch() ! 509: { ! 510: register ART_NUM i; ! 511: ! 512: setdef(buf,dfltcmd); ! 513: #ifdef VERIFY ! 514: printcmd(); ! 515: #endif ! 516: switch (*buf) { ! 517: case 'p': /* find previous unread article */ ! 518: do { ! 519: if (art <= firstart) ! 520: break; ! 521: art--; ! 522: } while (was_read(art) || artopen(art) == Nullfp); ! 523: #ifdef ARTSEARCH ! 524: srchahead = 0; ! 525: #endif ! 526: return AS_NORM; ! 527: case 'P': /* goto previous article */ ! 528: if (art > absfirst) ! 529: art--; ! 530: else { ! 531: #ifdef VERBOSE ! 532: IF(verbose) ! 533: fputs("\n\ ! 534: There are no articles prior to this one.\n\ ! 535: ",stdout) FLUSH; ! 536: ELSE ! 537: #endif ! 538: #ifdef TERSE ! 539: fputs("\nNo previous articles\n",stdout) FLUSH; ! 540: #endif ! 541: return AS_ASK; ! 542: } ! 543: reread = TRUE; ! 544: #ifdef ARTSEARCH ! 545: srchahead = 0; ! 546: #endif ! 547: return AS_NORM; ! 548: case '-': ! 549: if (recent_art) { ! 550: art = recent_art; ! 551: reread = TRUE; ! 552: #ifdef ARTSEARCH ! 553: srchahead = -(srchahead != 0); ! 554: #endif ! 555: return AS_NORM; ! 556: } ! 557: else { ! 558: exit_code = NG_MINUS; ! 559: return AS_CLEAN; ! 560: } ! 561: case 'n': /* find next unread article? */ ! 562: if (art > lastart) { ! 563: if (toread[ng]) ! 564: art = firstart; ! 565: else ! 566: return AS_CLEAN; ! 567: } ! 568: #ifdef ARTSEARCH ! 569: else if (scanon && srchahead) { ! 570: *buf = Ctl('n'); ! 571: goto normal_search; ! 572: } ! 573: #endif ! 574: else ! 575: art++; ! 576: #ifdef ARTSEARCH ! 577: srchahead = 0; ! 578: #endif ! 579: return AS_NORM; ! 580: case 'N': /* goto next article */ ! 581: if (art > lastart) ! 582: art = absfirst; ! 583: else ! 584: art++; ! 585: if (art <= lastart) ! 586: reread = TRUE; ! 587: #ifdef ARTSEARCH ! 588: srchahead = 0; ! 589: #endif ! 590: return AS_NORM; ! 591: case '$': ! 592: art = lastart+1; ! 593: forcelast = TRUE; ! 594: #ifdef ARTSEARCH ! 595: srchahead = 0; ! 596: #endif ! 597: return AS_NORM; ! 598: case '1': case '2': case '3': /* goto specified article */ ! 599: case '4': case '5': case '6': /* or do something with a range */ ! 600: case '7': case '8': case '9': case '.': ! 601: forcelast = TRUE; ! 602: switch (numnum()) { ! 603: case NN_INP: ! 604: return AS_INP; ! 605: case NN_ASK: ! 606: return AS_ASK; ! 607: case NN_REREAD: ! 608: reread = TRUE; ! 609: #ifdef ARTSEARCH ! 610: if (srchahead) ! 611: srchahead = -1; ! 612: #endif ! 613: break; ! 614: case NN_NORM: ! 615: if (was_read(art)) { ! 616: art = firstart; ! 617: pad(just_a_sec/3); ! 618: } ! 619: else ! 620: return AS_ASK; ! 621: break; ! 622: } ! 623: return AS_NORM; ! 624: case Ctl('k'): ! 625: edit_kfile(); ! 626: return AS_ASK; ! 627: case 'K': ! 628: case 'k': ! 629: case Ctl('n'): case Ctl('p'): ! 630: case '/': case '?': ! 631: #ifdef ARTSEARCH ! 632: normal_search: ! 633: { /* search for article by pattern */ ! 634: char cmd = *buf; ! 635: ! 636: reread = TRUE; /* assume this */ ! 637: switch (art_search(buf, (sizeof buf), TRUE)) { ! 638: case SRCH_ERROR: ! 639: return AS_ASK; ! 640: case SRCH_ABORT: ! 641: return AS_INP; ! 642: case SRCH_INTR: ! 643: #ifdef VERBOSE ! 644: IF(verbose) ! 645: printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH; ! 646: ELSE ! 647: #endif ! 648: #ifdef TERSE ! 649: printf("\n(Intr at %ld)\n",(long)art) FLUSH; ! 650: #endif ! 651: art = curr_art; ! 652: /* restore to current article */ ! 653: return AS_ASK; ! 654: case SRCH_DONE: ! 655: fputs("done\n",stdout) FLUSH; ! 656: pad(just_a_sec/3); /* 1/3 second */ ! 657: if (srchahead) ! 658: art = firstart; ! 659: else ! 660: art = curr_art; ! 661: reread = FALSE; ! 662: return AS_NORM; ! 663: case SRCH_SUBJDONE: ! 664: #ifdef UNDEF ! 665: fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH; ! 666: pad(just_a_sec/3); /* 1/3 second */ ! 667: #endif ! 668: art = firstart; ! 669: reread = FALSE; ! 670: return AS_NORM; ! 671: case SRCH_NOTFOUND: ! 672: fputs("\n\n\n\nNot found.\n",stdout) FLUSH; ! 673: art = curr_art; /* restore to current article */ ! 674: return AS_ASK; ! 675: case SRCH_FOUND: ! 676: if (cmd == Ctl('n') || cmd == Ctl('p')) ! 677: oldsubject = TRUE; ! 678: break; ! 679: } ! 680: return AS_NORM; ! 681: } ! 682: #else ! 683: buf[1] = '\0'; ! 684: notincl(buf); ! 685: return AS_ASK; ! 686: #endif ! 687: case 'u': /* unsubscribe from this newsgroup? */ ! 688: rcchar[ng] = NEGCHAR; ! 689: return AS_CLEAN; ! 690: case 'M': ! 691: #ifdef DELAYMARK ! 692: if (art <= lastart) { ! 693: delay_unmark(art); ! 694: printf("\nArticle %ld will return.\n",(long)art) FLUSH; ! 695: } ! 696: #else ! 697: notincl("M"); ! 698: #endif ! 699: return AS_ASK; ! 700: case 'm': ! 701: if (art <= lastart) { ! 702: unmark_as_read(art); ! 703: printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH; ! 704: } ! 705: return AS_ASK; ! 706: case 'c': /* catch up */ ! 707: reask_catchup: ! 708: #ifdef VERBOSE ! 709: IF(verbose) ! 710: in_char("\nDo you really want to mark everything as read? [yn] "); ! 711: ELSE ! 712: #endif ! 713: #ifdef TERSE ! 714: in_char("\nReally? [ynh] "); ! 715: #endif ! 716: putchar('\n') FLUSH; ! 717: setdef(buf,"y"); ! 718: #ifdef VERIFY ! 719: printcmd(); ! 720: #endif ! 721: if (*buf == 'h') { ! 722: #ifdef VERBOSE ! 723: IF(verbose) ! 724: fputs("\ ! 725: Type y or SP to mark all articles as read.\n\ ! 726: Type n to leave articles marked as they are.\n\ ! 727: Type u to mark everything read and unsubscribe.\n\ ! 728: ",stdout) FLUSH; ! 729: ELSE ! 730: #endif ! 731: #ifdef TERSE ! 732: fputs("\ ! 733: y or SP to mark all read.\n\ ! 734: n to forget it.\n\ ! 735: u to mark all and unsubscribe.\n\ ! 736: ",stdout) FLUSH; ! 737: #endif ! 738: goto reask_catchup; ! 739: } ! 740: else if (*buf == 'n' || *buf == 'q') { ! 741: return AS_ASK; ! 742: } ! 743: else if (*buf != 'y' && *buf != 'u') { ! 744: fputs(hforhelp,stdout) FLUSH; ! 745: settle_down(); ! 746: goto reask_catchup; ! 747: } ! 748: for (i = firstart; i <= lastart; i++) { ! 749: ctl_set(i); /* mark as read */ ! 750: } ! 751: #ifdef DELAYMARK ! 752: if (dmfp) ! 753: yankback(); ! 754: #endif ! 755: if (*buf == 'u') { ! 756: rcchar[ng] = NEGCHAR; ! 757: return AS_CLEAN; ! 758: } ! 759: art = lastart+1; ! 760: forcelast = FALSE; ! 761: return AS_NORM; ! 762: case 'Q': ! 763: exit_code = NG_ASK; ! 764: /* FALL THROUGH */ ! 765: case 'q': /* go back up to newsgroup level? */ ! 766: return AS_CLEAN; ! 767: case 'j': ! 768: putchar('\n') FLUSH; ! 769: if (art <= lastart) ! 770: mark_as_read(art); ! 771: return AS_ASK; ! 772: case 'h': { /* help? */ ! 773: int cmd; ! 774: ! 775: if ((cmd = help_art()) > 0) ! 776: pushchar(cmd); ! 777: return AS_ASK; ! 778: } ! 779: case '&': ! 780: if (switcheroo()) /* get rest of command */ ! 781: return AS_INP; /* if rubbed out, try something else */ ! 782: return AS_ASK; ! 783: case '#': ! 784: #ifdef VERBOSE ! 785: IF(verbose) ! 786: printf("\nThe last article is %ld.\n",(long)lastart) FLUSH; ! 787: ELSE ! 788: #endif ! 789: #ifdef TERSE ! 790: printf("\n%ld\n",(long)lastart) FLUSH; ! 791: #endif ! 792: return AS_ASK; ! 793: case '=': { ! 794: char tmpbuf[256]; ! 795: ART_NUM oldart = art; ! 796: int cmd; ! 797: char *subjline = getval("SUBJLINE",Nullch); ! 798: #ifndef CACHESUBJ ! 799: char *s; ! 800: #endif ! 801: ! 802: page_init(); ! 803: #ifdef CACHESUBJ ! 804: if (!subj_list) ! 805: fetchsubj(art,TRUE,FALSE); ! 806: #endif ! 807: for (i=firstart; i<=lastart && !int_count; i++) { ! 808: #ifdef CACHESUBJ ! 809: if (!was_read(i) && ! 810: (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE)) && ! 811: *subj_list[OFFSET(i)] ) { ! 812: sprintf(tmpbuf,"%5ld ", i); ! 813: if (subjline) { ! 814: art = i; ! 815: interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline); ! 816: } ! 817: else ! 818: safecpy(tmpbuf + 6, subj_list[OFFSET(i)], ! 819: (sizeof tmpbuf) - 6); ! 820: if (cmd = print_lines(tmpbuf,NOMARKING)) { ! 821: if (cmd > 0) ! 822: pushchar(cmd); ! 823: break; ! 824: } ! 825: } ! 826: #else ! 827: if (!was_read(i) && (s = fetchsubj(i,FALSE,FALSE)) && *s) { ! 828: sprintf(tmpbuf,"%5ld ", i); ! 829: if (subjline) { /* probably fetches it again! */ ! 830: art = i; ! 831: interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline); ! 832: } ! 833: else ! 834: safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6); ! 835: if (cmd = print_lines(tmpbuf,NOMARKING)) { ! 836: if (cmd > 0) ! 837: pushchar(cmd); ! 838: break; ! 839: } ! 840: } ! 841: #endif ! 842: } ! 843: int_count = 0; ! 844: art = oldart; ! 845: return AS_ASK; ! 846: } ! 847: case '^': ! 848: art = firstart; ! 849: #ifdef ARTSEARCH ! 850: srchahead = 0; ! 851: #endif ! 852: return AS_NORM; ! 853: #if defined(CACHESUBJ) && defined(DEBUGGING) ! 854: case 'D': ! 855: printf("\nFirst article: %ld\n",(long)firstart) FLUSH; ! 856: if (!subj_list) ! 857: fetchsubj(art,TRUE,FALSE); ! 858: if (subj_list != Null(char **)) { ! 859: for (i=1; i<=lastart && !int_count; i++) { ! 860: if (subj_list[OFFSET(i)]) ! 861: printf("%5ld %c %s\n", ! 862: i, (was_read(i)?'y':'n'), subj_list[OFFSET(i)]) FLUSH; ! 863: } ! 864: } ! 865: int_count = 0; ! 866: return AS_ASK; ! 867: #endif ! 868: case 'v': ! 869: if (art <= lastart) { ! 870: reread = TRUE; ! 871: do_hiding = FALSE; ! 872: } ! 873: return AS_NORM; ! 874: #ifdef ROTATION ! 875: case Ctl('x'): ! 876: #endif ! 877: case Ctl('r'): ! 878: #ifdef ROTATION ! 879: rotate = (*buf==Ctl('x')); ! 880: #endif ! 881: if (art <= lastart) ! 882: reread = TRUE; ! 883: return AS_NORM; ! 884: #ifdef ROTATION ! 885: case 'X': ! 886: rotate = !rotate; ! 887: /* FALL THROUGH */ ! 888: #else ! 889: case Ctl('x'): ! 890: case 'x': ! 891: case 'X': ! 892: notincl("x"); ! 893: return AS_ASK; ! 894: #endif ! 895: case 'l': case Ctl('l'): /* refresh screen */ ! 896: if (art <= lastart) { ! 897: reread = TRUE; ! 898: clear(); ! 899: do_fseek = TRUE; ! 900: artline = topline; ! 901: if (artline < 0) ! 902: artline = 0; ! 903: } ! 904: return AS_NORM; ! 905: case 'b': case Ctl('b'): /* back up a page */ ! 906: if (art <= lastart) { ! 907: ART_LINE target; ! 908: ! 909: reread = TRUE; ! 910: clear(); ! 911: do_fseek = TRUE; ! 912: target = topline - (LINES - 2); ! 913: artline = topline; ! 914: do { ! 915: artline--; ! 916: } while (artline >= 0 && artline > target && ! 917: vrdary(artline-1) >= 0); ! 918: topline = artline; ! 919: if (artline < 0) ! 920: artline = 0; ! 921: } ! 922: return AS_NORM; ! 923: case '!': /* shell escape */ ! 924: if (escapade()) ! 925: return AS_INP; ! 926: return AS_ASK; ! 927: case 'C': { ! 928: cancel_article(); ! 929: return AS_ASK; ! 930: } ! 931: case 'R': ! 932: case 'r': { /* reply? */ ! 933: reply(); ! 934: return AS_ASK; ! 935: } ! 936: case 'F': ! 937: case 'f': { /* followup command */ ! 938: followup(); ! 939: forcegrow = TRUE; /* recalculate lastart */ ! 940: return AS_ASK; ! 941: } ! 942: case '|': ! 943: case 'w': case 'W': ! 944: case 's': case 'S': /* save command */ ! 945: if (save_article() == SAVE_ABORT) ! 946: return AS_INP; ! 947: return AS_ASK; ! 948: #ifdef DELAYMARK ! 949: case 'Y': /* yank back M articles */ ! 950: yankback(); ! 951: art = firstart; /* from the beginning */ ! 952: return AS_NORM; /* pretend nothing happened */ ! 953: #endif ! 954: #ifdef STRICTCR ! 955: case '\n': ! 956: fputs(badcr,stdout) FLUSH; ! 957: return AS_ASK; ! 958: #endif ! 959: default: ! 960: printf("\n%s",hforhelp) FLUSH; ! 961: settle_down(); ! 962: return AS_ASK; ! 963: } ! 964: } ! 965: ! 966: #ifdef MAILCALL ! 967: /* see if there is any mail */ ! 968: ! 969: void ! 970: setmail() ! 971: { ! 972: if (! (mailcount++)) { ! 973: char *mailfile = filexp(getval("MAILFILE",MAILFILE)); ! 974: ! 975: if (stat(mailfile,&filestat) < 0 || !filestat.st_size ! 976: || filestat.st_atime > filestat.st_mtime) ! 977: mailcall = nullstr; ! 978: else ! 979: mailcall = "(Mail) "; ! 980: } ! 981: mailcount %= 10; /* check every 10 articles */ ! 982: } ! 983: #endif ! 984: ! 985: void ! 986: setdfltcmd() ! 987: { ! 988: if (toread[ng]) { ! 989: #ifdef ARTSEARCH ! 990: if (srchahead) ! 991: dfltcmd = "^Nnpq"; ! 992: else ! 993: #endif ! 994: dfltcmd = "npq"; ! 995: } ! 996: else { ! 997: if (art > lastart) ! 998: dfltcmd = "qnp"; ! 999: else ! 1000: dfltcmd = "npq"; ! 1001: } ! 1002: } ! 1003:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.