home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume23
/
trn
/
part09
/
rn.c
< prev
Wrap
C/C++ Source or Header
|
1991-08-22
|
15KB
|
622 lines
/* 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;
}