# 2.11BSD#431 - /usr/src/new/rn/ng.c

##### Functions

    art_switch        X
    do_newsgroup      X
    ng_init           X
    setdfltcmd        X
    setmail           X

##### Variables

    curr_art          X
    exit_code         X
    recent_art        X

##### Macros

    AS_ASK            X
    AS_CLEAN          X
    AS_INP            X
    AS_NORM           X
    READDIR           X

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

#### Defined functions

art_switch defined in line 542; used 2 times

- in line 480
- in /usr/src/new/rn/ng.h line 32

do_newsgroup defined in line 110; used 2 times

- in /usr/src/new/rn/ng.h line 31
- in /usr/src/new/rn/rn.c line 473

ng_init defined in line 67; used 2 times

- in /usr/src/new/rn/init.c line 181
- in /usr/src/new/rn/ng.h line 30

setdfltcmd defined in line 1021; used 3 times

- in line 448
- in /usr/src/new/rn/art.c line 809
- in /usr/src/new/rn/ng.h line 36

setmail defined in line 1005; used 2 times

- in line 446
- in /usr/src/new/rn/ng.h line 34

#### Defined variables

curr_art defined in line 64; used 10 times

- in line 137, 282-285(3), 402-405(3), 686, 695, 708

exit_code defined in line 65; used 4 times

- in line 138, 537, 593, 799

recent_art defined in line 63; used 5 times

- in line 137, 283, 403, 584-585(2)

#### Defined macros

AS_ASK defined in line 60; used 25 times

- in line 576, 641, 655, 661, 674, 688, 709, 720, 734, 740, 777, 807, 813-818(2), 828, 881, 902, 929, 962-970(3), 976, 983, 993-998(2)

AS_CLEAN defined in line 61; used 5 times

- in line 594, 601, 724, 793, 802

AS_INP defined in line 59; used 5 times

- in line 639, 676, 817, 961, 982

AS_NORM defined in line 58; used 17 times

- in line 561, 582, 590, 614, 625, 632, 658, 697, 705, 715, 797, 888, 909, 919, 940, 958, 988

READDIR defined in line 362; used 1 times

- in line 363

Last modified: 1987-05-26 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2442 |