home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume30
/
tin
/
part12
/
kill.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-20
|
12KB
|
530 lines
/*
* Project : tin - a threaded Netnews reader
* Module : kill.c
* Author : I.Lea & J.Robinson
* Created : 01-04-91
* Updated : 10-05-92
* Notes : kill & auto select (hot) articles
* Copyright : (c) Copyright 1991-92 by Iain Lea & Jim Robinson
* You may freely copy or redistribute this software,
* so long as there is no profit made from its use, sale
* trade or reproduction. You may not change this copy-
* right notice, and it must be included in any copy made
*/
#include "tin.h"
#ifdef NO_REGEX
char *stars = "";
#else
char *stars = "*";
#endif
#define SET_KILLED(i) (arts[i].unread = ART_READ, arts[i].killed = 1, num_of_killed_arts++)
#define SET_HOT(i) (arts[i].hot = 1, num_of_hot_arts++)
#define IS_READ(i) (arts[i].unread == ART_READ)
#define IS_KILLED(i) (arts[i].killed == 1)
#define KILL_CHAR 'K'
#define HOT_CHAR 'H'
#define K_KILL 0
#define K_HOT 1
int kill_level = 1;
int kill_num = 0;
int max_kill;
struct kill_t *killf;
/*
* read_kill_file - read ~/.tin/kill file contents into kill array
*/
int read_kill_file ()
{
char buf[LEN];
FILE *fp;
int n;
char c;
unsigned int type;
free_kill_array ();
set_real_uid_gid ();
if ((fp = fopen (killfile, "r")) == NULL) {
set_tin_uid_gid ();
return FALSE;
}
kill_num=0;
while (fgets (buf, sizeof buf, fp) != NULL) {
if (buf[0] == '#') {
continue;
}
if (kill_num == max_kill-1) {
expand_kill ();
}
n = sscanf(buf, "%d %c", &type, &c);
if (n == 0) {
goto corrupt_killfile;
}
if (n > 1 && c == HOT_CHAR) { /* hot */
killf[kill_num].kill_how = K_HOT;
} else {
killf[kill_num].kill_how = K_KILL;
}
killf[kill_num].kill_type = type;
if (fgets (buf, sizeof buf, fp) == NULL) {
goto corrupt_killfile;
}
killf[kill_num].kill_group = (long) atol (buf);
switch (killf[kill_num].kill_type) {
case KILL_SUBJ:
if (fgets (buf, sizeof buf, fp) != NULL) {
buf[strlen (buf)-1] = '\0';
killf[kill_num].kill_subj = str_dup (buf);
}
break;
case KILL_FROM:
if (fgets (buf, sizeof buf, fp) != NULL) {
buf[strlen (buf)-1] = '\0';
killf[kill_num].kill_from = str_dup (buf);
}
break;
case KILL_BOTH:
if (fgets (buf, sizeof buf, fp) != NULL) {
buf[strlen (buf)-1] = '\0';
killf[kill_num].kill_subj = str_dup (buf);
}
if (fgets (buf, sizeof buf, fp) != NULL) {
buf[strlen (buf)-1] = '\0';
killf[kill_num].kill_from = str_dup (buf);
}
break;
default:
goto corrupt_killfile;
}
kill_num++;
}
fclose (fp);
set_tin_uid_gid ();
return (kill_num);
corrupt_killfile:
fclose (fp);
killf[kill_num].kill_type = 0;
error_message (txt_corrupt_kill_file, killfile);
set_tin_uid_gid ();
return FALSE;
}
/*
* write_kill_file - write kill strings to ~/.tin/kill
*/
void write_kill_file ()
{
FILE *fp;
int i;
set_real_uid_gid ();
if (kill_num == 0 || (fp = fopen (killfile, "w")) == NULL) {
set_tin_uid_gid ();
return;
}
wait_message (txt_saving);
fprintf (fp, "# 1st line 1=(Subject: only) 2=(From: only) 3=(Subject: & From:)\n");
fprintf (fp, "# %c=(kill) %c=(auto-selection)\n", KILL_CHAR, HOT_CHAR);
fprintf (fp, "# 2nd line 0=(kill on all newsgroups) >0=(kill on specific newsgroup)\n");
for (i=0 ; i < kill_num ; i++) {
if (killf[i].kill_type == 0 || (killf[i].kill_subj == 0
&& killf[i].kill_from == 0))
continue;
if (killf[i].kill_how == K_KILL) {
fprintf (fp, "#\n# %03d KILL\n", i+1);
fprintf (fp, "%d\t%c\n", killf[i].kill_type, KILL_CHAR);
} else {
fprintf (fp, "#\n# %03d HOT\n", i+1);
fprintf (fp, "%d\t%c\n", killf[i].kill_type, HOT_CHAR);
}
fprintf (fp, "%ld\n", killf[i].kill_group);
switch (killf[i].kill_type) {
case KILL_SUBJ:
fprintf (fp, "%s\n", killf[i].kill_subj);
break;
case KILL_FROM:
fprintf (fp, "%s\n", killf[i].kill_from);
break;
case KILL_BOTH:
fprintf (fp, "%s\n", killf[i].kill_subj);
fprintf (fp, "%s\n", killf[i].kill_from);
break;
}
}
fclose (fp);
chmod (killfile, 0600);
set_tin_uid_gid ();
}
static int get_choice (x, help, prompt, opt1, opt2, opt3, opt4)
int x;
char *help, *prompt, *opt1, *opt2, *opt3, *opt4;
{
int ch, n = 0, i = 0;
char *argv[4];
if (opt1)
argv[n++] = opt1;
if (opt2)
argv[n++] = opt2;
if (opt3)
argv[n++] = opt3;
if (opt4)
argv[n++] = opt4;
assert(n > 0);
if (help)
show_menu_help (help);
do {
MoveCursor(x, (int) strlen (prompt));
fputs (argv[i], stdout);
fflush (stdout);
CleartoEOLN ();
if ((ch = ReadCh ()) != ' ')
continue;
if (++i == n)
i = 0;
} while (ch != CR && ch != ESC);
if (ch == ESC)
return (-1);
return (i);
}
/*
* options menu so that the user can dynamically change parameters
*/
int kill_art_menu (group_name, index)
char *group_name;
int index;
{
char buf[LEN];
char text[LEN];
char kill_from[LEN];
char kill_subj[LEN];
char kill_group[LEN];
char ch_default = 's';
int ch;
int counter = 0;
int killed = TRUE;
int kill_from_ok = FALSE;
int kill_subj_ok = FALSE;
int kill_every_group = FALSE;
int i;
int kill_how;
#ifdef SIGTSTP
sigtype_t (*susp)() = (sigtype_t *) 0;
if (do_sigtstp) {
susp = sigdisp (SIGTSTP, SIG_DFL);
sigdisp (SIGTSTP, SIG_IGN);
}
#endif
sprintf (kill_group, "%s only", group_name);
sprintf (kill_subj, txt_kill_subject, COLS-35, COLS-35, arts[index].subject);
if (arts[index].name != (char *) 0) {
sprintf (text, "%s (%s)", arts[index].from, arts[index].name);
} else {
strcpy (text, arts[index].from);
}
sprintf (kill_from, txt_kill_from, COLS-35, COLS-35, text);
text[0] = '\0';
ClearScreen ();
center_line (0, TRUE, txt_kill_menu);
MoveCursor (INDEX_TOP, 0);
printf ("%s\r\n\r\n\r\n", txt_kill_how);
printf ("%s\r\n\r\n", txt_kill_text);
printf ("%s\r\n\r\n\r\n", txt_kill_text_type);
printf ("%s\r\n\r\n", kill_subj);
printf ("%s\r\n\r\n\r\n", kill_from);
printf ("%s%s", txt_kill_group, kill_group);
fflush (stdout);
i = get_choice (INDEX_TOP, txt_help_kill_how, txt_kill_how,
"Kill ", "Auto Select", NULL, NULL);
if (i == -1) {
return FALSE;
}
kill_how = (i == 0 ? K_KILL : K_HOT);
show_menu_help (txt_help_kill_text);
if (! prompt_menu_string (INDEX_TOP+3, (int) strlen (txt_kill_text), text)) {
return FALSE;
}
if (text[0]) {
i = get_choice(INDEX_TOP+5, txt_help_kill_text_type,
txt_kill_text_type, "Subject: line only ",
"From: line only ", "Subject: & From: lines",
NULL);
if (i == -1) {
return FALSE;
}
counter = ((i == 0 ? KILL_SUBJ : (i == 1 ? KILL_FROM : KILL_BOTH)));
}
if (! text[0]) {
i = get_choice (INDEX_TOP+8, txt_help_kill_subject,
kill_subj, "Yes", "No ", NULL, NULL);
if (i == -1) {
return FALSE;
} else {
kill_subj_ok = (i ? FALSE : TRUE);
}
i = get_choice (INDEX_TOP+10, txt_help_kill_from,
kill_from, "No ", "Yes", NULL, NULL);
if (i == -1) {
return FALSE;
} else {
kill_from_ok = (i ? TRUE : FALSE);
}
}
if (text[0] || kill_subj_ok || kill_from_ok) {
i = get_choice (INDEX_TOP+13, txt_help_kill_group,
txt_kill_group, kill_group, "All groups",
NULL, NULL);
if (i == -1) {
return FALSE;
}
kill_every_group = (i == 0 ? FALSE : TRUE);
}
while (1) {
do {
sprintf (msg, "%s%c", txt_quit_edit_save_killfile, ch_default);
wait_message (msg);
MoveCursor (LINES, (int) strlen (txt_quit_edit_save_killfile));
if ((ch = ReadCh ()) == CR)
ch = ch_default;
} while (ch != ESC && ch != 'q' && ch != 'e' && ch != 's');
switch (ch) {
case 'e':
start_line_offset = 2;
invoke_editor (killfile);
unkill_all_articles ();
killed_articles = read_kill_file ();
killed = TRUE;
goto kill_done;
case 'a':
case ESC:
killed = FALSE;
goto kill_done;
case 's':
if (kill_num > max_kill-1) {
expand_kill ();
}
killf[kill_num].kill_how = kill_how;
if (text[0]) {
sprintf (buf, "%s%s%s", stars, text, stars);
switch (counter) {
case KILL_SUBJ:
killf[kill_num].kill_subj = str_dup (buf);
break;
case KILL_FROM:
killf[kill_num].kill_from = str_dup (buf);
break;
case KILL_BOTH:
killf[kill_num].kill_subj = str_dup (buf);
killf[kill_num].kill_from = killf[kill_num].kill_subj;
break;
}
killf[kill_num].kill_type = counter;
if (kill_every_group) {
killf[kill_num].kill_group = 0L;
} else {
killf[kill_num].kill_group = hash_s (group_name);
}
kill_num++;
} else {
if (kill_subj_ok) {
killf[kill_num].kill_type = KILL_SUBJ;
sprintf (buf, "%s%s%s",
stars, arts[index].subject, stars);
killf[kill_num].kill_subj = str_dup (buf);
}
if (kill_from_ok) {
killf[kill_num].kill_type |= KILL_FROM;
if (arts[index].name != (char *) 0) {
sprintf (buf, "%s%s (%s)%s",
stars, arts[index].from, arts[index].name, stars);
} else {
sprintf (buf, "%s%s%s",
stars, arts[index].from, stars);
}
killf[kill_num].kill_from = str_dup (buf);
}
if (killf[kill_num].kill_type) {
if (kill_every_group) {
killf[kill_num].kill_group= 0L;
} else {
killf[kill_num].kill_group= hash_s (group_name);
}
kill_num++;
}
}
write_kill_file ();
kill_done:
#ifdef SIGTSTP
if (do_sigtstp) {
sigdisp (SIGTSTP, susp);
}
#endif
return (killed);
}
}
/* NOTREACHED */
}
/*
* We assume that any articles which are tagged as killed are also
* tagged as being read BECAUSE they were killed. So, we retag
* them as being unread.
*/
int unkill_all_articles ()
{
int unkilled = FALSE;
register int i;
for (i=0 ; i < top ; i++) {
if (arts[i].killed) {
arts[i].killed = FALSE;
arts[i].unread = ART_UNREAD;
unkilled = TRUE;
}
}
num_of_killed_arts = 0;
return (unkilled);
}
int kill_any_articles (group)
char *group;
{
char buf[LEN];
int killed = FALSE;
int run_ok = FALSE;
int is_hot;
long newsgroup_hash;
register int i, j;
if (! kill_num) {
return (killed);
}
num_of_killed_arts = 0;
num_of_hot_arts = 0;
newsgroup_hash = hash_s (group);
for (i=0 ; i < kill_num ; i++) {
if (killf[i].kill_group == 0L ||
killf[i].kill_group == newsgroup_hash) {
run_ok = TRUE;
}
}
if (! run_ok) {
return (killed);
}
if (debug && ! update) {
wait_message (txt_killing_arts);
}
for (i=0 ; i < top ; i++) {
if (IS_READ(i) && kill_level == 0) {
continue;
}
for (j=0 ; j < kill_num ; j++) {
if (killf[j].kill_group != 0L &&
killf[j].kill_group != newsgroup_hash)
continue;
is_hot = (killf[j].kill_how == K_HOT ? TRUE : FALSE);
switch (killf[j].kill_type) {
case KILL_SUBJ:
if (STR_MATCH (arts[i].subject, killf[j].kill_subj)) {
if (!is_hot)
SET_KILLED(i);
else
SET_HOT(i);
}
break;
case KILL_FROM:
if (arts[i].name != (char *) 0) {
sprintf (buf, "%s (%s)", arts[i].from, arts[i].name);
} else {
strcpy (buf, arts[i].from);
}
if (STR_MATCH (buf, killf[j].kill_from)) {
if (!is_hot)
SET_KILLED(i);
else
SET_HOT(i);
}
break;
case KILL_BOTH:
if (STR_MATCH (arts[i].subject, killf[j].kill_subj)) {
if (!is_hot)
SET_KILLED(i);
else
SET_HOT(i);
break; /* XXX ? - JBR */
}
if (arts[i].name != (char *) 0) {
sprintf (buf, "%s (%s)", arts[i].from, arts[i].name);
} else {
strcpy (buf, arts[i].from);
}
if (STR_MATCH (buf, killf[j].kill_from)) {
if (!is_hot)
SET_KILLED(i);
else
SET_HOT(i);
}
break;
}
if (IS_KILLED(i) || ! killed)
killed = TRUE;
}
}
return (killed);
}