/* $Header: rcstuff.c,v 4.3.1.4 85/09/10 11:04:44 lwall Exp $
* Revision 4.3.1.4 85/09/10 11:04:44 lwall
* Improved %m in in_char().
* Revision 4.3.1.3 85/05/29 09:13:25 lwall
* Revision 4.3.1.2 85/05/17 11:40:08 lwall
* Sped up "rn -c" by not mallocing unnecessarily.
* Revision 4.3.1.1 85/05/10 11:37:18 lwall
* Revision 4.3 85/05/01 11:45:56 lwall
* Baseline for release with 4.3bsd.
char *rcname
INIT(Nullch
); /* path name of .newsrc file */
char *rctname
INIT(Nullch
); /* path name of temp .newsrc file */
char *rcbname
INIT(Nullch
); /* path name of backup .newsrc file */
char *softname
INIT(Nullch
); /* path name of .rnsoft file */
FILE *rcfp
INIT(Nullfp
); /* .newsrc file pointer */
register bool foundany
= FALSE
;
for (i
=0; i
<HASHSIZ
; i
++)
rcname
= savestr(filexp(RCNAME
));
rctname
= savestr(filexp(RCTNAME
));
rcbname
= savestr(filexp(RCBNAME
));
softname
= savestr(filexp(SOFTNAME
));
/* make sure the .newsrc file exists */
/* open .rnsoft file containing soft ptrs to active file */
tmpfp
= fopen(softname
,"r");
/* read in the .newsrc file */
(some_buf
= get_a_line(buf
,LBUFLEN
,rcfp
)) != Nullch
;
/* for each line in .newsrc */
newng
= nextrcline
; /* get it into a register */
length
= len_last_line_got
; /* side effect of get_a_line */
if (length
<= 1) { /* only a newline??? */
nextrcline
--; /* compensate for loop increment */
if (newng
>= MAXRCLINE
) { /* check for overflow */
fputs("Too many lines in .newsrc\n",stdout
) FLUSH
;
if (tmpfp
!= Nullfp
&& fgets(tmpbuf
,10,tmpfp
) != Nullch
)
softptr
[newng
] = atoi(tmpbuf
);
some_buf
[--length
] = '\0'; /* wipe out newline */
if (checkflag
) /* no extra mallocs for -c */
rcline
[newng
] = some_buf
;
else if (some_buf
== buf
) {
rcline
[newng
] = savestr(some_buf
);
/* make a semipermanent copy */
some_buf
= saferealloc(some_buf
,(MEM_SIZE
)(length
+1));
rcline
[newng
] = some_buf
;
if (strnEQ(some_buf
,"to.",3)) { /* is this a non-newsgroup? */
nextrcline
--; /* destroy this line */
strnEQ(some_buf
,"options",7)) { /* non-useful line? */
for (s
= rcline
[newng
]; *s
&& *s
!= ':' && *s
!= NEGCHAR
; s
++) ;
rcline
[newng
] = saferealloc(rcline
[newng
],(MEM_SIZE
)length
+2);
s
= rcline
[newng
] + length
;
rcchar
[newng
] = *s
; /* salt away the : or ! */
rcnums
[newng
] = (char)(s
- rcline
[newng
]);
rcnums
[newng
]++; /* remember where it was */
*s
= '\0'; /* null terminate newsgroup name */
if (rcchar
[newng
] == NEGCHAR
) {
toread
[newng
] = TR_UNSUB
;
/* now find out how much there is to read */
if (!inlist(buf
) || (suppress_cn
&& foundany
&& !paranoid
))
toread
[newng
] = TR_NONE
; /* no need to calculate now */
if (!checkflag
&& softmisses
== 1) {
softmisses
++; /* lie a little */
fputs("(Revising soft pointers--be patient.)\n",stdout
) FLUSH
;
if (toread
[newng
] > TR_NONE
) { /* anything unread? */
foundany
= TRUE
; /* remember that fact*/
if (suppress_cn
) { /* if no listing desired */
if (checkflag
) { /* if that is all they wanted */
finalize(1); /* then bomb out */
printf("Unread news in %-20s %5ld article%s\n",
rcline
[newng
],(long)toread
[newng
],
toread
[newng
]==TR_ONE
? nullstr
: "s") FLUSH
;
printf("%s: %ld article%s\n",
rcline
[newng
],(long)toread
[newng
],
toread
[newng
]==TR_ONE
? nullstr
: "s") FLUSH
;
fputs("etc.\n",stdout
) FLUSH
;
fclose(rcfp
); /* close .newsrc */
fclose(tmpfp
); /* close .rnsoft */
if (checkflag
) { /* were we just checking? */
finalize(foundany
); /* tell them what we found */
for (i
=0; i
<HASHSIZ
; i
++) {
sprintf(buf
,"%d %d",i
,hashtbl
[i
]);
print_lines(buf
,NOMARKING
);
/* try to find or add an explicitly specified newsgroup */
/* returns TRUE if found or added, FALSE if not. */
/* assumes that we are chdir'ed to SPOOL */
ntoforget
= "Type n to forget about this newsgroup.\n";
ntoforget
= "n to forget it.\n";
printf("\nBad newsgroup name.\n") FLUSH
;
if (ng
== nextrcline
) { /* not in .newsrc? */
(softptr
[ng
] = findact(buf
,ngname
,strlen(ngname
),0L)) < 0 ) {
printf("\nNewsgroup %s does not exist!\n",ngname
) FLUSH
;
printf("\nNo %s!\n",ngname
) FLUSH
;
sprintf(promptbuf
,"\nNewsgroup %s not in .newsrc--add? [yn] ",ngname
);
sprintf(promptbuf
,"\nAdd %s? [yn] ",ngname
);
printf("Type y or SP to add %s to your .newsrc.\n", ngname
)
fputs("y or SP to add\n",stdout
) FLUSH
;
fputs(ntoforget
,stdout
) FLUSH
;
else if (*buf
== 'n' || *buf
== 'q') {
ng
= add_newsgroup(ngname
);
fputs(hforhelp
,stdout
) FLUSH
;
else if (rcchar
[ng
] == NEGCHAR
) { /* unsubscribed? */
"\nNewsgroup %s is currently unsubscribed to--resubscribe? [yn] ",ngname
)
sprintf(promptbuf
,"\n%s unsubscribed--resubscribe? [yn] ",ngname
)
printf("Type y or SP to resubscribe to %s.\n", ngname
) FLUSH
;
fputs("y or SP to resubscribe.\n",stdout
) FLUSH
;
fputs(ntoforget
,stdout
) FLUSH
;
else if (*buf
== 'n' || *buf
== 'q') {
fputs(hforhelp
,stdout
) FLUSH
;
/* now calculate how many unread articles in newsgroup */
ng
= relocate_newsgroup(ng
,-1);
return toread
[ng
] >= TR_NONE
;
/* add a newsgroup to the .newsrc file (eventually) */
register NG_NUM newng
= nextrcline
++;
/* increment max rcline index */
rcnums
[newng
] = strlen(ngn
) + 1;
rcline
[newng
] = safemalloc((MEM_SIZE
)(rcnums
[newng
] + 1));
strcpy(rcline
[newng
],ngn
); /* and copy over the name */
*(rcline
[newng
] + rcnums
[newng
]) = '\0';
rcchar
[newng
] = ':'; /* call it subscribed */
toread
[newng
] = TR_NONE
; /* just for prettiness */
sethash(newng
); /* so we can find it again */
return relocate_newsgroup(newng
,-1);
relocate_newsgroup(ngx
,newng
)
char *dflt
= (ngx
!=current_ng
? "$^.L" : "$^L");
starthere
= 0; /* Disable this optimization */
writesoft
= TRUE
; /* Update soft pointer file */
if (ngx
< nextrcline
-1) {
for (i
=0; i
<HASHSIZ
; i
++) {
else if (hashtbl
[i
] == ngx
)
hashtbl
[i
] = nextrcline
-1;
tmpsoftptr
= softptr
[ngx
];
for (i
=ngx
+1; i
<nextrcline
; i
++) {
softptr
[i
-1] = softptr
[i
];
rcline
[nextrcline
-1] = tmprcline
;
toread
[nextrcline
-1] = tmptoread
;
rcchar
[nextrcline
-1] = tmprcchar
;
rcnums
[nextrcline
-1] = tmprcnums
;
softptr
[nextrcline
-1] = tmpsoftptr
;
ngmax
[nextrcline
-1] = tmpngmax
;
abs1st
[nextrcline
-1] = tmpabs1st
;
unflush_output(); /* disable any ^O in effect */
printf("\nPut newsgroup where? [%s] ", dflt
);
printf("\nPut where? [%s] ", dflt
);
if (errno
|| *buf
== '\f') {
/* if return from stop signal */
goto reask_reloc
; /* give them a prompt again */
Type ^ to put the newsgroup first (position 0).\n\
Type $ to put the newsgroup last (position %d).\n", nextrcline
-1);
Type . to put it before the current newsgroup (position %d).\n", current_ng
);
Type -newsgroup name to put it before that newsgroup.\n\
Type +newsgroup name to put it after that newsgroup.\n\
Type a number between 0 and %d to put it at that position.\n", nextrcline
-1);
Type L for a listing of newsgroups and their positions.\n") FLUSH
;
^ to put newsgroup first (pos 0).\n\
$ to put last (pos %d).\n", nextrcline
-1);
. to put before current newsgroup (pos %d).\n", current_ng
);
-newsgroup to put before newsgroup.\n\
+newsgroup to put after.\n\
number in 0-%d to put at that pos.\n", nextrcline
-1);
L for list of .newsrc.\n") FLUSH
;
else if (isdigit(*buf
)) {
if (!finish_command(TRUE
)) /* get rest of command */
else if (*buf
== '-' || *buf
== '+') {
if (!finish_command(TRUE
)) /* get rest of command */
if (newng
== nextrcline
) {
fputs("Not found.",stdout
) FLUSH
;
printf("\n%s",hforhelp
) FLUSH
;
if (newng
< nextrcline
-1) {
for (i
=0; i
<HASHSIZ
; i
++) {
if (hashtbl
[i
] == nextrcline
-1)
else if (hashtbl
[i
] >= newng
)
tmprcline
= rcline
[nextrcline
-1];
tmptoread
= toread
[nextrcline
-1];
tmprcchar
= rcchar
[nextrcline
-1];
tmprcnums
= rcnums
[nextrcline
-1];
tmpsoftptr
= softptr
[nextrcline
-1];
tmpngmax
= ngmax
[nextrcline
-1];
tmpabs1st
= abs1st
[nextrcline
-1];
for (i
=nextrcline
-2; i
>=newng
; i
--) {
softptr
[i
+1] = softptr
[i
];
rcline
[newng
] = tmprcline
;
toread
[newng
] = tmptoread
;
rcchar
[newng
] = tmprcchar
;
rcnums
[newng
] = tmprcnums
;
softptr
[newng
] = tmpsoftptr
;
abs1st
[newng
] = tmpabs1st
;
/* List out the newsrc with annotations */
static char *status
[] = {"(READ)","(UNSUB)","(BOGUS)","(JUNK)"};
for (i
=0; i
<nextrcline
&& !int_count
; i
++) {
*(rcline
[i
] + rcnums
[i
] - 1) = rcchar
[i
];
sprintf(tmpbuf
,"%3d %6ld ",i
,(long)toread
[i
]);
sprintf(tmpbuf
,"%3d %7s ",i
,status
[-toread
[i
]]);
safecpy(tmpbuf
+13,rcline
[i
],2034);
*(rcline
[i
] + rcnums
[i
] - 1) = '\0';
if (cmd
= print_lines(tmpbuf
,NOMARKING
)) {
/* find a newsgroup in .newsrc */
register int hashix
= hash(ngnam
);
while ((ngnum
= hashtbl
[hashix
]) >= 0) {
if (strEQ(rcline
[ngnum
], ngnam
) && toread
[ngnum
] >= TR_UNSUB
)
hashix
= (hashix
+ incr
) % HASHSIZ
;
incr
+= 2; /* offsets from original are in n*2 */
return nextrcline
; /* = notfound */
#else /* just do linear search */
for (ngnum
= 0; ngnum
< nextrcline
; ngnum
++) {
if (strEQ(rcline
[ngnum
],ngnam
))
register NG_NUM bogosity
= 0;
fputs("Checking out your .newsrc--hang on a second...\n",stdout
)
fputs("Checking .newsrc--hang on...\n",stdout
) FLUSH
;
for (ngx
= 0; ngx
< nextrcline
; ngx
++) {
if (toread
[ngx
] >= TR_UNSUB
) {
set_toread(ngx
); /* this may reset newsgroup */
/* or declare it bogus */
if (toread
[ngx
] == TR_BOGUS
)
for (ngx
= nextrcline
-1; ngx
>= 0 && toread
[ngx
] == TR_BOGUS
; ngx
--)
bogosity
--; /* discount already moved ones */
if (nextrcline
> 5 && bogosity
> nextrcline
/ 2) {
"It looks like the active file is messed up. Contact your news administrator,\n\
"leave the \"bogus\" groups alone, and they may come back to normal. Maybe.\n\
fputs("Moving bogus newsgroups to the end of your .newsrc.\n",
fputs("Moving boguses to the end.\n",stdout
) FLUSH
;
for (; ngx
>= 0; ngx
--) {
if (toread
[ngx
] == TR_BOGUS
)
relocate_newsgroup(ngx
,nextrcline
-1);
in_char("Delete bogus newsgroups? [ny] ", 'D');
Type y to delete bogus newsgroups.\n\
Type n or SP to leave them at the end in case they return.\n\
fputs("y to delete, n to keep\n",stdout
) FLUSH
;
else if (*buf
== 'n' || *buf
== 'q')
while (toread
[nextrcline
-1] == TR_BOGUS
&& nextrcline
> 0)
--nextrcline
; /* real tough, huh? */
fputs(hforhelp
,stdout
) FLUSH
;
fputs("You should edit bogus newsgroups out of your .newsrc.\n",
fputs("Edit boguses from .newsrc.\n",stdout
) FLUSH
;
/* make an entry in the hash table for the current newsgroup */
register int hashix
= hash(rcline
[thisng
]);
static int hashhits
= 0, hashtries
= 0;
while (hashtbl
[hashix
] >= 0) {
printf(" Hash hits: %d / %d\n",hashhits
, hashtries
) FLUSH
;
hashix
= (hashix
+ incr
) % HASHSIZ
;
incr
+= 2; /* offsets from original are in n*2 */
hashtbl
[hashix
] = thisng
;
short prime
[] = {1,2,-3,-5,7,11,-13,-17,19,23,-29,-31,37,41,-43,-47,53,57,-59,
-61,67,71,-73,-79,83,89,-97,-101,1,1,1,1,1,1,1,1,1,1,1,1};
sum
+= (ch
+ i
) * prime
[i
]; /* gives ~ 10% hits at 25% full */
printf("hash(%s) => %d => %d\n",ngn
, sum
, (sum
<0?-sum
:sum
)%HASHSIZ
)
rcfp
= fopen(rcname
,"r"); /* open it */
if (rcfp
== Nullfp
) { /* not there? */
Trying to set up a .newsrc file--running newsetup...\n\n\
fputs("Setting up .newsrc...\n",stdout
) FLUSH
;
if (doshell(sh
,filexp(NEWSETUP
)) ||
(rcfp
= fopen(rcname
,"r")) == Nullfp
) {
Can't create a .newsrc--you must do it yourself.\n\
fputs("(Fatal)\n",stdout
) FLUSH
;
UNLINK(rcbname
); /* unlink backup file name */
link(rcname
,rcbname
); /* and backup current name */
/* write out the (presumably) revised .newsrc */
rcfp
= fopen(rctname
, "w"); /* open .newsrc */
printf("Can't recreate .newsrc\n") FLUSH
;
for (tmpng
= 0; tmpng
< nextrcline
; tmpng
++) {
delim
= rcline
[tmpng
] + rcnums
[tmpng
] - 1;
if (debug
& DEB_NEWSRC_LINE
)
printf("%s\n",rcline
[tmpng
]) FLUSH
;
fprintf(rcfp
,"%s\n",rcline
[tmpng
]);
*delim
= '\0'; /* might still need this line */
fclose(rcfp
); /* close .newsrc */
tmpfp
= fopen(filexp(softname
), "w"); /* open .rnsoft */
printf(cantcreate
,filexp(softname
)) FLUSH
;
for (tmpng
= 0; tmpng
< nextrcline
; tmpng
++) {
fprintf(tmpfp
,"%ld\n",(long)softptr
[tmpng
]);