home *** CD-ROM | disk | FTP | other *** search
- /* rn -- new readnews program
- *
- * Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
- * Organization: System Development Corporation, Santa Monica
- *
- * begun: 01/14/83
- * 1.0: 04/08/83
- * 2.0: 09/01/83
- * RRN/RN: 11/01/89
- */
-
- static char rnid[] = "@(#)$Header: rn.c,v 4.3.3.4 91/06/26 02:25:34 davison Trn $";
- static char patchlevel[] = "Trn v1.0.3 based on Rn patchlevel 54";
-
- /* $Log: rn.c,v $
- * Revision 4.3.3.4 91/06/26 02:25:34 davison
- * Misc. fixes for minor problems.
- *
- * Revision 4.3.3.3 91/01/16 03:28:42 davison
- * Integrated rn patches 48-54. Fixed in_char and verify interaction.
- *
- * Revision 4.3.3.2 90/08/20 16:48:19 davison
- * Changed unthreaded group's default action, version #, email address.
- *
- * Revision 4.3.3.1 90/07/21 20:31:38 davison
- * Initial Trn Release
- *
- * Revision 4.3.2.11 91/01/04 22:58:24 sob
- * Checkpoint for patch 54
- *
- * Revision 4.3.2.10 90/12/30 22:58:24 sob
- * Checkpoint for patch 53
- *
- * Revision 4.3.2.9 90/12/13 22:58:24 sob
- * Checkpoint for patch 52
- *
- * Revision 4.3.2.8 90/12/10 01:35:43 sob
- * Checkpoint for patch 51
- *
- * Revision 4.3.2.7 90/11/23 20:30:43 sob
- * Checkpoint for patch 50
- *
- * Revision 4.3.2.6 90/11/22 13:55:23 sob
- * Checkpoint for patch #49
- *
- * Revision 4.3.2.5 90/11/06 01:19:43 sob
- * Checkpoint for patch 48
- *
- * Revision 4.3.2.4 90/04/03 23:11:33 sob
- * Added more information to the version command.
- *
- * Revision 4.3.2.3 90/03/22 23:05:23 sob
- * Fixes provided by Wayne Davison <drivax!davison>
- *
- * Revision 4.3.2.2 89/11/28 01:51:25 sob
- * Removed redundant #include directive.
- *
- * Revision 4.3.2.1 89/11/08 02:27:38 sob
- * Release of RN 4.3 with RRN that can be compiled from the same
- * sources as either version of the program.
- *
- * Revision 4.3.1.4 85/09/10 11:05:13 lwall
- * Improved %m in in_char().
- *
- * Revision 4.3.1.3 85/05/16 16:47:10 lwall
- * Catchup confirmation didn't grok -t.
- *
- * Revision 4.3.1.2 85/05/13 09:34:53 lwall
- * Fixed default after do_newsgroup() returns from Q command.
- *
- * Revision 4.3.1.1 85/05/10 11:38:08 lwall
- * Branch for patches.
- *
- * Revision 4.3 85/05/01 11:47:56 lwall
- * Baseline for release with 4.3bsd.
- *
- */
-
- #include "INTERN.h"
- #include "common.h"
- #include "rn.h"
- #include "EXTERN.h"
- #include "rcstuff.h"
- #include "term.h"
- #include "final.h"
- #include "ngdata.h"
- #include "util.h"
- #include "only.h"
- #include "ngsrch.h"
- #include "help.h"
- #include "last.h"
- #include "init.h"
- #include "intrp.h"
- #include "rcln.h"
- #include "sw.h"
- #include "addng.h"
- #include "ng.h"
-
- void
- rn_init()
- {
- ;
- }
-
- void
- main(argc,argv)
- int argc;
- char *argv[];
- {
- bool foundany;
- register char *s;
- bool oh_for_the_good_old_days = FALSE;
-
- #if defined(USETHREADS) && !THREAD_INIT
- /* Default to threaded operation if our name starts with a 't' */
- if ((s = rindex(argv[0],'/')) == Nullch)
- s = argv[0];
- else
- s++;
- if (*s == 't')
- use_threads = TRUE;
- #endif
- foundany = initialize(argc,argv);
-
- if (maxngtodo)
- starthere = 0;
- else if (!foundany) { /* nothing to do? */
- #ifdef VERBOSE
- if (verbose)
- fputs("\
- No unread news in subscribed-to newsgroups. To subscribe to a new\n\
- newsgroup use the g<newsgroup> command.\n\
- ",stdout) FLUSH;
- #endif
- starthere = nextrcline;
- }
-
- /* loop through all unread news */
-
- {
- char promptbuf[80];
- bool special = FALSE; /* temporarily allow newsgroup */
- /* with no unread news? */
- bool retry; /* cycle back to top of list? */
- NG_NUM recent_ng = 0;
-
- current_ng = 0;
- do {
- retry = FALSE;
- if (findlast) {
- findlast = FALSE;
- starthere = 0;
- if (*lastngname) {
- if ((ng = find_ng(lastngname)) == nextrcline)
- ng = 0;
- else {
- set_ngname(lastngname);
- set_toread(ng);
- if (toread[ng] <= TR_NONE)
- ng = 0;
- }
- }
- }
- else {
- ng = starthere;
- starthere = 0;
- }
- while (ng <= nextrcline) { /* for each newsgroup */
- mode = 'n';
- if (ng >= nextrcline) { /* after the last newsgroup? */
- ng = nextrcline; /* force it to 1 after */
- #ifdef ONLY
- if (maxngtodo) {
- if (retry)
- #ifdef VERBOSE
- IF(verbose)
- printf("\nRestriction %s%s still in effect.\n",
- ngtodo[0],
- maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("\n(\"Only\" mode.)\n",stdout) FLUSH;
- #endif
- else {
- #ifdef VERBOSE
- IF(verbose)
- fputs("\nNo articles under restriction.",
- stdout) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("\nNo \"only\" articles.",stdout) FLUSH;
- #endif
- end_only(); /* release the restriction */
- retry = TRUE;
- }
- }
- #endif
- dfltcmd = (retry ? "npq" : "qnp");
- #ifdef VERBOSE
- IF(verbose)
- sprintf(promptbuf,
- "\n******** End of newsgroups--what next? [%s] ",
- dfltcmd);
- ELSE
- #endif
- #ifdef TERSE
- sprintf(promptbuf,
- "\n**** End--next? [%s] ", dfltcmd);
- #endif
- }
- else {
- bool shoe_fits; /* newsgroup matches restriction? */
-
- if (toread[ng] >= TR_NONE) { /* recalc toread? */
- set_ngname(rcline[ng]);
- if (shoe_fits = (special || inlist(ngname)))
- set_toread(ng);
- if (paranoid) {
- recent_ng = current_ng;
- current_ng = ng;
- cleanup_rc();
- /* this may move newsgroups around */
- ng = current_ng;
- set_ngname(rcline[ng]);
- }
- }
- if (toread[ng] < (maxngtodo||special ? TR_NONE : TR_ONE) || !shoe_fits) {
- /* unwanted newsgroup? */
- ng++; /* then skip it */
- continue;
- }
- reprompt_newsgroup:
- #ifdef USETHREADS
- dfltcmd = (ThreadedGroup && select_on
- && (ART_NUM)toread[ng] >= select_on ? "+ynq" : "ynq");
- #else
- dfltcmd = "ynq";
- #endif
- #ifdef VERBOSE
- IF(verbose)
- sprintf(promptbuf,
- "\n******** %3ld unread article%s in %s--read now? [%s] ",
- (long)toread[ng], (toread[ng]==TR_ONE ? nullstr : "s"),
- ngname, dfltcmd); /* format prompt string */
- ELSE
- #endif
- #ifdef TERSE
- sprintf(promptbuf,
- "\n**** %3ld in %s--read? [%s] ",
- (long)toread[ng],
- ngname,dfltcmd); /* format prompt string */
- #endif
- }
- special = FALSE; /* go back to normal mode */
- if (ng != current_ng) {
- recent_ng = current_ng;
- /* remember previous newsgroup */
- current_ng = ng; /* remember current newsgroup */
- }
- reask_newsgroup:
- unflush_output(); /* disable any ^O in effect */
- fputs(promptbuf,stdout) FLUSH;/* print prompt */
- fflush(stdout);
- reinp_newsgroup:
- eat_typeahead();
- getcmd(buf);
- if (errno || *buf == '\f') {
- putchar('\n') FLUSH; /* if return from stop signal */
- goto reask_newsgroup; /* give them a prompt again */
- }
- setdef(buf,dfltcmd);
- #ifdef VERIFY
- printcmd();
- #endif
- switch (*buf) {
- case 'p': /* find previous unread newsgroup */
- do {
- if (ng <= 0)
- break;
- ng--;
- if (toread[ng] == TR_NONE)
- set_toread(ng);
- } while (toread[ng] <= TR_NONE);
- break;
- case 'P': /* goto previous newsgroup */
- do {
- if (ng <= 0)
- break;
- ng--;
- } while (toread[ng] < TR_NONE);
- special = TRUE; /* don't skip it if toread==0 */
- break;
- case '-':
- ng = recent_ng; /* recall previous newsgroup */
- special = TRUE; /* don't skip it if toread==0 */
- break;
- case 'q': case 'Q': case 'x': /* quit? */
- oh_for_the_good_old_days = (*buf == 'x');
- putchar('\n') FLUSH;
- ng = nextrcline+1; /* satisfy */
- retry = FALSE; /* loop conditions */
- break;
- case '^':
- putchar('\n') FLUSH;
- ng = 0;
- break;
- case 'n': /* find next unread newsgroup */
- if (ng == nextrcline) {
- putchar('\n') FLUSH;
- retry = TRUE;
- }
- else if (toread[ng] > TR_NONE)
- retry = TRUE;
- ng++;
- break;
- case 'N': /* goto next newsgroup */
- ng++;
- special = TRUE; /* and don't skip it if toread==0 */
- break;
- case '1': /* goto 1st newsgroup */
- ng = 0;
- special = TRUE; /* and don't skip it if toread==0 */
- break;
- case '$':
- ng = nextrcline; /* goto last newsgroup */
- retry = TRUE;
- break;
- case 'L':
- list_newsgroups();
- goto reask_newsgroup;
- case '/': case '?': /* scan for newsgroup pattern */
- #ifdef NGSEARCH
- switch (ng_search(buf,TRUE)) {
- case NGS_ABORT:
- goto reinp_newsgroup;
- case NGS_INTR:
- #ifdef VERBOSE
- IF(verbose)
- fputs("\n(Interrupted)\n",stdout) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("\n(Intr)\n",stdout) FLUSH;
- #endif
- ng = current_ng;
- goto reask_newsgroup;
- case NGS_FOUND:
- special = TRUE; /* don't skip it if toread==0 */
- break;
- case NGS_NOTFOUND:
- #ifdef VERBOSE
- IF(verbose)
- fputs("\n\nNot found--use g to add newsgroups\n",
- stdout) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("\n\nNot found\n",stdout) FLUSH;
- #endif
- goto reask_newsgroup;
- }
- #else
- notincl("/");
- #endif
- break;
- case 'm':
- #ifndef RELOCATE
- notincl("m");
- break;
- #endif
- case 'g': /* goto named newsgroup */
- if (!finish_command(FALSE))
- /* if they didn't finish command */
- goto reinp_newsgroup; /* go try something else */
- for (s = buf+1; *s == ' '; s++);
- /* skip leading spaces */
- if (!*s)
- strcpy(s,ngname);
- #ifdef RELOCATE
- if (!get_ng(s,*buf=='m')) /* try to find newsgroup */
- #else
- if (!get_ng(s,FALSE)) /* try to find newsgroup */
- #endif
- ng = current_ng;/* if not found, go nowhere */
- special = TRUE; /* don't skip it if toread==0 */
- break;
- #ifdef DEBUGGING
- case 'D':
- printf("\nTries: %d Hits: %d\n",
- softtries,softtries-softmisses) FLUSH;
- goto reask_newsgroup;
- #endif
- case '!': /* shell escape */
- if (escapade()) /* do command */
- goto reinp_newsgroup;
- /* if rubbed out, re input */
- goto reask_newsgroup;
- case Ctl('k'): /* edit global KILL file */
- edit_kfile();
- goto reask_newsgroup;
- case 'c': /* catch up */
- #ifdef CATCHUP
- 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
- setdef(buf,"y");
- #ifdef VERIFY
- printcmd();
- #endif
- putchar('\n') FLUSH;
- if (*buf == 'h') {
- #ifdef VERBOSE
- printf("Type y or SP to mark all articles as read.\n");
- printf("Type n to leave articles marked as they are.\n");
- #else
- printf("y or SP to mark all read.\n");
- printf("n to forget it.\n");
- #endif
- goto reask_catchup;
- }
- else if (*buf!=' ' && *buf!='y' && *buf!='n' && *buf!='q') {
- printf(hforhelp);
- settle_down();
- goto reask_catchup;
- } else if ( (*buf == ' ' || *buf == 'y') && ng<nextrcline )
- catch_up(ng);
- else
- retry = TRUE;
- ng++;
- #else
- notincl("c");
- #endif
- break;
- case 'u': /* unsubscribe */
- if (ng < nextrcline && toread[ng] >= TR_NONE) {
- /* unsubscribable? */
- printf(unsubto,rcline[ng]) FLUSH;
- rcchar[ng] = NEGCHAR;
- /* unsubscribe to (from?) it */
- toread[ng] = TR_UNSUB;
- /* and make line invisible */
- ng++; /* do an automatic 'n' */
- }
- break;
- case 'h': { /* help */
- int cmd;
-
- if ((cmd = help_ng()) > 0)
- pushchar(cmd);
- goto reask_newsgroup;
- }
- case 'a':
- #ifndef FINDNEWNG
- notincl("a");
- goto reask_newsgroup;
- #else
- /* FALL THROUGH */
- #endif
- case 'o':
- #ifdef ONLY
- {
- #ifdef FINDNEWNG
- bool doscan = (*buf == 'a');
- #endif
-
- if (!finish_command(TRUE)) /* get rest of command */
- goto reinp_newsgroup; /* if rubbed out, try something else */
- end_only();
- if (buf[1]) {
- bool minusd = instr(buf+1,"-d") != Nullch;
-
- sw_list(buf+1);
- if (minusd)
- cwd_check();
- putchar('\n') FLUSH;
- #ifdef FINDNEWNG
- if (doscan && maxngtodo)
- scanactive();
- #endif
- }
- ng = 0; /* simulate ^ */
- retry = FALSE;
- break;
- }
- #else
- notincl("o");
- goto reask_newsgroup;
- #endif
- case '&':
- if (switcheroo()) /* get rest of command */
- goto reinp_newsgroup; /* if rubbed out, try something else */
- goto reask_newsgroup;
- case 'l': { /* list other newsgroups */
- if (!finish_command(TRUE)) /* get rest of command */
- goto reinp_newsgroup; /* if rubbed out, try something else */
- for (s = buf+1; *s == ' '; s++);
- /* skip leading spaces */
- sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s);
- resetty();
- if (doshell(sh,cmd_buf))
- #ifdef VERBOSE
- IF(verbose)
- fputs(" (Error from newsgroups program)\n",
- stdout) FLUSH;
- ELSE
- #endif
- #ifdef TERSE
- fputs("(Error)\n",stdout) FLUSH;
- #endif
- noecho();
- crmode();
- goto reask_newsgroup;
- }
- #ifdef USETHREADS
- case 'U': case '+':
- #endif
- case '.': case '=':
- case 'y': case 'Y': /* do normal thing */
- if (ng >= nextrcline) {
- fputs("\nNot on a newsgroup.",stdout) FLUSH;
- goto reask_newsgroup;
- }
- #ifdef USETHREADS
- else if (*buf == '+' || *buf == 'U' || *buf == '=') {
- buf[1] = '\0';
- s = savestr(buf);
- }
- #else
- if (*buf == '=')
- s = savestr("=");
- #endif
- else if (*buf == '.') { /* start command? */
- if (!finish_command(FALSE)) /* get rest of command */
- goto reinp_newsgroup;
- s = savestr(buf+1);
- /* do_newsgroup will free it */
- }
- else
- s = Nullch;
- if (toread[ng])
- retry = TRUE;
- switch (do_newsgroup(s)) {
- case NG_ERROR:
- case NG_NORM:
- ng++;
- break;
- case NG_ASK:
- goto reprompt_newsgroup;
- case NG_MINUS:
- ng = recent_ng; /* recall previous newsgroup */
- special = TRUE; /* don't skip it if toread==0 */
- break;
- }
- break;
- #ifdef STRICTCR
- case '\n':
- fputs(badcr,stdout) FLUSH;
- goto reask_newsgroup;
- #endif
- case 'v':
- printf("\n%s",rnid);
- printf("\n%s",patchlevel);
- printf("\nSend bugs to davison@borland.com\n") FLUSH;
- goto reask_newsgroup;
- default:
- printf("\n%s",hforhelp) FLUSH;
- settle_down();
- goto reask_newsgroup;
- }
- }
- } while (retry);
- }
-
- /* now write .newsrc back out */
-
- write_rc();
-
- if (oh_for_the_good_old_days)
- get_old_rc();
-
- finalize(0); /* and exit */
- }
-
- /* set current newsgroup */
-
- void
- set_ngname(what)
- char *what;
- {
- int len = strlen(what)+1;
-
- growstr(&ngname,&ngnlen,len);
- strcpy(ngname,what);
- growstr(&ngdir,&ngdlen,len);
- strcpy(ngdir,getngdir(ngname));
- }
-
- static char *myngdir;
- static int ngdirlen = 0;
-
- char *
- getngdir(ngnam)
- char *ngnam;
- {
- register char *s;
-
- growstr(&myngdir,&ngdirlen,strlen(ngnam)+1);
- strcpy(myngdir,ngnam);
- for (s = myngdir; *s; s++)
- if (*s == '.')
- *s = '/';
- return myngdir;
- }
-