home *** CD-ROM | disk | FTP | other *** search
- /* $Header: E:\SRC\UUPC\RN\RCS\NG.C 1.2 1992/11/22 21:09:09 ahd Exp $
- *
- * $Log: NG.C $
- * Revision 1.2 1992/11/22 21:09:09 ahd
- * Back off use of strpool for memory allocation
- *
- * Revision 1.1 1992/11/21 06:14:58 ahd
- * Initial
- *
- *
- * Rev 1.0 18 Nov 1990 0:21:50
- * Initial revision.
- * Revision 4.3.2.7 90/04/21 14:44:23 sob
- * Revised previous patch insure that it does not decrement below zero.
- *
- * Revision 4.3.2.6 90/03/22 23:04:49 sob
- * Fixes provided by Wayne Davison <drivax!davison>
- *
- * Revision 4.3.2.5 89/12/09 01:18:42 sob
- * Fixed a bad call to nntpopen().
- *
- * Revision 4.3.2.4 89/11/28 01:51:20 sob
- * Removed redundant #include directive.
- *
- * Revision 4.3.2.3 89/11/27 01:31:03 sob
- * Altered NNTP code per ideas suggested by Bela Lubkin
- * <filbo@gorn.santa-cruz.ca.us>
- *
- * Revision 4.3.2.2 89/11/26 22:53:35 sob
- * Add new patches to make RRN be faster.
- *
- * Revision 4.3.2.1 89/11/06 00:54:27 sob
- * Added RRN support from NNTP 1.5
- *
- * Revision 4.3.1.6 85/09/10 11:03:42 lwall
- * Improved %m in in_char().
- *
- * Revision 4.3.1.5 85/09/05 12:34:37 lwall
- * Catchup command could make unread article count too big.
- *
- * Revision 4.3.1.4 85/07/23 18:19:46 lwall
- * Added MAILCALL environment variable.
- *
- * Revision 4.3.1.3 85/05/16 16:48:09 lwall
- * Fixed unsubsubscribe.
- *
- * Revision 4.3.1.2 85/05/13 09:29:28 lwall
- * Added CUSTOMLINES option.
- *
- * Revision 4.3.1.1 85/05/10 11:36:00 lwall
- * Branch for patches.
- *
- * Revision 4.3 85/05/01 11:43:43 lwall
- * Baseline for release with 4.3bsd.
- *
- */
-
- #ifdef msdos
- #include <dos.h>
- #endif
-
- #include <conio.h>
- #include <stdio.h>
- #include <time.h>
- #include <stdlib.h>
-
- #include "lib.h"
- #include "ssleep.h"
-
- currentfile();
-
- #include "EXTERN.h"
- #include "common.h"
- #include "rn.h"
- #include "term.h"
- #include "final.h"
- #include "util.h"
- #include "artsrch.h"
- #include "cheat.h"
- #include "help.h"
- #include "kfile.h"
- #include "rcstuff.h"
- #include "head.h"
- #include "bits.h"
- #include "art.h"
- #include "artio.h"
- #include "ngstuff.h"
- #include "intrp.h"
- #include "respond.h"
- #include "ngdata.h"
- #include "backpage.h"
- #include "rcln.h"
- #include "last.h"
- #include "search.h"
-
- #ifdef SERVER
- #include "server.h"
- #endif
-
- #include "INTERN.h"
- #include "ng.h"
- #include "artstate.h" /* somebody has to do it */
-
- /* art_switch() return values */
-
- #define AS_NORM 0
- #define AS_INP 1
- #define AS_ASK 2
- #define AS_CLEAN 3
-
- ART_NUM recent_art = 0; /* previous article #
- * for '-' command */
- ART_NUM curr_art = 0; /* current article # */
- int exit_code = NG_NORM;
-
- void
- ng_init()
- {
-
- #ifdef KILLFILES
- open_kfile(KF_GLOBAL);
- #endif
-
- #ifdef CUSTOMLINES
- init_compex(&hide_compex);
- init_compex(&page_compex);
- #endif
- }
-
- /* do newsgroup on line ng with name ngname */
-
- /* assumes that we are chdir'ed to SPOOL, and assures that that is
- * still true upon return, but chdirs to SPOOL/ngname in between
- *
- * If you can understand this routine, you understand most of the program.
- * The basic structure is:
- * for each desired article
- * for each desired page
- * for each line on page
- * if we need another line from file
- * get it
- * if it's a header line
- * do special things
- * for each column on page
- * put out a character
- * end loop
- * end loop
- * end loop
- * end loop
- *
- * (Actually, the pager is in another routine.)
- *
- * The chief problem is deciding what is meant by "desired". Most of
- * the messiness of this routine is due to the fact that people want
- * to do unstructured things all the time. I have used a few judicious
- * goto's where I thought it improved readability. The rest of the messiness
- * arises from trying to be both space and time efficient. Have fun.
- */
-
- int
- do_newsgroup(start_command)
- char *start_command; /* command to fake up
- * first */
- {
-
- #ifdef SERVER
- char ser_line[256];
- char artname[32];
- static long our_pid;
-
- #endif /* SERVER */
- char oldmode = mode;
- register long i; /* scratch */
- int skipstate; /* how many unavailable
- * articles */
-
- /* have we skipped already? */
-
- char *whatnext = "%sWhat next? [%s]";
-
- #ifdef SERVER
- if (our_pid == 0) /* Agreed, this is gross */
- our_pid = getpid();
- #endif /* SERVER */
-
- #ifdef ARTSEARCH
- srchahead = (scanon && ((ART_NUM) toread[ng]) >= scanon ? -1 : 0);
- /* did they say -S? */
- #endif
-
- mode = 'a';
- recent_art = curr_art = 0;
- exit_code = NG_NORM;
-
- #ifdef SERVER
- sprintf(ser_line, "GROUP %s", ngname);
- put_server(ser_line);
- if (get_server(ser_line, sizeof (ser_line)) < 0)
- {
- fprintf(stderr, "rrn: Unexpected close of server socket.\n");
- finalize(1);
- }
- if (*ser_line != CHAR_OK)
- {
- if (atoi(ser_line) != ERR_NOGROUP)
- fprintf(stderr, "rrn: server response to GROUP %s:\n%s\n",
- ngname, ser_line);
- return (-1);
- }
- #else /* not SERVER */
-
- #ifndef msdos
- if (eaccess(ngdir, 5))
- { /* directory read
- * protected? */
- if (eaccess(ngdir, 0))
- {
-
- #ifdef VERBOSE
- IF(verbose)
- printf("\nNewsgroup %s does not have a spool directory!\n",
- ngname) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- printf("\nNo spool for %s!\n", ngname) FLUSH;
- #endif
-
- #ifdef CATCHUP
- catch_up(ng);
- #endif
-
- toread[ng] = TR_NONE;
- }
- else
- {
-
- #ifdef VERBOSE
- IF(verbose)
- printf("\nNewsgroup %s is not currently accessible.\n",
- ngname) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- printf("\n%s not readable.\n", ngname) FLUSH;
- #endif
-
- toread[ng] = TR_NONE; /* make this newsgroup
- * invisible */
- /* (temporarily) */
- }
- mode = oldmode;
- return -1;
- }
- #endif /* msdos */
-
- /* chdir to newsgroup subdirectory */
-
- if (chdir(ngdir))
- {
- printerr(ngdir);
- printf(nocd, ngdir) FLUSH;
-
- mode = oldmode;
- return -1;
- }
- #endif /* SERVER */
-
- #ifdef CACHESUBJ
- subj_list = Null(char **);/* no subject list till
- * needed */
- #endif
-
- /* initialize control bitmap */
-
- if (initctl())
- {
- mode = oldmode;
- return -1;
- }
-
- /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
-
- in_ng = TRUE; /* tell the world we are
- * here */
- forcelast = TRUE; /* if 0 unread, do not
- * bomb out */
- art = firstart;
-
- /* remember what newsgroup we were in for sake of posterity */
-
- writelast();
-
- /* see if there are any special searches to do */
-
- #ifdef KILLFILES
- open_kfile(KF_LOCAL);
-
- #ifdef VERBOSE
- IF(verbose)
- kill_unwanted(firstart, "Looking for articles to kill...\n\n", TRUE);
- ELSE
- #endif
-
- #ifdef TERSE
- kill_unwanted(firstart, "Killing...\n\n", TRUE);
- #endif
-
- #endif
-
- /* do they want a special top line? */
-
- firstline = getval("FIRSTLINE", Nullch);
-
- /* custom line suppression, custom page ending */
-
- #ifdef CUSTOMLINES
- if (hideline = getval("HIDELINE", Nullch))
- compile(&hide_compex, hideline, TRUE, TRUE);
- if (pagestop = getval("PAGESTOP", Nullch))
- compile(&page_compex, pagestop, TRUE, TRUE);
- #endif
-
- /* now read each unread article */
-
- rc_changed = doing_ng = TRUE; /* enter the twilight
- * zone */
- skipstate = 0; /* we have not skipped
- * anything (yet) */
- checkcount = 0; /* do not checkpoint for
- * a while */
- do_fseek = FALSE; /* start 1st article at
- * top */
- if (art > lastart)
- art = firstart; /* init the for loop
- * below */
- for (; art <= lastart + 1;)
- { /* for each article */
-
- /* do we need to "grow" the newsgroup? */
-
- if (art > lastart || forcegrow)
- grow_ctl();
- check_first(art); /* make sure firstart is
- * still 1st */
- if (start_command)
- { /* fake up an initial
- * command? */
- prompt = whatnext;
- strcpy(buf, start_command);
- free(start_command);
- start_command = Nullch;
- art = lastart + 1;
- goto article_level;
- }
- if (art > lastart)
- { /* are we off the end
- * still? */
- ART_NUM ucount = 0; /* count of unread
- * articles left */
-
- for (i = firstart; i <= lastart; i++)
- if (!(ctl_read(i)))
- ucount++; /* count the unread
- * articles */
-
- #ifdef DEBUGGING
- /* NOSTRICT */
- if (debug && ((ART_NUM) toread[ng]) != ucount)
- printf("(toread=%ld sb %ld)", (long) toread[ng], (long) ucount)
- FLUSH;
- #endif
-
- /* NOSTRICT */
- toread[ng] = (ART_UNREAD) ucount; /* this is perhaps
- * pointless */
- art = lastart + 1; /* keep bitmap
- * references sane */
- if (art != curr_art)
- {
- recent_art = curr_art;
- /* remember last article # (for '-') */
- curr_art = art; /* remember this article
- * # */
- }
- if (erase_screen)
- clear(); /* clear the screen */
- else
- fputs("\n\n", stdout) FLUSH;
-
- #ifdef VERBOSE
- IF(verbose)
- printf("End of newsgroup %s.", ngname);
- /* print pseudo-article */
- ELSE
- #endif
-
- #ifdef TERSE
- printf("End of %s", ngname);
- #endif
-
- if (ucount)
- {
- printf(" (%ld article%s still unread)",
- (long) ucount, ucount == 1 ? nullstr : "s");
- }
- else
- {
- if (!forcelast)
- goto cleanup; /* actually exit
- * newsgroup */
- }
- prompt = whatnext;
-
- #ifdef ARTSEARCH
- srchahead = 0; /* no more subject
- * search mode */
- #endif
-
- fputs("\n\n", stdout) FLUSH;
- skipstate = 0; /* back to none skipped */
- }
- else if (!reread && was_read(art))
- {
- /* has this article been read? */
- art++; /* then skip it */
- continue;
- }
- else if
- (!reread && !was_read(art)
-
- #ifdef SERVER
- && nntpopen(art, HEAD) == Nullfp)
- {
- #else
- && artopen(art) == Nullfp)
- { /* never read it, &
- * cannot find it? */
- if (errno != ENOENT)
- { /* has it not been
- * deleted? */
-
- #ifdef VERBOSE
- IF(verbose)
- printf("\n(Article %ld exists but is unreadable.)\n",
- (long) art) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- printf("\n(%ld unreadable.)\n", (long) art) FLUSH;
- #endif
-
- skipstate = 0;
- ssleep(2);
- }
- #endif
-
- switch (skipstate++)
- {
- case 0:
- clear();
-
- #ifdef VERBOSE
- IF(verbose)
- fputs("Skipping unavailable article", stdout);
- ELSE
- #endif
-
- #ifdef TERSE
- fputs("Skipping", stdout);
- #endif
-
- pad(just_a_sec / 3);
- break;
- case 1:
- fputs("..", stdout);
- fflush(stdout);
- break;
- default:
- putchar('.');
- fflush(stdout);
-
- #ifndef SERVER
- #define READDIR
-
- #ifdef READDIR
- { /* fast skip patch */
- ART_NUM newart;
-
- if (!(newart = getngmin(".", art)))
- newart = lastart + 1;
- for (i = art; i < newart; i++)
- oneless(i);
- art = newart - 1;
- }
- #endif
-
- #else
- {
- char ser_line[256];
- ART_NUM newart;
-
- put_server("NEXT");
- if (get_server(ser_line, sizeof (ser_line)) < 0)
- {
- fprintf(stderr,
- "rrn: unexpected close of server socket.\n");
- finalize(1);
- }
- if (ser_line[0] != CHAR_OK)
- newart = lastart + 1;
- else
- newart = atoi(ser_line + 4);
- for (i = art; i < newart; i++)
- oneless(i);
- art = newart - 1;
- }
- #endif /* SERVER */
-
- break;
- }
- oneless(art); /* mark deleted as read */
- art++; /* try next article */
- continue;
- }
- else
- { /* we have a real live
- * article */
- skipstate = 0; /* back to none skipped */
- if (art != curr_art)
- {
- recent_art = curr_art;
- /* remember last article # (for '-') */
- curr_art = art; /* remember this article
- * # */
- }
- if (!do_fseek)
- { /* starting at top of
- * article? */
- artline = 0; /* start at the
- * beginning */
- topline = -1; /* and remember top line
- * of screen */
- /* (line # within article file) */
- }
- clear(); /* clear screen */
- artopen(art); /* make sure article
- * file is open */
- if (artfp == Nullfp)
- { /* could not find
- * article? */
- printf("Article %ld of %s is not available.\n\n",
- (long) art, ngname) FLUSH;
- prompt = whatnext;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
- }
- else
- { /* found it, so print it */
- switch (do_article())
- {
- case DA_CLEAN: /* quit newsgroup */
- goto cleanup;
- case DA_TOEND: /* do not mark as read */
- goto reask_article;
- case DA_RAISE: /* reparse command at
- * end of art */
- goto article_level;
- case DA_NORM: /* normal end of article */
- break;
- }
- }
- mark_as_read(art); /* mark current article
- * as read */
- reread = FALSE;
- do_hiding = TRUE;
-
- #ifdef ROTATION
- rotate = FALSE;
- #endif
- }
-
- /* if these gotos bother you, think of this as a little state machine */
-
- reask_article:
-
- #ifdef MAILCALL
- setmail();
- #endif
-
- setdfltcmd();
-
- #ifdef CLEAREOL
- if (erase_screen && can_home_clear)
- clear_rest();
- #endif /* CLEAREOL */
-
- unflush_output(); /* disable any ^O in
- * effect */
- standout(); /* enter standout mode */
- printf(prompt, mailcall, dfltcmd); /* print prompt,
- * whatever it is */
- un_standout(); /* leave standout mode */
- putchar(' ');
- fflush(stdout);
- reinp_article:
- eat_typeahead();
-
- #ifdef PENDING
- look_ahead(); /* see what we can do in
- * advance */
- if (!input_pending())
- collect_subjects(); /* loads subject cache
- * until */
- /* input is pending */
- #endif
-
- getcmd(buf);
- if (errno || *buf == '\f')
- {
- if (LINES < 100 && !int_count)
- *buf = '\f'; /* on CONT fake up
- * refresh */
- else
- {
- putchar('\n') FLUSH; /* but only on a crt */
- goto reask_article;
- }
- }
- article_level:
-
- /* parse and process article level command */
-
- switch (art_switch())
- {
- case AS_INP: /* multichar command
- * rubbed out */
- goto reinp_article;
- case AS_ASK: /* reprompt "End of
- * article..." */
- goto reask_article;
- case AS_CLEAN: /* exit newsgroup */
- goto cleanup;
- case AS_NORM: /* display article art */
- break;
- }
- } /* end of article
- * selection loop */
-
- /* shut down newsgroup */
-
- cleanup:
-
- #ifdef KILLFILES
- kill_unwanted(firstart, "\nCleaning up...\n\n", FALSE);
- /* do cleanup from KILL file, if any */
- #endif
-
- in_ng = FALSE; /* leave newsgroup state */
- if (artfp != Nullfp)
- { /* article still open? */
- fclose(artfp); /* close it */
- artfp = Nullfp; /* and tell the world */
-
- #ifdef SERVER
- sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid);
- UNLINK(artname);
- #endif /* SERVER */
-
- openart = 0;
- }
- putchar('\n') FLUSH;
- yankback(); /* do a Y command */
- restore_ng(); /* reconstitute .newsrc
- * line */
- doing_ng = FALSE; /* tell sig_catcher to
- * cool it */
- free(ctlarea); /* return the control
- * area */
-
- #ifdef CACHESUBJ
- if (subj_list)
- {
- for (i = OFFSET(lastart); i >= 0; --i)
- if (subj_list[i])
- free(subj_list[i]);
-
- #ifndef lint
- free((char *) subj_list);
- #endif /* lint */
- }
- #endif
-
- write_rc(); /* and update .newsrc */
- rc_changed = FALSE; /* tell sig_catcher it
- * is ok */
- if (chdir(spool))
- {
- printerr(ngdir);
- printf(nocd, spool) FLUSH;
- sig_catcher(0);
- }
-
- #ifdef KILLFILES
- if (localkfp)
- {
- fclose(localkfp);
- localkfp = Nullfp;
- }
- #endif
-
- mode = oldmode;
- return exit_code;
- } /* Whew! */
-
- /* decide what to do at the end of an article */
-
- int
- art_switch()
- {
- register ART_NUM i;
-
- setdef(buf, dfltcmd);
-
- #ifdef VERIFY
- printcmd();
- #endif
-
- switch (*buf)
- {
- case 'p': /* find previous unread
- * article */
- do
- {
- if (art <= firstart)
- break;
- art--;
-
- #ifdef SERVER
- } while (was_read(art) || nntpopen(art, HEAD) == Nullfp);
- #else
- } while (was_read(art) || artopen(art) == Nullfp);
- #endif
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
- case 'P': /* goto previous article */
- if (art > absfirst)
- art--;
- else
- {
-
- #ifdef VERBOSE
- IF(verbose)
- fputs("\n\
- There are no articles prior to this one.\n\
- ", stdout) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- fputs("\nNo previous articles\n", stdout) FLUSH;
- #endif
-
- return AS_ASK;
- }
- reread = TRUE;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
- case '-':
- if (recent_art)
- {
- art = recent_art;
- reread = TRUE;
-
- #ifdef ARTSEARCH
- srchahead = -(srchahead != 0);
- #endif
-
- return AS_NORM;
- }
- else
- {
- exit_code = NG_MINUS;
- return AS_CLEAN;
- }
- case 'n': /* find next unread
- * article? */
- if (art > lastart)
- {
- if (toread[ng])
- art = firstart;
- else
- return AS_CLEAN;
- }
-
- #ifdef ARTSEARCH
- else if (scanon && srchahead)
- {
- *buf = Ctl('n');
- goto normal_search;
- }
- #endif
-
- else
- art++;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
- case 'N': /* goto next article */
- if (art > lastart)
- art = absfirst;
- else
- art++;
- if (art <= lastart)
- reread = TRUE;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
- case '$':
- art = lastart + 1;
- forcelast = TRUE;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
- case '1':
- case '2':
- case '3': /* goto specified
- * article */
- case '4':
- case '5':
- case '6': /* or do something with
- * a range */
- case '7':
- case '8':
- case '9':
- case '.':
- forcelast = TRUE;
- switch (numnum())
- {
- case NN_INP:
- return AS_INP;
- case NN_ASK:
- return AS_ASK;
- case NN_REREAD:
- reread = TRUE;
-
- #ifdef ARTSEARCH
- if (srchahead)
- srchahead = -1;
- #endif
-
- break;
- case NN_NORM:
- if (was_read(art))
- {
- art = firstart;
- pad(just_a_sec / 3);
- }
- else
- return AS_ASK;
- break;
- }
- return AS_NORM;
- case Ctl('k'):
- edit_kfile();
- return AS_ASK;
- case 'K':
- case 'k':
- case Ctl('n'):
- case Ctl('p'):
- case '/':
- case '?':
-
- #ifdef ARTSEARCH
- normal_search:
- { /* search for article by
- * pattern */
- char cmd = *buf;
-
- reread = TRUE; /* assume this */
- switch (art_search(buf, (sizeof buf), TRUE))
- {
- case SRCH_ERROR:
- return AS_ASK;
- case SRCH_ABORT:
- return AS_INP;
- case SRCH_INTR:
-
- #ifdef VERBOSE
- IF(verbose)
- printf("\n(Interrupted at article %ld)\n", (long) art) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- printf("\n(Intr at %ld)\n", (long) art) FLUSH;
- #endif
-
- art = curr_art;
- /* restore to current article */
- return AS_ASK;
- case SRCH_DONE:
- fputs("done\n", stdout) FLUSH;
- pad(just_a_sec / 3); /* 1/3 second */
- if (srchahead)
- art = firstart;
- else
- art = curr_art;
- reread = FALSE;
- return AS_NORM;
- case SRCH_SUBJDONE:
-
- #ifdef UNDEF
- fputs("\n\n\n\nSubject not found.\n", stdout) FLUSH;
- pad(just_a_sec / 3); /* 1/3 second */
- #endif
-
- art = firstart;
- reread = FALSE;
- return AS_NORM;
- case SRCH_NOTFOUND:
- fputs("\n\n\n\nNot found.\n", stdout) FLUSH;
- art = curr_art; /* restore to current
- * article */
- return AS_ASK;
- case SRCH_FOUND:
- if (cmd == Ctl('n') || cmd == Ctl('p'))
- oldsubject = TRUE;
- break;
- }
- return AS_NORM;
- }
- #else
- buf[1] = '\0';
- notincl(buf);
- return AS_ASK;
- #endif
-
- case 'u': /* unsubscribe from this
- * newsgroup? */
- rcchar[ng] = NEGCHAR;
- return AS_CLEAN;
- case 'M':
-
- #ifdef DELAYMARK
- if (art <= lastart)
- {
- delay_unmark(art);
- printf("\nArticle %ld will return.\n", (long) art) FLUSH;
- }
- #else
- notincl("M");
- #endif
-
- return AS_ASK;
- case 'm':
- if (art <= lastart)
- {
- unmark_as_read(art);
- printf("\nArticle %ld marked as still unread.\n", (long) art) FLUSH;
- }
- return AS_ASK;
- case 'c': /* catch up */
- reask_catchup:
-
- #ifdef VERBOSE
- IF(verbose)
- in_char("\nDo you really want to mark everything as read? [yn] ",
- 'C');
- ELSE
- #endif
-
- #ifdef TERSE
- in_char("\nReally? [ynh] ", 'C');
- #endif
-
- putchar('\n') FLUSH;
- setdef(buf, "y");
-
- #ifdef VERIFY
- printcmd();
- #endif
-
- if (*buf == 'h')
- {
-
- #ifdef VERBOSE
- IF(verbose)
- fputs("\
- Type y or SP to mark all articles as read.\n\
- Type n to leave articles marked as they are.\n\
- Type u to mark everything read and unsubscribe.\n\
- ", stdout) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- fputs("\
- y or SP to mark all read.\n\
- n to forget it.\n\
- u to mark all and unsubscribe.\n\
- ", stdout) FLUSH;
- #endif
-
- goto reask_catchup;
- }
- else if (*buf == 'n' || *buf == 'q')
- {
- return AS_ASK;
- }
- else if (*buf != 'y' && *buf != 'u')
- {
- fputs(hforhelp, stdout) FLUSH;
- settle_down();
- goto reask_catchup;
- }
- for (i = firstart; i <= lastart; i++)
- {
- oneless(i); /* mark as read */
- }
-
- #ifdef DELAYMARK
- if (dmfp)
- yankback();
- #endif
-
- if (*buf == 'u')
- {
- rcchar[ng] = NEGCHAR;
- return AS_CLEAN;
- }
- art = lastart + 1;
- forcelast = FALSE;
- return AS_NORM;
- case 'Q':
- exit_code = NG_ASK;
- /* FALL THROUGH */
- case 'q': /* go back up to
- * newsgroup level? */
- return AS_CLEAN;
- case 'j':
- putchar('\n') FLUSH;
- if (art <= lastart)
- mark_as_read(art);
- return AS_ASK;
- case 'h':
- { /* help? */
- int cmd;
-
- if ((cmd = help_art()) > 0)
- pushchar(cmd);
- return AS_ASK;
- }
- case '&':
- if (switcheroo()) /* get rest of command */
- return AS_INP; /* if rubbed out, try
- * something else */
- return AS_ASK;
- case '#':
-
- #ifdef VERBOSE
- IF(verbose)
- printf("\nThe last article is %ld.\n", (long) lastart) FLUSH;
- ELSE
- #endif
-
- #ifdef TERSE
- printf("\n%ld\n", (long) lastart) FLUSH;
- #endif
-
- return AS_ASK;
- case '=':
- {
- char tmpbuf[256];
- ART_NUM oldart = art;
- int cmd;
- char *subjline = getval("SUBJLINE", Nullch);
-
- #ifndef CACHESUBJ
- char *s;
-
- #endif
-
- page_init();
-
- #ifdef CACHESUBJ
- if (!subj_list)
- fetchsubj(art, TRUE, FALSE);
- #endif
-
- for (i = firstart; i <= lastart && !int_count; i++)
- {
-
- #ifdef CACHESUBJ
- if (!was_read(i) &&
- (subj_list[OFFSET(i)] != Nullch || fetchsubj(i, FALSE, FALSE)) &&
- *subj_list[OFFSET(i)])
- {
- sprintf(tmpbuf, "%5ld ", i);
- if (subjline)
- {
- art = i;
- interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
- }
- else
- safecpy(tmpbuf + 6, subj_list[OFFSET(i)],
- (sizeof tmpbuf) - 6);
- if (cmd = print_lines(tmpbuf, NOMARKING))
- {
- if (cmd > 0)
- pushchar(cmd);
- break;
- }
- }
- #else
- if (!was_read(i) && (s = fetchsubj(i, FALSE, FALSE)) && *s)
- {
- sprintf(tmpbuf, "%5ld ", i);
- if (subjline)
- { /* probably fetches it
- * again! */
- art = i;
- interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
- }
- else
- safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6);
- if (cmd = print_lines(tmpbuf, NOMARKING))
- {
- if (cmd > 0)
- pushchar(cmd);
- break;
- }
- }
- #endif
- }
- int_count = 0;
- art = oldart;
- return AS_ASK;
- }
- case '^':
- art = firstart;
-
- #ifdef ARTSEARCH
- srchahead = 0;
- #endif
-
- return AS_NORM;
-
- #if defined(CACHESUBJ) && defined(DEBUGGING)
- case 'D':
- printf("\nFirst article: %ld\n", (long) firstart) FLUSH;
- if (!subj_list)
- fetchsubj(art, TRUE, FALSE);
- if (subj_list != Null(char **))
- {
- for (i = 1; i <= lastart && !int_count; i++)
- {
- if (subj_list[OFFSET(i)])
- printf("%5ld %c %s\n",
- i, (was_read(i) ? 'y' : 'n'), subj_list[OFFSET(i)]) FLUSH;
- }
- }
- int_count = 0;
- return AS_ASK;
- #endif
-
- case 'v':
- if (art <= lastart)
- {
- reread = TRUE;
- do_hiding = FALSE;
- }
- return AS_NORM;
-
- #ifdef ROTATION
- case Ctl('x'):
- #endif
-
- case Ctl('r'):
-
- #ifdef ROTATION
- rotate = (*buf == Ctl('x'));
- #endif
-
- if (art <= lastart)
- reread = TRUE;
- return AS_NORM;
-
- #ifdef ROTATION
- case 'X':
- rotate = !rotate;
- /* FALL THROUGH */
- #else
- case Ctl('x'):
- case 'x':
- case 'X':
- notincl("x");
- return AS_ASK;
- #endif
-
- case 'l':
- case Ctl('l'): /* refresh screen */
- if (art <= lastart)
- {
- reread = TRUE;
- clear();
- do_fseek = TRUE;
- artline = topline;
- if (artline < 0)
- artline = 0;
- }
- return AS_NORM;
- case 'b':
- case Ctl('b'): /* back up a page */
- if (art <= lastart)
- {
- ART_LINE target;
-
- reread = TRUE;
- clear();
- do_fseek = TRUE;
- target = topline - (LINES - 2);
- artline = topline;
- if (artline > 0)
- do
- {
- artline--;
- } while (artline >= 0 && artline > target &&
- vrdary(artline - 1) >= 0);
- topline = artline;
- if (artline < 0)
- artline = 0;
- }
- return AS_NORM;
- case '!': /* shell escape */
- if (escapade())
- return AS_INP;
- return AS_ASK;
- case 'C':
- {
- cancel_article();
- return AS_ASK;
- }
- case 'R':
- case 'r':
- { /* reply? */
- reply();
- return AS_ASK;
- }
- case 'F':
- case 'f':
- { /* followup command */
- followup();
- forcegrow = TRUE; /* recalculate lastart */
- return AS_ASK;
- }
- case '|':
- case 'w':
- case 'W':
- case 's':
- case 'S': /* save command */
- if (save_article() == SAVE_ABORT)
- return AS_INP;
- return AS_ASK;
-
- #ifdef DELAYMARK
- case 'Y': /* yank back M articles */
- yankback();
- art = firstart; /* from the beginning */
- return AS_NORM; /* pretend nothing
- * happened */
- #endif
-
- #ifdef STRICTCR
- case '\n':
- fputs(badcr, stdout) FLUSH;
- return AS_ASK;
- #endif
-
- default:
- printf("\n%s", hforhelp) FLUSH;
- settle_down();
- return AS_ASK;
- }
- }
-
- #ifdef MAILCALL
- /* see if there is any mail */
-
- void
- setmail()
- {
- if (!(mailcount++))
- {
- char *mailfile = filexp(getval("MAILFILE", MAILFILE));
-
- if (stat(mailfile, &filestat) < 0 || !filestat.st_size
- || filestat.st_atime > filestat.st_mtime)
- mailcall = nullstr;
- else
- mailcall = getval("MAILCALL", "(Mail) ");
- }
- mailcount %= 10; /* check every 10
- * articles */
- }
-
- #endif
-
- void
- setdfltcmd()
- {
- if (toread[ng])
- {
-
- #ifdef ARTSEARCH
- if (srchahead)
- dfltcmd = "^Nnpq";
- else
- #endif
-
- dfltcmd = "npq";
- }
- else
- {
- if (art > lastart)
- dfltcmd = "qnp";
- else
- dfltcmd = "npq";
- }
- }
-