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: }

Defined functions

art_switch defined in line 507; used 2 times
do_newsgroup defined in line 101; used 2 times
ng_init defined in line 58; used 2 times
setdfltcmd defined in line 985; used 3 times
setmail defined in line 969; used 2 times

Defined variables

curr_art defined in line 55; used 10 times
exit_code defined in line 56; used 4 times
recent_art defined in line 54; used 5 times

Defined macros

AS_ASK defined in line 51; used 25 times
AS_CLEAN defined in line 52; used 5 times
AS_INP defined in line 50; used 5 times
AS_NORM defined in line 49; used 17 times
READDIR defined in line 346; used 1 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3310
Valid CSS Valid XHTML 1.0 Strict