home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- }
- }
-