home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume30
/
tin
/
part10
/
misc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-20
|
15KB
|
864 lines
/*
* Project : tin - a threaded Netnews reader
* Module : misc.c
* Author : I.Lea & R.Skrenta
* Created : 01-04-91
* Updated : 10-05-92
* Notes :
* Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
* 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"
static char *mailbox_name = (char *) 0;
static int mailbox_size;
void asfail (file, line, cond)
char *file;
int line;
char *cond;
{
fprintf (stderr, "%s: assertion failure: %s (%d): %s\n",
progname, file, line, cond);
fflush (stderr);
/*
* create a core dump
*/
#ifdef SIGABRT
sigdisp(SIGABRT, SIG_DFL);
kill (process_id, SIGABRT);
#else
# ifdef SIGILL
sigdisp(SIGILL, SIG_DFL);
kill (process_id, SIGILL);
# else
# ifdef SIGIOT
sigdisp(SIGIOT, SIG_DFL);
kill (process_id, SIGIOT);
# endif
# endif
#endif
exit(1);
}
void copy_fp (fp_ip, fp_op, prefix)
FILE *fp_ip;
FILE *fp_op;
char *prefix;
{
extern int errno;
char buf[8192];
while (fgets (buf, sizeof (buf), fp_ip) != NULL) {
if (fprintf (fp_op, "%s%s", prefix, buf) == EOF) {
if (errno == EPIPE) {
return;
}
sprintf (msg, "Error: fprintf() failed in copy_fp(). errno=%d", errno);
perror_message (msg, "");
}
}
}
char *get_val (env, def)
char *env; /* Environment variable we're looking for */
char *def; /* Default value if no environ value found */
{
char *ptr;
if ((ptr = (char *) getenv(env)) != NULL)
return (ptr);
else
return (def);
}
int invoke_editor (nam)
char *nam;
{
char buf[LEN];
char *my_editor;
static char editor[LEN];
static int first = TRUE;
if (first) {
my_editor = (char *) getenv ("VISUAL");
strcpy (editor, my_editor != NULL ? my_editor : get_val ("EDITOR", DEFAULT_EDITOR));
first = FALSE;
}
if (start_editor_offset) {
sprintf (buf, "%s +%d %s", editor, start_line_offset, nam);
} else {
sprintf (buf, "%s %s", editor, nam);
}
wait_message (buf);
return invoke_cmd (buf);
}
void shell_escape ()
{
char shell[LEN];
char *p;
#ifdef SIGTSTP
sigtype_t (*susp)() = (sigtype_t *) 0;
#endif
sprintf (msg, txt_shell_escape, default_shell_command);
if (! prompt_string (msg, shell))
my_strncpy (shell, get_val ("SHELL", DEFAULT_SHELL), sizeof (shell));
for (p = shell; *p && (*p == ' ' || *p == '\t'); p++)
continue;
if (*p) {
my_strncpy (default_shell_command, p, sizeof (default_shell_command));
} else {
if (default_shell_command[0]) {
my_strncpy (shell, default_shell_command, sizeof (shell));
} else {
my_strncpy (shell, get_val ("SHELL", DEFAULT_SHELL), sizeof (shell));
}
p = shell;
}
ClearScreen ();
sprintf (msg, "Shell Command (%s)", p);
center_line (0, TRUE, msg);
MoveCursor (INDEX_TOP, 0);
EndWin ();
Raw (FALSE);
#ifdef SIGTSTP
if (do_sigtstp)
susp = signal (SIGTSTP, SIG_DFL);
#endif
system (p);
#ifdef SIGTSTP
if (do_sigtstp)
signal (SIGTSTP, susp);
#endif
Raw (TRUE);
InitWin ();
mail_setup ();
continue_prompt ();
if (draw_arrow_mark) {
ClearScreen ();
}
}
void tin_done (ret)
int ret;
{
extern char index_file[PATH_LEN];
char group_path[PATH_LEN], *p;
int ask = TRUE;
register int i, j;
/*
* check if any groups were read & ask if they should marked read
*/
if (catchup_read_groups) {
for (i = 0 ; i < group_top ; i++) {
if (active[my_group[i]].attribute.read) {
if (ask) {
if (prompt_yn (LINES, "Catchup all groups entered during this session? (y/n): ", 'n')) {
ask = FALSE;
thread_arts = FALSE; /* speeds up index loading */
} else {
break;
}
}
sprintf (msg, "Catchup %s...", active[my_group[i]].name);
wait_message (msg);
my_strncpy (group_path, active[my_group[i]].name, sizeof (group_path));
for (p = group_path ; *p ; p++) {
if (*p == '.') {
*p = '/';
}
}
index_group (active[my_group[i]].name, group_path);
for (j = 0; j < top; j++) {
arts[j].unread = ART_READ;
}
update_newsrc (active[my_group[i]].name, my_group[i], FALSE);
}
}
}
nntp_close (); /* disconnect from NNTP server */
free_all_arrays (); /* deallocate all arrays */
ClearScreen ();
EndWin ();
Raw (FALSE);
if (read_news_via_nntp && xindex_supported) {
unlink (index_file);
}
exit (ret);
}
#ifdef USE_MKDIR
mkdir (path, mode)
char *path;
int mode;
{
char buf[LEN];
struct stat sb;
sprintf(buf, "mkdir %s", path);
if (stat (path, &sb) == -1) {
system (buf);
chmod (path, mode);
}
}
#endif
/*
* hash group name for fast lookup later
*/
long hash_groupname (group)
char *group;
{
unsigned long hash_value;
unsigned char *ptr = (unsigned char *) group;
hash_value = *ptr++;
while (*ptr)
hash_value = ((hash_value << 1) ^ *ptr++) % TABLE_SIZE;
return (hash_value);
}
void rename_file (old_filename, new_filename)
char *old_filename;
char *new_filename;
{
char buf[LEN];
unlink (new_filename);
if (link (old_filename, new_filename) == -1) {
sprintf (buf, txt_rename_error, old_filename, new_filename);
perror_message (buf, "ONE");
return;
}
if (unlink (old_filename) == -1) {
sprintf (buf, txt_rename_error, old_filename, new_filename);
perror_message (buf, "TWO");
return;
}
}
char *str_dup (str)
char *str;
{
char *dup = (char *) 0;
if (str) {
dup = my_malloc (strlen (str)+1);
strcpy (dup, str);
}
return dup;
}
int invoke_cmd (nam)
char *nam;
{
int ret;
int time_remaining;
#ifdef SIGTSTP
sigtype_t (*susp)() = (sigtype_t *) 0;
#endif
#ifndef NO_RESYNC_ACTIVE_FILE
time_remaining = alarm (0); /* save time remaining on alarm clock */
#endif
EndWin ();
Raw (FALSE);
#ifdef SIGTSTP
if (do_sigtstp)
susp = signal(SIGTSTP, SIG_DFL);
#endif
ret = system (nam);
#ifdef SIGTSTP
if (do_sigtstp)
signal (SIGTSTP, susp);
#endif
Raw (TRUE);
InitWin ();
#ifndef NO_RESYNC_ACTIVE_FILE
alarm (time_remaining); /* restart resync alarm clock */
#endif
return ret == 0;
}
void draw_percent_mark (cur_num, max_num)
int cur_num;
int max_num;
{
char buf[32];
int percent = 0;
if (NOTESLINES <= 0) {
return;
}
if (cur_num <= 0 && max_num <= 0) {
return;
}
percent = cur_num * 100 / max_num;
sprintf (buf, "%s(%d%%) [%d/%d]", txt_more, percent, cur_num, max_num);
MoveCursor (LINES, (COLS - (int) strlen (buf))-(1+BLANK_PAGE_COLS));
StartInverse ();
fputs (buf, stdout);
fflush (stdout);
EndInverse ();
}
void set_real_uid_gid ()
{
if (local_index)
return;
umask (real_umask);
#if defined(BSD) && ! defined(sinix)
#ifdef sun
if (seteuid (real_uid) == -1) {
perror_message ("Error setreuid(real) failed", "");
}
if (setegid (real_gid) == -1) {
perror_message ("Error setregid(real) failed", "");
}
#else
if (setreuid (tin_uid, real_uid) == -1) {
perror_message ("Error setreuid(real) failed", "");
}
if (setregid (tin_gid, real_gid) == -1) {
perror_message ("Error setregid(real) failed", "");
}
#endif /* sun */
#else
if (setuid (real_uid) == -1) {
perror_message ("Error setuid(real) failed", "");
}
if (setgid (real_gid) == -1) {
perror_message ("Error setgid(real) failed", "");
}
#endif
}
void set_tin_uid_gid ()
{
if (local_index)
return;
umask (real_umask);
#if defined(BSD) && ! defined(sinix)
#ifdef sun
if (seteuid (tin_uid) == -1) {
perror_message ("Error setreuid(real) failed", "");
}
if (setegid (tin_gid) == -1) {
perror_message ("Error setregid(real) failed", "");
}
#else
if (setreuid (real_uid, tin_uid) == -1) {
perror_message ("Error setreuid(tin) failed", "");
}
if (setregid (real_gid, tin_gid) == -1) {
perror_message ("Error setregid(tin) failed", "");
}
#endif /* sun */
#else
if (setuid (tin_uid) == -1) {
perror_message ("Error setuid(tin) failed", "");
}
if (setgid (tin_gid) == -1) {
perror_message ("Error setgid(tin) failed", "");
}
#endif
}
void basename (dirname, program)
char *dirname; /* argv[0] */
char *program; /* progname is returned */
{
int i;
strcpy (program, dirname);
for (i=(int) strlen (dirname)-1 ; i ; i--) {
if (dirname[i] == '/') {
strcpy (program, dirname+(i+1));
break;
}
}
}
/*
* Record size of mailbox so we can detect if new mail has arrived
*/
void mail_setup ()
{
struct stat buf;
mailbox_name = get_val ("MAIL", mailbox);
if (stat (mailbox_name, &buf) >= 0) {
mailbox_size = buf.st_size;
} else {
mailbox_size = 0;
}
}
/*
* Return TRUE if new mail has arrived
*/
int mail_check ()
{
struct stat buf;
if (mailbox_name != (char *) 0 &&
stat(mailbox_name, &buf) >= 0 &&
mailbox_size < buf.st_size) {
return TRUE;
}
return FALSE;
}
/*
* Parse various From: lines into the component mail addresses and
* real names
*/
void parse_from (str, addr, name)
char *str;
char *addr;
char *name;
{
register int c;
register char *cp, *ncp;
int gotlt, lastsp, level;
gotlt = 0;
lastsp = 0;
cp = addr;
ncp = name;
while (*str == ' ')
++str;
while (c = *str++)
switch (c) {
case '(':
ncp = name;
level = 1;
while (*str != '\0' && level) {
switch (c = *str++) {
case '(':
*ncp++ = c;
level++;
break;
case ')':
level--;
if (level > 0)
*ncp++ = c;
break;
default:
if (c != '"') { /* IL */
*ncp++ = c;
}
break;
}
}
if (*str)
str++;
lastsp = 0;
break;
case ' ':
if (str[0] == 'a' && str[1] == 't' && str[2] == ' ')
str += 3, *cp++ = '@';
else if (str[0] == '@' && str[1] == ' ')
str += 2, *cp++ = '@';
else
lastsp = 1;
if (ncp > name)
*ncp++ = ' ';
break;
case '<':
cp = addr;
gotlt++;
lastsp = 0;
break;
case '>':
if (gotlt)
goto done;
/* FALL THROUGH CASE */
default:
if (lastsp) {
lastsp = 0;
*cp++ = ' ';
}
*cp++ = c;
if (! gotlt)
*ncp++ = c;
break;
}
done:
*cp = 0;
while (ncp>name && ncp[-1]==' ')
--ncp;
*ncp = 0;
if (*addr == '@') {
char buf [512];
strcpy (buf, addr);
strcpy (addr, "root");
strcat (addr, buf);
}
}
/*
* Convert a string to a long, only look at first n characters
*/
long my_atol (s, n)
char *s;
int n;
{
long ret = 0;
while (*s && n--) {
if (*s >= '0' && *s <= '9')
ret = ret * 10 + (*s - '0');
else
return -1;
s++;
}
return ret;
}
/*
* strcmp that ignores case
*/
#define FOLD_TO_UPPER(a) (islower ((int) (a)) ? toupper ((int) (a)) : (a))
int my_stricmp (p, q)
char *p;
char *q;
{
for (; FOLD_TO_UPPER (*p) == FOLD_TO_UPPER (*q); ++p, ++q) {
if (*p == '\0') {
return (0);
}
}
return (FOLD_TO_UPPER (*p) - FOLD_TO_UPPER (*q));
}
/*
* Return a pointer into s eliminating any leading Re:'s. Example:
*
* Re: Reorganization of misc.jobs
* ^ ^
*/
char *eat_re (s)
char *s;
{
while (*s == 'r' || *s == 'R') {
if ((*(s+1) == 'e' || *(s+1) == 'E')) {
if (*(s+2) == ':')
s += 3;
else if (*(s+2) == '^' && isdigit(*(s+3)) && *(s+4) == ':')
s += 5; /* hurray nn */
else
break;
} else
break;
while (*s == ' ')
s++;
}
return s;
}
/*
* Hash the subjects (after eating the Re's off) for a quicker
* thread search later. We store the hashes for subjects in the
* index file for speed.
*/
long hash_s (s)
char *s;
{
long h = 0;
unsigned char *t = (unsigned char *) s;
while (*t)
h = h * 64 + *t++;
return h;
}
/*
* strncpy that stops at a newline and null terminates
*/
void my_strncpy (p, q, n)
char *p;
char *q;
int n;
{
while (n--) {
if (! *q || *q == '\n')
break;
*p++ = *q++;
}
*p = '\0';
}
int untag_all_articles ()
{
int untagged = FALSE;
register int i;
for (i=0 ; i < top ; i++) {
if (arts[i].tagged) {
arts[i].tagged = FALSE;
untagged = TRUE;
}
}
num_of_tagged_arts = 0;
return (untagged);
}
/*
* ANSI C strstr () - Uses Boyer-Moore algorithm.
*/
char *str_str (text, pattern, patlen)
char *text;
char *pattern;
int patlen;
{
register unsigned char *p, *t;
register int i, p1, j, *delta;
int deltaspace[256];
int textlen;
textlen = strlen (text);
/* algorithm fails if pattern is empty */
if ((p1 = patlen) == 0)
return (text);
/* code below fails (whenever i is unsigned) if pattern too long */
if (p1 > textlen)
return (NULL);
/* set up deltas */
delta = deltaspace;
for (i = 0; i <= 255; i++)
delta[i] = p1;
for (p = (unsigned char *) pattern, i = p1; --i > 0;)
delta[*p++] = i;
/*
* From now on, we want patlen - 1.
* In the loop below, p points to the end of the pattern,
* t points to the end of the text to be tested against the
* pattern, and i counts the amount of text remaining, not
* including the part to be tested.
*/
p1--;
p = (unsigned char *) pattern + p1;
t = (unsigned char *) text + p1;
i = textlen - patlen;
for (;;) {
if (*p == *t && memcmp ((p - p1), (t - p1), p1) == 0)
return ((char *)t - p1);
j = delta[*t];
if (i < j)
break;
i -= j;
t += j;
}
return (NULL);
}
void get_author (thread, respnum, str)
int thread;
int respnum;
char *str;
{
extern int threaded_on_subject;
int author;
/*
int len_from = max_from;
if (thread) {
if (threaded_on_subject) {
len_from = max_subj+max_from;
} else {
len_from = max_from;
}
author = SHOW_FROM_BOTH;
} else {
author = show_author;
}
*/
if (thread) {
if (threaded_on_subject) {
author = SHOW_FROM_BOTH;
} else {
author = show_author;
}
} else {
author = show_author;
}
switch (author) {
case SHOW_FROM_NONE:
str[0] = '\0';
break;
case SHOW_FROM_ADDR:
strcpy (str, arts[respnum].from);
break;
case SHOW_FROM_NAME:
strcpy (str, arts[respnum].name);
break;
case SHOW_FROM_BOTH:
if (arts[respnum].name != arts[respnum].from) {
sprintf (str, "%s (%s)", arts[respnum].name, arts[respnum].from);
} else {
strcpy (str, arts[respnum].from);
}
break;
}
}
void toggle_inverse_video ()
{
inverse_okay = !inverse_okay;
if (inverse_okay) {
#ifndef USE_INVERSE_HACK
draw_arrow_mark = FALSE;
#endif
info_message (txt_inverse_on);
} else {
draw_arrow_mark = TRUE;
info_message (txt_inverse_off);
}
}
int get_arrow_key ()
{
int ch;
ch = ReadCh ();
if (ch == '[' || ch == 'O')
ch = ReadCh();
switch (ch) {
case 'A':
case 'D':
case 'i':
return KEYMAP_UP;
case 'B':
case 'C':
return KEYMAP_DOWN;
case 'I': /* ansi PgUp */
case 'V': /* at386 PgUp */
case 'S': /* 97801 PgUp */
case 'v': /* emacs style */
return KEYMAP_PAGE_UP;
case 'G': /* ansi PgDn */
case 'U': /* at386 PgDn */
case 'T': /* 97801 PgDn */
return KEYMAP_PAGE_DOWN;
case 'H': /* at386 Home */
return KEYMAP_HOME;
case 'F': /* ansi End */
case 'Y': /* at386 End */
return KEYMAP_END;
case '5': /* vt200 PgUp */
ch = ReadCh (); /* eat the ~ */
return KEYMAP_PAGE_UP;
case '6': /* vt200 PgUp */
ch = ReadCh (); /* eat the ~ */
return KEYMAP_PAGE_DOWN;
case '1': /* vt200 PgUp */
ch = ReadCh (); /* eat the ~ */
return KEYMAP_HOME;
case '4': /* vt200 PgUp */
ch = ReadCh (); /* eat the ~ */
return KEYMAP_END;
default:
return KEYMAP_UNKNOWN;
}
}