home *** CD-ROM | disk | FTP | other *** search
- /* trn -- threaded readnews program based on rn 4.4
- *
- * Author/Maintainer of trn: davison@borland.com (Wayne Davison)
- * Organization: Borland International
- * Author/Maintainer of rn: sob@bcm.tmc.edu (Stan Barber)
- * Organization: Baylor College of Medicine, Houston,Tx
- * Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
- * Organization: System Development Corporation, Santa Monica
- *
- * History:
- * 01/14/83 - rn begun
- * 04/08/83 - rn 1.0
- * 09/01/83 - rn 2.0
- * 05/01/85 - rn 4.3
- * 11/01/89 - rn/rrn integration
- * 11/25/89 - trn begun
- * 07/21/90 - trn 1.0
- * 07/04/91 - rn 4.4
- * 11/25/91 - trn 2.0
- */
- /* This software is Copyright 1991 by Stan Barber.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or otherwise
- * use this software as long as: there is no monetary profit gained
- * specifically from the use or reproduction of this software, it is not
- * sold, rented, traded or otherwise marketed, and this copyright notice is
- * included prominently in any copy made.
- *
- * The author make no claims as to the fitness or correctness of this software
- * for any use whatsoever, and it is provided as is. Any use of this software
- * is at the user's own risk.
- */
-
- static char rnid[] = "@(#)$Id: rn.c,v 4.4.3.1 1991/11/22 04:12:14 davison Trn $";
- static char patchlevelos2[] = "TRN 1.2 for OS/2 based on Trn 2.5";
- static char patchlevel[] = "Trn-2.5 based on rn-4.4PL4";
-
- /* $Log: rn.c,v $
- * Revision 4.4.2.1 1991/12/01 18:05:42 sob
- * Patchlevel 2 changes
- *
- * Revision 4.4.1.1 1991/09/25 19:38:08 sob
- * Updated patchlevel message
- *
- * Revision 4.4 1991/09/09 20:27:37 sob
- * release 4.4
- *
- *
- *
- *
- */
-
- #include "INTERN.h"
- #include "common.h"
- #include "rn.h"
- #ifdef SERVER
- #include "server.h"
- #endif
- #include "EXTERN.h"
- #include "rcstuff.h"
- #include "term.h"
- #include "final.h"
- #include "search.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;
- int direction = 1;
-
- /*** OS2: Now we load the settings out of the uupc-rc-files.
- This settings contain the information, which was
- previously hardcoded in the config.h-file by
- the Configure-shell-script. ***/
-
- if (!load_uupc_rc())
- { fprintf(stderr,"An error occurred while reading the uupc-rc-files!\n\
- The following settings must be defined in the UUPCSYSRC-file:\n\
- MailServ, NodeName, NewsDir, Domain, TempDir, MailDir, rmail\n");
- fprintf(stderr,"These settings must be defined in the UUPCUSRRC-file:\n\
- Mailbox, Signature, Name, Home, Organization, Editor\n");
- fprintf(stderr,"And these settings must be defined in the UUPCTRNRC-file:\n\
- Newsadmin, TrnLib, LocalDist, OrganizationDist, CityDist,\n\
- StateDist, Countrydist, ContinentDist\n");
- fprintf(stderr,"\nDon't forget, these settings are required, not optional!\n");
- fflush(stderr);
- exit(1);
- }
-
- setvbuf(stdout, NULL, _IOFBF, BUFSIZ);
-
-
- #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 */
-
- {
- 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
- }
- else {
- bool shoe_fits; /* newsgroup matches restriction? */
-
- if (toread[ng] >= TR_NONE) { /* recalc toread? */
- set_ngname(rcline[ng]);
- shoe_fits = inlist(ngname);
- if (shoe_fits)
- 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 += direction; /* then skip it */
- if (ng < 0) {
- ng = 1;
- direction = 1;
- }
- continue;
- }
- }
- 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 */
- if (ng >= nextrcline) {
- #ifdef SERVER
- if (time(Null(time_t*)) - lastactfetch > MINFETCHTIME) {
- fclose(actfp);
- ngdata_init(); /* re-grab the active file */
- }
- #endif
- dfltcmd = (retry ? "npq" : "qnp");
- #ifdef VERBOSE
- IF(verbose)
- printf("\n******** End of newsgroups--what next? [%s] ",
- dfltcmd);
- ELSE
- #endif
- #ifdef TERSE
- printf("\n**** End--next? [%s] ", dfltcmd);
- #endif
- } else {
- #ifdef USETHREADS
- ThreadedGroup = (use_threads
- && (thread_always || rcchar[ng] == '0'));
- dfltcmd = (use_threads && select_on
- && (ART_NUM)toread[ng] >= select_on ? "+ynq" : "ynq");
- #else
- dfltcmd = "ynq";
- #endif
- #ifdef VERBOSE
- IF(verbose)
- printf("\n******** %3ld unread article%s in %s--read now? [%s] ",
- (long)toread[ng], (toread[ng]==TR_ONE ? nullstr : "s"),
- ngname, dfltcmd);
- ELSE
- #endif
- #ifdef TERSE
- printf("\n**** %3ld in %s--read? [%s] ",
- (long)toread[ng],
- ngname,dfltcmd);
- #endif
- }
- 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
- do_command:
- direction = 1; /* default to forward motion */
- addnewbydefault = 0;
- switch (*buf) {
- case 'P': /* goto previous newsgroup */
- special = TRUE; /* don't skip it if toread==0 */
- /* FALL THROUGH */
- case 'p': /* find previous unread newsgroup */
- if (ng > 0)
- ng--;
- direction = -1; /* go backward in the newsrc */
- break;
- case '-':
- ng = recent_ng; /* recall previous newsgroup */
- if (ng < nextrcline)
- if (!get_ng(rcline[ng],FALSE))
- ng = current_ng;
- 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 */
- special = TRUE; /* and don't skip it if toread==0 */
- ng++;
- 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_ERROR:
- goto reask_newsgroup;
- 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 a or 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 */
- #ifdef RELOCATE
- if (!*s && *buf == 'm' && ngname && ng < nextrcline)
- strcpy(s,ngname);
- #endif
- if (isalnum(*s)) {
- char *_s;
- for (_s=s; isdigit(*_s); _s++)
- ;
- if (*_s && !isspace(*_s))
- /* found non-digit before hitting end */
- set_ngname(s);
- else {
- int rcnum;
- rcnum = atoi(s);
- if (rcnum < nextrcline)
- set_ngname(rcline[rcnum]);
- else {
- printf("\nOnly %d groups. Try again.\n",
- nextrcline) ; FLUSH;
- goto reask_newsgroup;
- }
- }
- }
- else {
- printf("\nPlease specify a newsgroup.\n"); FLUSH;
- goto reask_newsgroup;
- }
- #ifdef RELOCATE
- if (!get_ng(ngname,*buf=='m'))
- /* try to find newsgroup */
- #else
- if (!get_ng(ngname,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
- if (ng < nextrcline)
- ask_catchup();
- ng++;
- #else
- notincl("c");
- #endif
- break;
- #ifdef USETHREADS
- case 't':
- if (!use_threads)
- printf("\n\nNot running in thread mode.\n");
- else if (ng < nextrcline && toread[ng] >= TR_NONE) {
- bool force_threaded = (rcchar[ng] == ':');
- rcchar[ng] = (force_threaded ? '0' : ':');
- printf("\n\n%s will %s.\n", rcline[ng],
- force_threaded ? "always be read threaded"
- : "be read unthreaded if no thread file exists"
- ) ; FLUSH;
- set_toread(ng);
- }
- special = TRUE; /* don't skip it if toread==0 */
- break;
- #endif
- 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':
- if (ng >= nextrcline)
- break;
- reask_abandon:
- #ifdef VERBOSE
- IF(verbose)
- in_char("\nAbandon changes to current newsgroup? [yn] ", 'B');
- ELSE
- #endif
- #ifdef TERSE
- in_char("\nAbandon? [ynh] ", 'B');
- #endif
- setdef(buf,"y");
- #ifdef VERIFY
- printcmd();
- #endif
- putchar('\n') ; FLUSH;
- if (*buf == 'h') {
- #ifdef VERBOSE
- printf("Type y or SP to abandon the changes to this group since you started trn.\n");
- printf("Type n to leave the group as it is.\n");
- #else
- printf("y or SP to abandon changes to this group.\n");
- printf("n to forget it.\n");
- #endif
- goto reask_abandon;
- }
- else if (*buf != 'y' && *buf != 'n' && *buf != 'q') {
- printf(hforhelp);
- settle_down();
- goto reask_abandon;
- } else if (*buf == 'y')
- abandon_ng(ng);
- special = TRUE; /* don't skip it if toread==0 */
- break;
- case 'a':
- /*** OS2: please fix this later ***/
- /* printf("\nNot implemented, sorry!\n"); ** */
- /* goto reask_newsgroup; ** */
- /** end **/
- #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", TRUE) != 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 */
- /*** OS2: we look for unsubscribed newsgroups with
- our own function and not via the shellscript ***/
- /* sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s); */
- /* resetty(); */
- /* if (doshell(sh,cmd_buf)) */
- if (unsub_group(s))
- #ifdef VERBOSE
- IF(verbose) {
- fputs(" (Error from newsgroups function)\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': case '\t': /* 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 reask_newsgroup;
- case NG_SELPRIOR:
- *buf = 'p';
- goto do_command;
- case NG_SELNEXT:
- *buf = 'n';
- goto do_command;
- 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",patchlevelos2);
- printf("\n%s",patchlevel);
- /*** OS2: Send bugs to me not to Wayne for the OS/2 version ***/
- printf("\nSend bugs to haen@veces.stgt.sub.org\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();
-
-
- /*** OS2: reset and clear screen ***/
- termlib_reset();
- clear();
-
- 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;
- }
-