4.4BSD/usr/src/contrib/news/trn3/kfile.c

Compare this file to the similar file:
Show the results in this format:

/* $Id: kfile.c,v 3.0 1991/09/09 20:18:23 davison Trn $
 */
/* 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. 
 */

#include "EXTERN.h"
#include "common.h"
#include "term.h"
#include "util.h"
#include "cache.h"
#include "artsrch.h"
#include "ng.h"
#include "ngdata.h"
#include "intrp.h"
#include "ngstuff.h"
#include "rcstuff.h"
#include "trn.h"
#include "hash.h"
#include "rthread.h"
#include "rt-process.h"
#include "rt-select.h"
#include "INTERN.h"
#include "kfile.h"

static bool exitcmds = FALSE;

void
kfile_init()
{
    ;
}

#ifndef KILLFILES
int
edit_kfile()
{
    notincl("^K");
    return -1;
}

#else /* KILLFILES */

char killglobal[] = KILLGLOBAL;
char killlocal[] = KILLLOCAL;

void
mention(str)
char *str;
{
#ifdef VERBOSE
    IF(verbose) {
#ifdef NOFIREWORKS
	no_sofire();
#endif
	standout();
	fputs(str,stdout);
	un_standout();
	putchar('\n');
    }
    ELSE
#endif
#ifdef TERSE
	putchar('.');
#endif
    fflush(stdout);
}

bool kill_mentioned;

int
do_kfile(kfp,entering)
FILE *kfp;
int entering;
{
    bool first_time = (entering && !killfirst);
    ART_UNREAD selections = selected_count;
    ART_UNREAD unread = toread[ng];
    int thread_kill_cnt = 0;
    int thread_select_cnt = 0;

    art = lastart+1;
    killfirst = firstart;
    fseek(kfp,0L,0);			/* rewind file */
    while (fgets(buf,LBUFLEN,kfp) != Nullch) {
	buf[strlen(buf)-1] = '\0';
	if (strnEQ(buf,"THRU",4)) {
	    killfirst = atol(buf+4)+1;
	    continue;
	}
	if (*buf == 'X') {		/* exit command? */
	    if (entering) {
		exitcmds = TRUE;
		continue;
	    }
	    strcpy(buf,buf+1);
	}
	else if (!entering)
	    continue;

	if (*buf == '&') {
	    mention(buf);
	    switcheroo();
	}
	else if (*buf == '/' && firstart <= lastart) {
	    mention(buf);
	    kill_mentioned = TRUE;
	    has_normal_kills = TRUE;
	    switch (art_search(buf, (sizeof buf), FALSE)) {
	    case SRCH_ABORT:
		continue;
	    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
		return -1;
	    case SRCH_DONE:
		break;
	    case SRCH_SUBJDONE:
		fputs("\tsubject not found (?)\n",stdout) FLUSH;
		break;
	    case SRCH_NOTFOUND:
		fputs("\tnot found\n",stdout) FLUSH;
		break;
	    case SRCH_FOUND:
		fputs("\tfound\n",stdout) FLUSH;
	    }
	}
	else if (first_time && *buf == '<') {
	    register ARTICLE *ap;
	    char *cp = index(buf,' ');
	    if (!cp)
		cp = "T,";
	    else
		*cp++ = '\0';
	    art = 0;
	    if ((ap = get_article(buf)) != Nullart) {
		if ((ap->flags & AF_FAKE) == AF_FAKE) {
		    if (*cp == 'T')
			cp++;
		    switch (*cp) {
		    case '+':
			ap->flags |= AF_AUTOSELECTALL;
			thread_select_cnt++;
			break;
		    case '.':
			ap->flags |= AF_AUTOSELECT;
			thread_select_cnt++;
			break;
		    case 'j':
			ap->flags |= AF_AUTOKILLALL;
			thread_kill_cnt++;
			break;
		    case ',':
			ap->flags |= AF_AUTOKILL;
			thread_kill_cnt++;
			break;
		    }
		} else {
		    art = article_num(ap);
		    artp = ap;
		    perform(cp,FALSE);
		    if (ap->flags & (AF_AUTOSELECT|AF_AUTOSELECTALL))
			thread_select_cnt++;
		    else if (ap->flags & (AF_AUTOKILL|AF_AUTOKILLALL))
			thread_kill_cnt++;
		}
	    }
	    art = lastart+1;
	}
    }
    if (thread_kill_cnt) {
	sprintf(buf,"%ld auto-kill command%s.", (long)thread_kill_cnt,
		thread_kill_cnt == 1? "" : "s");
	mention(buf);
	kill_mentioned = TRUE;
    }
    if (thread_select_cnt) {
	sprintf(buf,"%ld auto-select command%s.", (long)thread_select_cnt,
		thread_select_cnt == 1? "" : "s");
	mention(buf);
	kill_mentioned = TRUE;
    }
    unread -= toread[ng];
    selections -= selected_count;
#ifdef VERBOSE
    IF(verbose && (unread > 0 || selections < 0)) {
	putchar('\n');
	if (unread > 0) {
	    printf("Killed %ld article%s", (long)unread,
		unread == 1? nullstr : "s");
	    if (selections < 0)
		fputs("; ",stdout);
	}
	if (selections < 0)
	    printf("Selected %ld article%s", (long)-selections,
		selections == -1? nullstr : "s");
	fputs(".\n",stdout) FLUSH;
	kill_mentioned = TRUE;
    }
#endif
    return 0;
}

void
kill_unwanted(starting,message,entering)
ART_NUM starting;
char *message;
int entering;
{
    bool intr = FALSE;			/* did we get an interrupt? */
    ART_NUM oldfirst;
    char oldmode = mode;
    bool anytokill = (toread[ng] > 0);

    mode = 'k';
    if ((entering || exitcmds) && (localkfp || globkfp)) {
	exitcmds = FALSE;
	oldfirst = firstart;
	firstart = starting;
	clear();
#ifdef VERBOSE
# ifdef TERSE
	if (message && (verbose || entering))
# else
	if (message)
# endif
#else
	if (message && entering)
#endif
	    fputs(message,stdout) FLUSH;

	kill_mentioned = FALSE;
	if (localkfp)
	    intr = do_kfile(localkfp,entering);
	if (globkfp && !intr)
	    intr = do_kfile(globkfp,entering);
	putchar('\n') FLUSH;
	if (entering && kill_mentioned && novice_delays)
#ifdef VERBOSE
	    IF(verbose)
		get_anything();
	    ELSE
#endif
#ifdef TERSE
		pad(just_a_sec);
#endif
	if (anytokill)			/* if there was anything to kill */
	    forcelast = FALSE;		/* allow for having killed it all */
	firstart = oldfirst;
    }
    if (!entering && (localkfp || save_ids) && !intr)
	setthru(lastart);
    mode = oldmode;
}

void
setthru(thru)
ART_NUM thru;
{
    register ARTICLE *ap;
    register ART_NUM an;
    FILE *newkfp;
    bool no_kills = 0;

    if (localkfp) {
	fseek(localkfp,0L,0);		/* rewind current file */
	if (save_ids)
	    ;
	else if (fgets(buf,LBUFLEN,localkfp) != Nullch
	 && (strnNE(buf,"THRU",4) || fgets(buf,LBUFLEN,localkfp) != Nullch))
	    fseek(localkfp,0L,0);
	else
	    no_kills = 1;
    }
    strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
    if (!localkfp)
	makedir(buf,MD_FILE);
    UNLINK(buf);			/* to prevent file reuse */
    if (no_kills)
	open_kfile(KF_LOCAL);		/* close file and reset open flag */
    else if (newkfp = fopen(buf,"w")) {
	fprintf(newkfp,"THRU %ld\n",(long)thru);
	while (localkfp && fgets(buf,LBUFLEN,localkfp) != Nullch) {
	    if (strnEQ(buf,"THRU",4))
		continue;
	    /* Leave out any outdated thread commands */
	    if (*buf != 'T' && *buf != '<')
		fputs(buf,newkfp);
	}
	/* Append all the still-valid thread commands */
	for (an = absfirst, ap = article_ptr(an); an <= lastart; an++, ap++) {
	    if (ap->flags & (AF_AUTOKILLALL|AF_AUTOSELECTALL))
		fprintf(newkfp,"%s T%c\n",ap->msgid,
			(ap->flags & AF_AUTOKILLALL)? 'j' : '+');
	    else if (ap->flags & (AF_AUTOKILL|AF_AUTOSELECT))
		fprintf(newkfp,"%s T%c\n",ap->msgid,
			(ap->flags & AF_AUTOKILL)? ',' : '.');
	}
	fclose(newkfp);
	open_kfile(KF_LOCAL);		/* and reopen local file */
    }
    else
	printf(cantcreate,buf) FLUSH;
}

/* edit KILL file for newsgroup */

int
edit_kfile()
{
    int r = -1;

    if (in_ng)
	strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
    else
	strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
    if ((r = makedir(buf,MD_FILE)) >= 0) {
	sprintf(cmd_buf,"%s %s",
	    filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
	printf("\nEditing %s KILL file:\n%s\n",
	    (in_ng?"local":"global"),cmd_buf) FLUSH;
	resetty();			/* make sure tty is friendly */
	r = doshell(sh,cmd_buf);/* invoke the shell */
	noecho();			/* and make terminal */
	crmode();			/*   unfriendly again */
	open_kfile(in_ng);
    }
    else
	printf("Can't make %s\n",buf) FLUSH;
    return r;
}

void
open_kfile(local)
int local;
{
    char *kname = filexp(local ?
	getval("KILLLOCAL",killlocal) :
	getval("KILLGLOBAL",killglobal)
	);
    
    /* delete the file if it is empty */
    if (stat(kname,&filestat) >= 0 && !filestat.st_size)
	UNLINK(kname);
    if (local) {
	if (localkfp)
	    fclose(localkfp);
	localkfp = fopen(kname,"r");
    }
    else {
	if (globkfp)
	    fclose(globkfp);
	globkfp = fopen(kname,"r");
    }
}

void
kf_append(cmd)
char *cmd;
{
    strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
    if (makedir(cmd_buf,MD_FILE) >= 0) {
#ifdef VERBOSE
	IF(verbose)
	    printf("\nDepositing command in %s...",cmd_buf);
	ELSE
#endif
#ifdef TERSE
	    printf("\n--> %s...",cmd_buf);
#endif
	fflush(stdout);
	if (novice_delays)
	    sleep(2);
	if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
	    fseek(tmpfp,0L,2);		/* get to EOF for sure */
	    fprintf(tmpfp,"%s\n",cmd);
	    fclose(tmpfp);
	    fputs("done\n",stdout) FLUSH;
	}
	else
	    printf(cantopen,cmd_buf) FLUSH;
    }
    has_normal_kills = TRUE;
}
#endif /* KILLFILES */