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

Defined functions

art_switch defined in line 488; used 2 times
do_newsgroup defined in line 109; used 2 times
ng_init defined in line 66; used 2 times
setdfltcmd defined in line 967; used 3 times
setmail defined in line 951; used 2 times

Defined variables

curr_art defined in line 63; used 10 times
exit_code defined in line 64; used 4 times
recent_art defined in line 62; used 5 times

Defined macros

AS_ASK defined in line 59; used 25 times
AS_CLEAN defined in line 60; used 5 times
AS_INP defined in line 58; used 5 times
AS_NORM defined in line 57; used 17 times
READDIR defined in line 332; used 1 times
Last modified: 1985-11-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2211
Valid CSS Valid XHTML 1.0 Strict