home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-07 | 53.6 KB | 2,366 lines |
- Newsgroups: comp.sources.misc
- From: iain%anl433.uucp@Germany.EU.net (Iain Lea)
- Subject: v31i013: tin - threaded full screen newsreader v1.1 PL4, Part13/15
- Message-ID: <1992Jul7.182024.7954@sparky.imd.sterling.com>
- X-Md4-Signature: 9ee573141d8ba83b5ab5bde6719d71d2
- Date: Tue, 7 Jul 1992 18:20:24 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: iain%anl433.uucp@Germany.EU.net (Iain Lea)
- Posting-number: Volume 31, Issue 13
- Archive-name: tin/part13
- Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
- Supersedes: tin: Volume 30, Issue 1-14
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: TODO active.c getline.c main.c signal.c
- # Wrapped by kent@sparky on Mon Jun 29 23:35:15 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 13 (of 15)."'
- if test -f 'TODO' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'TODO'\"
- else
- echo shar: Extracting \"'TODO'\" \(5083 characters\)
- sed "s/^X//" >'TODO' <<'END_OF_FILE'
- X!!! PLEASE NOTE THAT ON CERTAIN MACHINES (ie. mostly RISC DEC,HP) TIN
- X!!! WILL SOMETIMES CRASH WITH SIGBUS or SIGSEGV DUE TO THE HACK THAT
- X!!! IS USED IN HASHING STRINGS IN hashstr.c. SORRY BUT I HAVE NO TIME
- X!!! RIGHT NOW TO REIMPLEMENT THIS PART OF TIN WHICH IS A CARRY OVER
- X!!! FROM TASS v3.2 (Any takers ?)
- X
- XFIX FEATURES V1.x
- X-----------------
- X
- Xo If 'a' in pipe to less and 423 error msg from NNTP it starts less with
- X no file.
- X
- Xo Add Msg-Id: field contents to reply & followups.
- X
- Xo Add code to decrement/increment counter of NEW killed & hot articles
- X so that 'h' is not offered as default when there are no NEW hot articles.
- X Look at 'r' 'z' 'k' & code that marks arts read.
- X
- Xo Add Followup-To: field header to 'fF' followup articles with groups
- X copied from Newsgroups: field.
- X
- Xo Fix spooldirs[] so it auto-expands as needed.
- X
- Xo In inews.c also allow reply_to var to be used in From: field.
- X
- Xo Fix -S option to create an active file when new articles are
- X saved to <savedir>. Also fix -R option to read ACTIVE file created
- X by -S command. Use minimax code from tony travis to help in -R cmd
- X line option.
- X
- Xo Fix Save in feed.c routines.
- X Also fix so SAVING routines just use save_art_to_file() and print
- X *** X Articles saved *** & none of the BS done at the moment
- X
- Xo Add option to 'M' menu to allow 'C' command to return/stay at
- X group level.
- X
- Xo Fix 'c' at article level when within thread level?
- X
- Xo Fix -n option to hash the groups read in from ~/.tin/active and
- X mark active[].flag as TRUE. then find flag=FALSE and ask user if
- X they want to subscribe to group. On xenix386 takes 15 seconds on
- X current -n option. Also of CNEWS just do a compare of active.times
- X UNDER CNEWS USE active.times FILE FROM NNTPSERVER
- X UNDER NNTP USE newnews COMMAND FROM NNTPSERVER
- X
- Xo Add 'r' command to newsgroup level.
- X
- XFIX FEATURES V2.0
- X-----------------
- X
- Xo If saving in mailbox format and mailbox does not exist query the user?
- X
- Xo In kill.c should kill_both only kill when subj & from are matched?
- X
- Xo Add file ~/.tin/tinheaders for following headers to be stored:
- X Reply-To:
- X Organisation:
- X Distribution:
- X
- Xo Make binary as both standalone & NNTP as default
- X
- Xo Add Ctrl-/ Ctrl-? to search the whole of an article (Subj,From & Body)
- X at Group & Page level
- X
- Xo Add elm like mini-menu to tin for first time users.
- X
- Xo Add option to 'M' menu to allow unlinking/not of ~/.article
- X after posting an article.
- X
- Xo Add hashing to speedup valid_art() in big groups. Make it compile
- X option so tin is still usable on Minix/small memory machines.
- X -DSMALL_MEMORY_MACHINE
- X
- Xo Add auto-aliasing of peoples mail addresses to mail aliases file.
- X
- Xo Add Xref handling of articles so that read ones are marked read in
- X other groups. Use update_group() to do it?
- X Needs to handle 'c' 'C' 'k' 'K' commands. Perhaps it should be an
- X option so that performance is not impaired. (JIM).
- X
- Xo Add ^G command to skip to next Subject: in digests.
- X
- Xo Try compiling with -D_POSIX_SOURCE
- X
- Xo Add filename & groupname completion (readline?).
- X
- Xo Fix uuscram code in uudecode.
- X
- Xo Fix code to sort arts. At page level funny things happen.
- X
- XADD FEATURES
- X------------
- X
- Xo Add -P <pattern> or -P <file> to search for in new news and to
- X notify user by mail. Should understand 'subject=text' 'from=text'
- X 'body=text' and .AND. && .OR. || for filtering purposes.
- X
- Xo Add elm style print command with %s in it for printing in 'M'.
- X
- Xo Add 'C' command at group level to catchup present group and
- X enter next group with unread news in it.
- X
- Xo Sort .newsrc according to preference. (sort active file as it is read)
- X
- Xo Add time period to killing articles
- X
- XOTHER STUFF
- X-----------
- Xo Add rebindable keymaps and provide different terminal keymaps
- X (ie. keymap.ansi, keymap.wy50 etc.)
- X
- Xo Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
- X consists of comp.sys.ibm.* groups).
- X
- Xo Add threading on References like trn with mthreads database.
- X
- Xo Add full curses support instead of using printf()'s or joetty.
- X
- Xo Sub all not empty groups by looking at min max values in active array
- X and Unsub all empty groups by looking at min max values in active
- X array. have a command to do this in a toggle effect.
- X
- Xo Run tests of my_strncpy() and system strncpy()
- X
- Xo Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
- X consists of comp.sys.ibm.* groups). ~/.tin/virtual
- X
- Xo Change defaults on a per group basis
- XGroup Connect Read Thread Save Savedir Maildir Sigfile
- X Unread Unthread Mail ProcTyp Mailbox
- X-----------------------------------------------------------------------------
- Xjunk local Unread Thread None Default Default Default
- Xalt.sources 1.3.3.3 Read Thread Save $SRC/alt Default ~/.Sig-alt
- X
- XAdd a menu interface to define all this. Also add edit menu for entries in
- Xkill file.
- X
- XEach group could have a field to say which NNTP/local connection to use so
- Xas to be able to plug into different NNTP servers for different newsgroups
- END_OF_FILE
- if test 5083 -ne `wc -c <'TODO'`; then
- echo shar: \"'TODO'\" unpacked with wrong size!
- fi
- # end of 'TODO'
- fi
- if test -f 'active.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'active.c'\"
- else
- echo shar: Extracting \"'active.c'\" \(10048 characters\)
- sed "s/^X//" >'active.c' <<'END_OF_FILE'
- X/*
- X * Project : tin - a threaded Netnews reader
- X * Module : active.c
- X * Author : I.Lea
- X * Created : 16-02-92
- X * Updated : 08-06-92
- X * Notes :
- X * Copyright : (c) Copyright 1991-92 by Iain Lea
- X * You may freely copy or redistribute this software,
- X * so long as there is no profit made from its use, sale
- X * trade or reproduction. You may not change this copy-
- X * right notice, and it must be included in any copy made
- X */
- X
- X#include "tin.h"
- X
- Xint group_hash[TABLE_SIZE]; /* group name --> active[] */
- Xint reread_active_file = FALSE;
- X
- X
- X/*
- X * Resync active file when SIGALRM signal received that
- X * is triggered by alarm (RESYNC_ACTIVE_SECS) call.
- X */
- X
- Xvoid resync_active_file ()
- X{
- X if (reread_active_file) {
- X free_active_arrays ();
- X max_active = DEFAULT_ACTIVE_NUM;
- X expand_active ();
- X read_active_file ();
- X read_newsgroups_file ();
- X read_newsrc (TRUE);
- X set_alarm_signal ();
- X mail_setup ();
- X group_selection_page ();
- X }
- X}
- X
- X/*
- X * Load the active file into active[] and create copy of active ~/.tin/active
- X */
- X
- Xint read_active_file ()
- X{
- X FILE *fp;
- X char *p, *q, *r;
- X char buf[LEN];
- X char moderated = 'y';
- X int created, i;
- X long h;
- X
- X num_active = 0;
- X
- X if (! update) {
- X wait_message (txt_reading_active_file);
- X }
- X
- X if ((fp = open_active_fp ()) == NULL) {
- X if (compiled_with_nntp) {
- X sprintf (msg, txt_cannot_open_active_file, active_file, progname);
- X wait_message (msg);
- X } else {
- X fputc ('\n', stderr);
- X fprintf (stderr, txt_cannot_open, active_file);
- X fputc ('\n', stderr);
- X fflush (stderr);
- X }
- X exit (1);
- X }
- X
- X for (i = 0; i < TABLE_SIZE; i++) {
- X group_hash[i] = -1;
- X }
- X
- X while (fgets (buf, sizeof (buf), fp) != NULL) {
- X for (p = buf; *p && *p != ' '; p++)
- X continue;
- X if (*p != ' ') {
- X error_message (txt_bad_active_file, buf);
- X continue;
- X }
- X *p++ = '\0';
- X
- X if (num_active >= max_active) {
- X debug_nntp ("read_active_file", "EXPANDING active file");
- X expand_active ();
- X }
- X
- X h = hash_groupname (buf);
- X
- X if (group_hash[h] == -1) {
- X group_hash[h] = num_active;
- X } else { /* hash linked list chaining */
- X for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
- X if (strcmp(active[i].name, buf) == 0) {
- X goto read_active_continue; /* kill dups */
- X }
- X }
- X if (strcmp(active[i].name, buf) == 0)
- X goto read_active_continue;
- X active[i].next = num_active;
- X }
- X
- X for (q = p; *q && *q != ' '; q++)
- X continue;
- X if (*q != ' ') {
- X error_message (txt_bad_active_file, buf);
- X continue;
- X }
- X *q++ = '\0';
- X
- X for (r = q; *r && *r != '\n'; r++) {
- X if (*r == 'y' || *r == 'm') {
- X moderated = *r;
- X break;
- X }
- X }
- X
- X /*
- X * Group info.
- X */
- X active[num_active].name = str_dup (buf);
- X active[num_active].description = (char *) 0;
- X active[num_active].max = (long) atol (p);
- X active[num_active].min = (long) atol (q);
- X active[num_active].moderated = moderated;
- X active[num_active].next = -1; /* hash chaining */
- X active[num_active].flag = UNSUBSCRIBED; /* not in my_group[] yet */
- X /*
- X * Per group attributes
- X */
- X active[num_active].attribute.server = (char *) 0;
- X active[num_active].attribute.maildir = default_maildir;
- X active[num_active].attribute.savedir = default_savedir;
- X active[num_active].attribute.sigfile = default_sigfile;
- X active[num_active].attribute.read = FALSE; /* read/unread */
- X active[num_active].attribute.showall = show_only_unread;
- X active[num_active].attribute.thread = thread_arts;
- X active[num_active].attribute.sortby = sort_art_type;
- X active[num_active].attribute.author = show_author;
- X active[num_active].attribute.autosave= save_archive_name;
- X active[num_active].attribute.process = post_proc_type;
- X
- X num_active++;
- X
- Xread_active_continue:;
- X
- X }
- X fclose (fp);
- X
- X /*
- X * exit if active file is empty
- X */
- X if (! num_active) {
- X error_message (txt_active_file_is_empty, active_file);
- X exit (1);
- X }
- X
- X /*
- X * create backup of LIBDIR/active for use by -n option to notify new groups
- X */
- X created = backup_active (TRUE);
- X
- X/* if (cmd_line && (read_news_via_nntp && update == FALSE)) {
- X if (! (update && ! verbose)) {
- X wait_message ("\n");
- X }
- X }
- X*/
- X if (cmd_line && ! update && ! verbose) {
- X wait_message ("\n");
- X }
- X
- X return (created);
- X}
- X
- X/*
- X * create ~/.tin/active from LIBDIR/active if it does not exist
- X */
- X
- Xint backup_active (create)
- X int create;
- X{
- X char buf[LEN];
- X FILE *fp;
- X int created = FALSE;
- X int i;
- X struct stat sb;
- X
- X sprintf (buf, "%s/active", rcdir);
- X
- X if (create) {
- X if (stat (buf, &sb) != -1) {
- X goto backup_active_done;
- X }
- X }
- X
- X if ((fp = fopen (buf, "w")) != NULL) {
- X for (i = 0; i < num_active ; i++) { /* for each group */
- X fprintf (fp, "%s\n", active[i].name);
- X }
- X fclose (fp);
- X chmod (buf, 0644);
- X created = TRUE;
- X }
- X
- Xbackup_active_done:
- X return (created);
- X}
- X
- X/*
- X * Option -n to check for any newly created newsgroups.
- X */
- X
- Xvoid notify_groups ()
- X{
- X char buf[LEN];
- X FILE *fp;
- X int group_not_found;
- X int index;
- X int num = 0;
- X int update_old_active = FALSE;
- X int max_old_active;
- X register int i, j;
- X struct notify_t {
- X char name[LEN];
- X int len;
- X int visited;
- X } *old_active = (struct notify_t *) 0;
- X
- X sprintf (buf, "%s/active", rcdir);
- X
- X if ((fp = fopen (buf, "r")) == NULL) {
- X perror_message (txt_cannot_open, buf);
- X goto notify_groups_done;
- X }
- X
- X Raw (TRUE);
- X
- X wait_message (txt_checking_active_file);
- X
- X max_old_active = num_active;
- X
- X old_active = (struct notify_t *) my_malloc ((unsigned) sizeof (struct notify_t) * max_old_active);
- X if (old_active == (struct notify_t *) 0) {
- X error_message (txt_out_of_memory, progname);
- X goto notify_groups_done;
- X }
- X
- X while (fgets (old_active[num].name, sizeof (old_active[num].name), fp) != NULL) {
- X old_active[num].len = strlen (old_active[num].name)-1;
- X old_active[num].name[old_active[num].len] = '\0';
- X old_active[num].visited = FALSE;
- X num++;
- X if (num >= max_old_active) {
- X max_old_active= max_old_active + (max_old_active / 2);
- X old_active= (struct notify_t*) my_realloc(
- X (char *) old_active,
- X (unsigned) sizeof(struct notify_t) * max_old_active);
- X if (old_active == (struct notify_t *) 0) {
- X error_message (txt_out_of_memory, progname);
- X goto notify_groups_done;
- X }
- X }
- X }
- X
- X for (i = 0 ; i < num_active ; i++) {
- X group_not_found = TRUE;
- X for (j=0; j < num ; j++) {
- X if (strcmp (old_active[j].name, active[i].name) == 0) {
- X group_not_found = FALSE; /* found it so read in next group */
- X old_active[j].visited = TRUE;
- X break;
- X }
- X }
- X
- X if (group_not_found == FALSE) {
- X continue;
- X }
- X
- X update_old_active = TRUE;
- X do {
- X fputc ('\r', stdout);
- X CleartoEOLN();
- X printf (txt_subscribe_to_new_group, active[i].name);
- X fflush (stdout);
- X buf[0] = ReadCh();
- X } while (buf[0] != 'y' && buf[0] != 'n');
- X
- X if (buf[0] == 'y') {
- X index = add_group (active[i].name, TRUE);
- X subscribe (active[my_group[index]].name, ':',
- X my_group[index], FALSE);
- X }
- X printf ("\r\n%s", txt_checking);
- X fflush (stdout);
- X }
- X fclose (fp);
- X fputc ('\r', stdout);
- X fflush (stdout);
- X CleartoEOLN();
- X
- X /*
- X * Look for bogus groups
- X */
- X for (j = 0 ; j < num ; j++) {
- X if (old_active[j].visited) {
- X continue;
- X }
- X do {
- X update_old_active= 1;
- X fputc ('\r', stdout);
- X CleartoEOLN ();
- X printf (txt_delete_bogus_group, old_active[j].name);
- X fflush (stdout);
- X buf[0] = ReadCh ();
- X } while (buf[0] != 'y' && buf[0] != 'n');
- X if (buf[0] == 'y') {
- X delete_group (old_active[j].name);
- X }
- X printf ("\r\n");
- X }
- X
- X Raw (TRUE);
- X
- X /*
- X * write active[] to ~/.tin/active
- X */
- X if (update_old_active) {
- X backup_active (FALSE);
- X }
- X
- Xnotify_groups_done:
- X if (old_active != (struct notify_t *) 0) {
- X free ((char *) old_active);
- X old_active = (struct notify_t *) 0;
- X }
- X}
- X
- X/*
- X * Mark any groups in my_group[] that are in ~/.tin/unthread so they
- X * will not be threaded
- X */
- X
- Xvoid mark_unthreaded_groups ()
- X{
- X FILE *fp;
- X char buf[LEN];
- X int i, len;
- X long h;
- X
- X#ifndef INDEX_DAEMON
- X
- X if ((fp = fopen (unthreadfile, "r")) == NULL) {
- X perror_message (txt_cannot_open, unthreadfile);
- X return;
- X }
- X
- X while (fgets (buf, sizeof (buf), fp) != NULL) {
- X buf[strlen (buf)-1] = '\0';
- X h = hash_groupname (buf);
- X sprintf (msg, "Unthreading %s...\n", buf);
- X wait_message (msg);
- X
- X i = group_hash[h];
- X
- X if (active[i].next == -1) {
- X len = strlen (active[i].name);
- X if (strncmp (active[i].name, buf, len) == 0) {
- X active[i].attribute.thread = FALSE;
- X }
- X
- X } else {
- X for (i=group_hash[h] ; i >= 0 ; i=active[i].next) {
- X len = strlen (active[i].name);
- X if (strncmp (active[i].name, buf, len) == 0) {
- X active[i].attribute.thread = FALSE;
- X break;
- X }
- X }
- X }
- X }
- X
- X fclose (fp);
- X#endif /* INDEX_DAEMON */
- X}
- X
- X/*
- X * Load the text description from LIBDIR/newsgroups for each group
- X * into the active[] array.
- X */
- X
- Xvoid read_newsgroups_file ()
- X{
- X FILE *fp;
- X char *p, *q;
- X char buf[LEN];
- X char group[PATH_LEN];
- X int i;
- X long h;
- X
- X if (! show_description || update) {
- X return;
- X }
- X
- X wait_message (txt_reading_newsgroups_file);
- X
- X if ((fp = open_newsgroups_fp ()) == NULL) {
- X return;
- X }
- X
- X while (fgets (buf, sizeof (buf), fp) != NULL) {
- X buf[strlen (buf)-1] = '\0';
- X
- X for (p = buf, q = group ; *p && *p != ' ' && *p != '\t' ; p++, q++) {
- X *q = *p;
- X }
- X *q = '\0';
- X
- X for (;*p == '\t' || *p == ' '; p++) {
- X ;
- X }
- X
- X h = hash_groupname (group);
- X
- X i = group_hash[h];
- X
- X if (debug == 2) {
- X fprintf (stderr, "HASH=[%5ld] IDX=[%5d] GRP=[%s] TXT=[%s]\n", h, i, group, p);
- X }
- X
- X if (active[i].next == -1) {
- X if (strcmp (active[i].name, group) == 0) {
- Xif (debug == 2) {
- X fprintf (stderr, "FOUND HEAD\n");
- X}
- X if (active[i].description == (char *) 0) {
- X active[i].description = str_dup (p);
- X }
- X }
- X } else {
- X for (; i >= 0 ; i = active[i].next) {
- X if (strcmp (active[i].name, group) == 0) {
- Xif (debug == 2) {
- X fprintf (stderr, "FOUND LINK\n");
- X}
- X if (active[i].description == (char *) 0) {
- X active[i].description = str_dup (p);
- X break;
- X }
- X }
- X }
- X }
- X }
- X fclose (fp);
- X
- X if (cmd_line && ! update && ! verbose) {
- X wait_message ("\n");
- X }
- X}
- END_OF_FILE
- if test 10048 -ne `wc -c <'active.c'`; then
- echo shar: \"'active.c'\" unpacked with wrong size!
- fi
- # end of 'active.c'
- fi
- if test -f 'getline.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getline.c'\"
- else
- echo shar: Extracting \"'getline.c'\" \(11458 characters\)
- sed "s/^X//" >'getline.c' <<'END_OF_FILE'
- X/*
- X * Project : tin - a threaded Netnews reader
- X * Module : getline.c
- X * Author : Chris Thewalt & Iain Lea
- X * Created : 09-11-91
- X * Updated : 29-03-92
- X * Notes : emacs style line editing input package.
- X * Copyright : (c) Copyright 1991-92 by Chris Thewalt & Iain Lea
- X * Permission to use, copy, modify, and distribute this
- X * software for any purpose and without fee is hereby
- X * granted, provided that the above copyright notices
- X * appear in all copies and that both the copyright
- X * notice and this permission notice appear in supporting
- X * documentation. This software is provided "as is" without
- X * express or implied warranty.
- X */
- X
- X#include "tin.h"
- X
- Xextern int isatty ();
- X
- X#define BUF_SIZE 1024
- X#define SCROLL 30
- X#define TABSIZE 4
- X#ifndef HIST_SIZE
- X#define HIST_SIZE 100
- X#endif
- X
- X#define CTRL_A '\001'
- X#define CTRL_B '\002'
- X#define CTRL_D '\004'
- X#define CTRL_E '\005'
- X#define CTRL_F '\006'
- X#define CTRL_H '\010'
- X#define CTRL_K '\013'
- X#define CTRL_L '\014'
- X#define CTRL_R '\022'
- X#define CTRL_N '\016'
- X#define CTRL_P '\020'
- X#define TAB '\t'
- X#define DEL '\177'
- X
- Xchar *hist_buf[HIST_SIZE];
- Xint hist_pos, hist_last;
- Xstatic char gl_buf[BUF_SIZE]; /* input buffer */
- Xstatic char *gl_prompt; /* to save the prompt string */
- Xstatic int gl_init_done = 0; /* -1 is terminal, 1 is batch */
- Xstatic int gl_width = 0; /* net size available for input */
- Xstatic int gl_pos, gl_cnt = 0; /* position and size of input */
- X
- X#if __STDC__
- X
- Xstatic int gl_tab (char *, int, int *);
- Xstatic void gl_redraw (void);
- Xstatic void gl_addchar (int);
- Xstatic void gl_newline (void);
- Xstatic void gl_fixup (int, int);
- Xstatic void gl_del (int);
- Xstatic void gl_kill (void);
- Xstatic void hist_add (void);
- Xstatic void hist_init (void);
- Xstatic void hist_next (void);
- Xstatic void hist_prev (void);
- X
- Xint (*gl_in_hook)(char *) = 0;
- Xint (*gl_out_hook)(char *) = 0;
- Xint (*gl_tab_hook)(char *, int, int *) = gl_tab;
- X
- X#else
- X
- Xstatic int gl_tab ();
- Xstatic void gl_redraw ();
- Xstatic void gl_addchar ();
- Xstatic void gl_newline ();
- Xstatic void gl_fixup ();
- Xstatic void gl_del ();
- Xstatic void gl_kill ();
- Xstatic void hist_add ();
- Xstatic void hist_init ();
- Xstatic void hist_next ();
- Xstatic void hist_prev ();
- X
- Xint (*gl_in_hook)() = 0;
- Xint (*gl_out_hook)() = 0;
- Xint (*gl_tab_hook)() = gl_tab;
- X
- X#endif
- X
- X
- X#if __STDC__
- Xchar *getline (char *prompt, int number_only, char *str)
- X#else
- Xchar *getline (prompt, number_only, str)
- X char *prompt;
- X int number_only;
- X char *str;
- X#endif
- X{
- X int c, i, loc, tmp;
- X
- X if (! gl_init_done) {
- X gl_init_done = 1;
- X hist_init ();
- X }
- X
- X if (prompt == (char *) 0) {
- X prompt = "";
- X }
- X gl_buf[0] = 0; /* used as end of input indicator */
- X gl_fixup (-1, 0); /* this resets gl_fixup */
- X gl_width = COLS - strlen (prompt);
- X gl_prompt = prompt;
- X gl_pos = gl_cnt = 0;
- X
- X fputs (prompt, stdout);
- X fflush (stdout);
- X
- X if (gl_in_hook) {
- X loc = gl_in_hook (gl_buf);
- X if (loc >= 0)
- X gl_fixup (0, BUF_SIZE);
- X }
- X if (str != (char *) 0) {
- X for (i=0 ; str[i] ; i++)
- X gl_addchar (str[i]);
- X }
- X while ((c = ReadCh ()) != EOF) {
- X c &= 0xff;
- X if (isprint (c)) {
- X if (number_only) {
- X if (isdigit (c) && gl_cnt < 6) { /* num < 100000 */
- X gl_addchar (c);
- X } else {
- X ring_bell ();
- X }
- X } else {
- X gl_addchar (c);
- X }
- X } else {
- X switch (c) {
- X case ESC: /* abort */
- X return (char *) 0;
- X break;
- X case '\n': /* newline */
- X case '\r':
- X gl_newline ();
- X return gl_buf;
- X break;
- X case CTRL_A:
- X gl_fixup (-1, 0);
- X break;
- X case CTRL_B:
- X gl_fixup (-1, gl_pos-1);
- X break;
- X case CTRL_D:
- X if (gl_cnt == 0) {
- X gl_buf[0] = 0;
- X fputc ('\n', stdout);
- X return gl_buf;
- X } else {
- X gl_del (0);
- X }
- X break;
- X case CTRL_E:
- X gl_fixup (-1, gl_cnt);
- X break;
- X case CTRL_F:
- X gl_fixup (-1, gl_pos+1);
- X break;
- X case CTRL_H:
- X case DEL:
- X gl_del (-1);
- X break;
- X case TAB:
- X if (gl_tab_hook) {
- X tmp = gl_pos;
- X loc = gl_tab_hook (gl_buf, strlen (gl_prompt), &tmp);
- X if (loc >= 0 || tmp != gl_pos)
- X gl_fixup (loc, tmp);
- X }
- X break;
- X case CTRL_K:
- X gl_kill ();
- X break;
- X case CTRL_L:
- X case CTRL_R:
- X gl_redraw ();
- X break;
- X case CTRL_N:
- X hist_next ();
- X break;
- X case CTRL_P:
- X hist_prev ();
- X break;
- X default:
- X ring_bell ();
- X break;
- X }
- X }
- X }
- X return gl_buf;
- X}
- X
- X/*
- X * adds the character c to the input buffer at current location if
- X * the character is in the allowed template of characters
- X */
- X
- X#if __STDC__
- Xstatic void gl_addchar (int c)
- X#else
- Xstatic void gl_addchar (c)
- X int c;
- X#endif
- X{
- X int i;
- X
- X if (gl_cnt >= BUF_SIZE - 1) {
- X error_message ("getline: input buffer overflow", "");
- X exit (1);
- X }
- X
- X for (i=gl_cnt; i >= gl_pos; i--) {
- X gl_buf[i+1] = gl_buf[i];
- X }
- X gl_buf[gl_pos] = c;
- X gl_fixup (gl_pos, gl_pos+1);
- X}
- X
- X/*
- X * Cleans up entire line before returning to caller. A \n is appended.
- X * If line longer than screen, we redraw starting at beginning
- X */
- X
- Xstatic void gl_newline ()
- X{
- X int change = gl_cnt;
- X int len = gl_cnt;
- X int loc = gl_width - 5; /* shifts line back to start position */
- X
- X if (gl_cnt >= BUF_SIZE - 1) {
- X error_message ("getline: input buffer overflow", "");
- X exit (1);
- X }
- X hist_add (); /* only adds if nonblank */
- X if (gl_out_hook) {
- X change = gl_out_hook (gl_buf);
- X len = strlen (gl_buf);
- X }
- X if (loc > len)
- X loc = len;
- X gl_fixup (change, loc); /* must do this before appending \n */
- X gl_buf[len] = '\0';
- X}
- X
- X/*
- X * Delete a character. The loc variable can be:
- X * -1 : delete character to left of cursor
- X * 0 : delete character under cursor
- X */
- X
- X#if __STDC__
- Xstatic void gl_del (int loc)
- X#else
- Xstatic void gl_del (loc)
- X int loc;
- X#endif
- X{
- X int i;
- X
- X if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
- X for (i=gl_pos+loc; i < gl_cnt; i++)
- X gl_buf[i] = gl_buf[i+1];
- X gl_fixup (gl_pos+loc, gl_pos+loc);
- X } else {
- X ring_bell ();
- X }
- X}
- X
- X/*
- X * delete from current position to the end of line
- X */
- X
- Xstatic void gl_kill ()
- X{
- X if (gl_pos < gl_cnt) {
- X gl_buf[gl_pos] = '\0';
- X gl_fixup (gl_pos, gl_pos);
- X } else {
- X ring_bell ();
- X }
- X}
- X
- X/*
- X * emit a newline, reset and redraw prompt and current input line
- X */
- X
- Xstatic void gl_redraw ()
- X{
- X if (gl_init_done == -1) {
- X fputc ('\n', stdout);
- X fputs (gl_prompt, stdout);
- X gl_pos = 0;
- X gl_fixup (0, BUF_SIZE);
- X }
- X}
- X
- X/*
- X * This function is used both for redrawing when input changes or for
- X * moving within the input line. The parameters are:
- X * change : the index of the start of changes in the input buffer,
- X * with -1 indicating no changes.
- X * cursor : the desired location of the cursor after the call.
- X * A value of BUF_SIZE can be used to indicate the cursor
- X * should move just past the end of the input line.
- X */
- X
- X#if __STDC__
- Xstatic void gl_fixup (int change, int cursor)
- X#else
- Xstatic void gl_fixup (change, cursor)
- X int change;
- X int cursor;
- X#endif
- X{
- X static int gl_shift; /* index of first on screen character */
- X static int off_right; /* true if more text right of screen */
- X static int off_left; /* true if more text left of screen */
- X int left = 0, right = -1; /* bounds for redraw */
- X int pad; /* how much to erase at end of line */
- X int backup; /* how far to backup before fixing */
- X int new_shift; /* value of shift based on cursor */
- X int extra; /* adjusts when shift (scroll) happens */
- X int i;
- X
- X if (change == -1 && cursor == 0 && gl_buf[0] == 0) { /* reset */
- X gl_shift = off_right = off_left = 0;
- X return;
- X }
- X pad = (off_right) ? gl_width - 1 : gl_cnt - gl_shift; /* old length */
- X backup = gl_pos - gl_shift;
- X if (change >= 0) {
- X gl_cnt = strlen (gl_buf);
- X if (change > gl_cnt)
- X change = gl_cnt;
- X }
- X if (cursor > gl_cnt) {
- X if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
- X ring_bell ();
- X cursor = gl_cnt;
- X }
- X if (cursor < 0) {
- X ring_bell ();
- X cursor = 0;
- X }
- X if (off_right || off_left && (cursor < gl_shift + gl_width - SCROLL / 2))
- X extra = 2; /* shift the scrolling boundary */
- X else
- X extra = 0;
- X new_shift = cursor + extra + SCROLL - gl_width;
- X if (new_shift > 0) {
- X new_shift /= SCROLL;
- X new_shift *= SCROLL;
- X } else
- X new_shift = 0;
- X if (new_shift != gl_shift) { /* scroll occurs */
- X gl_shift = new_shift;
- X off_left = (gl_shift) ? 1 : 0;
- X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
- X left = gl_shift;
- X right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
- X } else if (change >= 0) { /* no scroll, but text changed */
- X if (change < gl_shift + off_left) {
- X left = gl_shift;
- X } else {
- X left = change;
- X backup = gl_pos - change;
- X }
- X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
- X right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
- X }
- X pad -= (off_right) ? gl_width - 1 : gl_cnt - gl_shift;
- X pad = (pad < 0)? 0 : pad;
- X if (left <= right) { /* clean up screen */
- X for (i=0; i < backup; i++)
- X fputc ('\b', stdout);
- X if (left == gl_shift && off_left) {
- X fputc ('$', stdout);
- X left++;
- X }
- X for (i=left; i < right; i++)
- X fputc (gl_buf[i], stdout);
- X if (off_right) {
- X fputc ('$', stdout);
- X gl_pos = right + 1;
- X } else {
- X for (i=0; i < pad; i++) /* erase remains of prev line */
- X fputc (' ', stdout);
- X gl_pos = right + pad;
- X }
- X }
- X i = gl_pos - cursor; /* move to final cursor location */
- X if (i > 0) {
- X while (i--)
- X fputc ('\b', stdout);
- X } else {
- X for (i=gl_pos; i < cursor; i++)
- X fputc (gl_buf[i], stdout);
- X }
- X fflush (stdout);
- X gl_pos = cursor;
- X}
- X
- X/*
- X * default tab handler, acts like tabstops every TABSIZE cols
- X */
- X
- X#if __STDC__
- Xstatic int gl_tab (char *buf, int offset, int *loc)
- X#else
- Xstatic int gl_tab (buf, offset, loc)
- X char *buf;
- X int offset;
- X int *loc;
- X#endif
- X{
- X int i, count, len;
- X
- X len = strlen (buf);
- X count = TABSIZE - (offset + *loc) % TABSIZE;
- X for (i=len; i >= *loc; i--)
- X buf[i+count] = buf[i];
- X for (i=0; i < count; i++)
- X buf[*loc+i] = ' ';
- X i = *loc;
- X *loc = i + count;
- X return i;
- X}
- X
- X/*
- X * History functions
- X */
- X
- Xstatic void hist_init ()
- X{
- X int i;
- X
- X for (i=0; i < HIST_SIZE; i++)
- X hist_buf[i] = (char *) 0;
- X}
- X
- X
- Xstatic void hist_add ()
- X{
- X char *p = gl_buf;
- X
- X while (*p == ' ' || *p == '\t') /* only save nonblank line */
- X p++;
- X if (*p) {
- X hist_buf[hist_last] = str_dup (gl_buf);
- X hist_last = (hist_last + 1) % HIST_SIZE;
- X if (hist_buf[hist_last]) { /* erase next location */
- X free(hist_buf[hist_last]);
- X hist_buf[hist_last] = (char *) 0;
- X }
- X }
- X hist_pos = hist_last;
- X}
- X
- X/*
- X * loads previous hist entry into input buffer, sticks on first
- X */
- X
- Xstatic void hist_prev ()
- X{
- X int next;
- X
- X next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
- X if (next != hist_last) {
- X if (hist_buf[next]) {
- X hist_pos = next;
- X strcpy (gl_buf, hist_buf[hist_pos]);
- X } else {
- X ring_bell ();
- X }
- X } else {
- X ring_bell ();
- X }
- X if (gl_in_hook)
- X gl_in_hook (gl_buf);
- X gl_fixup (0, BUF_SIZE);
- X}
- X
- X/*
- X * loads next hist entry into input buffer, clears on last
- X */
- X
- Xstatic void hist_next ()
- X{
- X if (hist_pos != hist_last) {
- X hist_pos = (hist_pos + 1) % HIST_SIZE;
- X if (hist_buf[hist_pos]) {
- X strcpy (gl_buf, hist_buf[hist_pos]);
- X } else {
- X gl_buf[0] = 0;
- X }
- X } else {
- X ring_bell ();
- X }
- X if (gl_in_hook)
- X gl_in_hook (gl_buf);
- X gl_fixup (0, BUF_SIZE);
- X}
- END_OF_FILE
- if test 11458 -ne `wc -c <'getline.c'`; then
- echo shar: \"'getline.c'\" unpacked with wrong size!
- fi
- # end of 'getline.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(12528 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X/*
- X * Project : tin - a threaded Netnews reader
- X * Module : main.c
- X * Author : I.Lea & R.Skrenta
- X * Created : 01-04-91
- X * Updated : 04-06-92
- X * Notes :
- X * Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
- X * You may freely copy or redistribute this software,
- X * so long as there is no profit made from its use, sale
- X * trade or reproduction. You may not change this copy-
- X * right notice, and it must be included in any copy made
- X */
- X
- X#include "tin.h"
- X
- X/*
- X * OK lets start the ball rolling...
- X */
- X
- Xvoid main (argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int created, i;
- X int start_groupnum = 0;
- X
- X cmd_line = TRUE;
- X debug = 0; /* debug OFF */
- X
- X set_signal_handlers ();
- X
- X basename (argv[0], progname);
- X
- X sprintf (page_header, "%s %s PL%d", progname, VERSION, PATCHLEVEL);
- X sprintf (cvers, "%s (c) Copyright 1991-92 Iain Lea.", page_header);
- X
- X#if defined(NNTP_ONLY) || defined(CDROM_ONLY)
- X read_news_via_nntp = TRUE;
- X#else
- X /*
- X * rtin/cdtin so read news remotely via NNTP
- X */
- X if (progname[0] == 'r' || (progname[0] == 'c' && progname[1] == 'd' )) {
- X# ifdef NNTP_ABLE
- X read_news_via_nntp = TRUE;
- X# else
- X error_message (txt_option_not_enabled, "-DNNTP_ABLE");
- X exit (1);
- X# endif
- X }
- X#endif
- X
- X /*
- X * set up char *'s: homedir, newsrc, etc.
- X */
- X init_selfinfo ();
- X
- X /*
- X * process command line options
- X */
- X read_cmd_line_options (argc, argv);
- X if (update_fork || (update && verbose) || !update) {
- X error_message (cvers, "");
- X }
- X
- X /*
- X * if specified connect to (cdrom pseudo) nntp server
- X */
- X nntp_open ();
- X
- X /*
- X * allocate initial array sizes
- X */
- X init_alloc ();
- X hash_init ();
- X
- X /*
- X * load the active file into active[]
- X */
- X created = read_active_file ();
- X
- X /*
- X * read text descriptions for each group from LIBDIR/newsgroups
- X */
- X read_newsgroups_file ();
- X debug_print_active ();
- X
- X /*
- X * log username info to local/central logfile (NNTP XUSER)
- X */
- X log_user ();
- X
- X if (create_mail_save_dirs ()) {
- X write_rcfile ();
- X }
- X
- X if (optind < argc) {
- X while (optind < argc) {
- X for (i = 0 ; i < num_active ; i++) {
- X if (wildmat(active[i].name, argv[optind])) {
- X if (add_group (active[i].name, TRUE) < 0) {
- X error_message (txt_not_in_active_file, active[i].name);
- X }
- X }
- X }
- X optind++;
- X }
- X } else {
- X backup_newsrc ();
- X read_newsrc (TRUE);
- X mark_unthreaded_groups ();
- X }
- X
- X /*
- X * read in users kill/auto-select (hot) file
- X */
- X killed_articles = read_kill_file ();
- X
- X /*
- X * check/start if any new/unread articles
- X */
- X start_groupnum = check_for_any_new_news (check_any_unread, start_any_unread);
- X
- X /*
- X * mail any new articles to specified user
- X * or
- X * save any new articles to savedir structure for later reading
- X */
- X save_or_mail_new_news ();
- X
- X /*
- X * update index files
- X */
- X update_index_files ();
- X
- X if (! InitScreen ()) {
- X error_message (txt_screen_init_failed, progname);
- X exit (1);
- X }
- X
- X /*
- X * get screen size from termcap entry
- X */
- X ScreenSize (&LINES, &COLS);
- X cmd_line = FALSE;
- X Raw (TRUE);
- X
- X /*
- X * check & set actual screen size
- X */
- X set_win_size (&LINES, &COLS);
- X
- X /*
- X * check for any newly created newsgroups
- X */
- X if (notify_new_groups && ! created) {
- X notify_groups ();
- X }
- X
- X /*
- X * if first time print welcome screen
- X and auto-subscribe
- X * to groups specified in /usr/lib/news/subscribe locally
- X * or via NNTP if reading news remotely (LIST SUBSCRIBE)
- X */
- X if (created_rcdir && update == FALSE) {
- X show_intro_page ();
- X }
- X
- X selection_index (start_groupnum);
- X
- X tin_done (0);
- X}
- X
- X/*
- X * process command line options
- X */
- X
- Xvoid read_cmd_line_options (argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int ch;
- X
- X#ifdef INDEX_DAEMON
- X while ((ch = getopt (argc, argv, "D:f:hI:vV")) != EOF) {
- X#else
- X while ((ch = getopt (argc, argv, "cD:f:hHI:m:M:np:rRs:SuUvVzZ")) != EOF) {
- X#endif
- X switch (ch) {
- X case 'c':
- X catchup = TRUE;
- X update = TRUE;
- X break;
- X
- X case 'D': /* debug mode 1=NNTP 2=ALL */
- X#ifdef DEBUG
- X redirect_output[0] = '\0';
- X debug = atoi (optarg);
- X#else
- X error_message (txt_option_not_enabled, "-DDEBUG");
- X exit (1);
- X#endif
- X break;
- X
- X case 'f':
- X my_strncpy (newsrc, optarg, sizeof (newsrc));
- X break;
- X
- X case 'H':
- X show_intro_page ();
- X exit (1);
- X break;
- X
- X#if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
- X case 'I':
- X my_strncpy (indexdir, optarg, sizeof (indexdir));
- X mkdir (indexdir, 0777);
- X break;
- X#endif
- X case 'm':
- X my_strncpy (default_maildir, optarg, sizeof (default_maildir));
- X break;
- X
- X case 'M': /* mail new news to specified user */
- X my_strncpy (mail_news_user, optarg, sizeof (mail_news_user));
- X mail_news = TRUE;
- X update = TRUE;
- X catchup = TRUE;
- X break;
- X
- X case 'n':
- X notify_new_groups = TRUE;
- X break;
- X
- X case 'p':
- X my_strncpy (cmd_line_printer, optarg, sizeof (cmd_line_printer));
- X default_printer = FALSE;
- X break;
- X
- X case 'r': /* read news remotely from default NNTP server */
- X#ifdef NNTP_ABLE
- X read_news_via_nntp = TRUE;
- X#else
- X error_message (txt_option_not_enabled, "-DNNTP_ABLE");
- X exit (1);
- X#endif
- X break;
- X
- X case 'R': /* read news saved by -S option */
- X error_message ("%s: Option -R not yet implemented.", progname);
- X exit (1);
- X break;
- X
- X case 's':
- X my_strncpy (default_savedir, optarg, sizeof (default_savedir));
- X break;
- X
- X case 'S': /* save new news to dir structure */
- X save_news = TRUE;
- X update = TRUE;
- X break;
- X
- X case 'u': /* update index files */
- X update = TRUE;
- X break;
- X
- X case 'U': /* update index files in background */
- X update_fork = TRUE;
- X update = TRUE;
- X break;
- X
- X case 'v': /* verbose mode */
- X verbose = TRUE;
- X break;
- X
- X case 'V':
- X#if defined(__DATE__) && defined(__TIME__)
- X sprintf (msg, "Version: %s PL%d %s %s",
- X VERSION, PATCHLEVEL, __DATE__, __TIME__);
- X#else
- X sprintf (msg, "Version: %s PL%d",
- X VERSION, PATCHLEVEL);
- X#endif
- X error_message (msg, "");
- X exit (1);
- X break;
- X
- X case 'z':
- X start_any_unread = TRUE;
- X update = TRUE;
- X break;
- X
- X case 'Z':
- X check_any_unread = TRUE;
- X update = TRUE;
- X break;
- X
- X case 'h':
- X case '?':
- X default:
- X usage (progname);
- X exit (1);
- X }
- X }
- X}
- X
- X/*
- X * usage
- X */
- X
- Xvoid usage (progname)
- X char *progname;
- X{
- X#ifndef INDEX_DAEMON
- X error_message ("%s A threaded Netnews reader.\n", cvers);
- X#else
- X error_message ("%s Tin index file daemon.\n", cvers);
- X#endif
- X error_message ("Usage: %s [options] [newsgroups]", progname);
- X#ifndef INDEX_DAEMON
- X error_message (" -c mark all news as read in subscribed newsgroups (batch mode)", "");
- X#endif
- X error_message (" -f file subscribed to newsgroups file [default=%s]", newsrc);
- X error_message (" -h help", "");
- X#ifndef INDEX_DAEMON
- X error_message (" -H help information about %s", progname);
- X#endif
- X error_message (" -I dir index file directory [default=%s]", indexdir);
- X#ifndef INDEX_DAEMON
- X error_message (" -m dir mailbox directory [default=%s]", default_maildir);
- X error_message (" -M user mail new news to specified user (batch mode)", "");
- X error_message (" -n notify user of any newly created newsgroups", "");
- X error_message (" -p file print program with options [default=%s]", DEFAULT_PRINTER);
- X# if defined(NNTP_ABLE) && !defined(NNTP_ONLY)
- X if (! read_news_via_nntp) {
- X error_message (" -r read news remotely from default NNTP server", "");
- X }
- X# endif /* NNTP_ABLE */
- X error_message (" -R read news saved by -S option (not yet implemented)", "");
- X error_message (" -s dir save news directory [default=%s]", default_savedir);
- X error_message (" -S save new news for later reading (batch mode)", "");
- X# if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
- X error_message (" -u update index files (batch mode)", "");
- X error_message (" -U update index files in the background while reading news", "");
- X# endif /* NNTP_XINDEX */
- X#endif /* INDEX_DAEMON */
- X error_message (" -v verbose output for batch mode options", "");
- X#ifndef INDEX_DAEMON
- X error_message (" -z start if any unread news", "");
- X error_message (" -Z return status indicating if any unread news (batch mode)", "");
- X#endif
- X error_message ("\nMail bug reports/comments to %s", BUG_REPORT_ADDRESS);
- X}
- X
- X/*
- X * check/start if any new/unread articles
- X */
- X
- Xint check_for_any_new_news (check_any_unread, start_any_unread)
- X int check_any_unread;
- X int start_any_unread;
- X{
- X int i = 0;
- X
- X if (check_any_unread) {
- X i = check_start_save_any_news (CHECK_ANY_NEWS);
- X exit (i);
- X }
- X
- X if (start_any_unread) {
- X i = check_start_save_any_news (START_ANY_NEWS);
- X if (i == -1) { /* no new/unread news so exit */
- X exit (0);
- X }
- X update = FALSE;
- X }
- X return (i);
- X}
- X
- X/*
- X * mail any new articles to specified user
- X * or
- X * save any new articles to savedir structure for later reading
- X */
- X
- Xvoid save_or_mail_new_news ()
- X{
- X int i;
- X
- X if (mail_news || save_news) {
- X i = catchup; /* set catchup to FALSE */
- X catchup = FALSE;
- X do_update ();
- X catchup = i; /* set catchup to previous value */
- X if (mail_news) {
- X check_start_save_any_news (MAIL_ANY_NEWS);
- X } else {
- X check_start_save_any_news (SAVE_ANY_NEWS);
- X }
- X tin_done (0);
- X }
- X}
- X
- X/*
- X * update index files
- X */
- X
- Xvoid update_index_files ()
- X{
- X if (update || update_fork) {
- X if (read_news_via_nntp && xindex_supported) {
- X error_message ("%s: Updating of index files not supported", progname);
- X tin_done (1);
- X }
- X
- X COLS = 132; /* set because curses has not started */
- X if (update_fork) {
- X catchup = FALSE; /* turn off msgs when running forked */
- X verbose = FALSE;
- X switch (fork ()) { /* fork child to update indexes in background */
- X case -1: /* error forking */
- X perror_message ("Failed to start background indexing process", "");
- X break;
- X case 0: /* child process */
- X process_id = getpid ();
- X#ifdef BSD
- X setpgrp (0, process_id); /* reset process group leader to this process */
- X# ifdef TIOCNOTTY
- X {
- X int fd;
- X
- X if ((fd = open ("/dev/tty", O_RDWR)) >= 0) {
- X ioctl (fd, TIOCNOTTY, (char *) NULL);
- X close (fd);
- X }
- X }
- X# endif
- X#else
- X setpgrp ();
- X signal (SIGHUP, SIG_IGN); /* make immune from process group leader death */
- X#endif
- X signal (SIGQUIT, SIG_IGN); /* stop indexing being interrupted */
- X signal (SIGALRM, SIG_IGN); /* stop indexing resyning active file */
- X nntp_open (); /* connect server if we are using nntp */
- X thread_arts = FALSE; /* stop threading to run faster */
- X do_update ();
- X nntp_close (); /* connect server if we are using nntp */
- X exit (0);
- X break;
- X default: /* parent process*/
- X break;
- X }
- X update = FALSE;
- X } else {
- X thread_arts = FALSE; /* stop threading to run faster */
- X do_update ();
- X tin_done (0);
- X }
- X }
- X}
- X
- X/*
- X * display page of general info. for first time user.
- X */
- X
- Xvoid show_intro_page ()
- X{
- X if (cmd_line) {
- X wait_message (cvers);
- X } else {
- X ClearScreen ();
- X center_line (0, TRUE, cvers);
- X Raw (FALSE);
- X }
- X
- X printf ("\n\nWelcome to tin, a full screen threaded Netnews reader. It can read news locally\n");
- X printf ("(ie. <spool>/news) or remotely (-r option) from a NNTP (Network News Transport\n");
- X printf ("Protocol) server. tin -h lists the available command line options.\n\n");
- X
- X printf ("Tin has four newsreading levels, the newsgroup selection page, the group index\n");
- X printf ("page, the thread listing page and the article viewer. Help is available at each\n");
- X printf ("level by pressing the 'h' command.\n\n");
- X
- X printf ("Move up/down by using the terminal arrow keys or 'j' and 'k'. Use PgUp/PgDn or\n");
- X printf ("Ctrl-U and Ctrl-D to page up/down. Enter a newsgroup by pressing RETURN.\n\n");
- X
- X printf ("Articles, threads, tagged articles or articles matching a pattern can be mailed\n");
- X printf ("('m' command), printed ('o' command), saved ('s' command), piped ('|' command).\n");
- X printf ("Use the 'w' command to post a news article, the 'f'/'F' commands to post a\n");
- X printf ("follow-up to an existing news article and the 'r'/'R' commands to reply via\n");
- X printf ("mail to an existing news articles author. The 'M' command allows the operation\n");
- X printf ("of tin to be configured via a menu.\n\n");
- X
- X printf ("For more information read the manual page, README, INSTALL, TODO and FTP files.\n\n");
- X printf ("Please send bug reports/comments to the programs author with the 'B' command.\n");
- X fflush (stdout);
- X
- X if (! cmd_line) {
- X Raw (TRUE);
- X continue_prompt ();
- X }
- X}
- X
- END_OF_FILE
- if test 12528 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'signal.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'signal.c'\"
- else
- echo shar: Extracting \"'signal.c'\" \(10115 characters\)
- sed "s/^X//" >'signal.c' <<'END_OF_FILE'
- X/*
- X * Project : tin - a threaded Netnews reader
- X * Module : signal.c
- X * Author : I.Lea
- X * Created : 01-04-91
- X * Updated : 22-06-92
- X * Notes : signal handlers for different modes and window resizing
- X * Copyright : (c) Copyright 1991-92 by Iain Lea
- X * You may freely copy or redistribute this software,
- X * so long as there is no profit made from its use, sale
- X * trade or reproduction. You may not change this copy-
- X * right notice, and it must be included in any copy made
- X */
- X
- X#include "tin.h"
- X
- Xextern char *glob_art_group;
- Xextern char *glob_group;
- Xextern char *glob_page_group;
- Xextern char index_file[PATH_LEN];
- Xextern int glob_respnum;
- X
- Xstatic int time_remaining;
- X
- X#ifdef SIGTSTP
- Xint do_sigtstp = 0;
- X#endif
- X
- X
- X#ifdef POSIX_JOB_CONTROL
- X
- X/*
- X * for POSIX systems we know SIGTYPE is void
- X */
- X
- Xvoid (*sigdisp(sig, func))()
- X int sig;
- X void (*func)();
- X{
- X struct sigaction sa, osa;
- X
- X sa.sa_handler = func;
- X sigemptyset (&sa.sa_mask);
- X sa.sa_flags = 0;
- X#ifdef SA_RESTART
- X sa.sa_flags |= SA_RESTART;
- X#endif
- X if (sigaction (sig, &sa, &osa) < 0) {
- X return ((void (*)(int))(-1));
- X }
- X return (osa.sa_handler);
- X}
- X
- X#else
- X
- Xsigtype_t (*sigdisp(sig, func))()
- X int sig;
- X sigtype_t (*func)();
- X{
- X return (signal (sig, func));
- X}
- X
- X#endif
- X
- Xvoid set_signal_handlers ()
- X{
- X signal (SIGINT, signal_handler); /* ctrl-C */
- X signal (SIGQUIT, signal_handler); /* ctrl-\ */
- X signal (SIGHUP, signal_handler); /* hangup */
- X signal (SIGILL, signal_handler);
- X signal (SIGBUS, signal_handler); /* bus error */
- X signal (SIGSEGV, signal_handler); /* segmentation violation */
- X signal (SIGPIPE, SIG_IGN);
- X#ifdef SIGCHLD
- X signal (SIGCHLD, signal_handler); /* death of a child process */
- X#endif
- X#ifdef SIGPWR
- X signal (SIGPWR, signal_handler); /* powerfail */
- X#endif
- X#ifdef SIGWINCH
- X if (debug == 2) {
- X wait_message ("SIGWINCH setting signal...");
- X sleep (2);
- X }
- X signal (SIGWINCH, main_resize);
- X#endif
- X
- X#if defined(SIGTSTP) && ! defined(MINIX)
- X {
- X sigtype_t (*ptr)();
- X ptr = signal (SIGTSTP, SIG_DFL);
- X signal (SIGTSTP, ptr);
- X if (ptr != SIG_IGN) {
- X /*
- X * SIGTSTP is ignored when starting from shells
- X * without job-control
- X */
- X do_sigtstp = 1;
- X signal (SIGTSTP, main_suspend);
- X }
- X }
- X#endif
- X}
- X
- X
- Xvoid set_alarm_signal ()
- X{
- X#ifndef NO_RESYNC_ACTIVE_FILE
- X /*
- X * Only reread active file if news is not static (ie. CD-ROM)
- X */
- X if (strcmp (spooldir_alias, "news") == 0) {
- X signal (SIGALRM, signal_handler);
- X alarm (RESYNC_ACTIVE_SECS);
- X }
- X reread_active_file = FALSE;
- X#endif
- X}
- X
- X
- Xvoid set_alarm_clock_on ()
- X{
- X#ifndef NO_RESYNC_ACTIVE_FILE
- X alarm (time_remaining);
- X#endif
- X}
- X
- X
- Xvoid set_alarm_clock_off ()
- X{
- X#ifndef NO_RESYNC_ACTIVE_FILE
- X time_remaining = alarm (0);
- X#endif
- X}
- X
- X
- Xvoid signal_handler (sig)
- X int sig;
- X{
- X char *sigtext;
- X#ifdef SIGCHLD
- X int wait_status = 1;
- X#endif
- X
- X switch (sig) {
- X case SIGINT:
- X if (update) {
- X sigtext = "SIGINT ";
- X } else {
- X signal (SIGINT, signal_handler);
- X return;
- X }
- X break;
- X case SIGQUIT:
- X sigtext = "SIGQUIT ";
- X break;
- X case SIGHUP:
- X sigtext = "SIGHUP ";
- X break;
- X#ifdef SIGCHLD
- X case SIGCHLD:
- X wait (&wait_status);
- X# ifdef WEXITSTATUS
- X system_status = WEXITSTATUS(wait_status);
- X# endif
- X return;
- X#endif
- X#ifdef SIGPWR
- X case SIGPWR:
- X sigtext = "SIGPWR ";
- X break;
- X#endif
- X case SIGBUS:
- X sigtext = "SIGBUS ";
- X break;
- X case SIGSEGV:
- X sigtext = "SIGSEGV ";
- X break;
- X#ifndef NO_RESYNC_ACTIVE_FILE
- X case SIGALRM:
- X set_alarm_signal ();
- X reread_active_file = TRUE;
- X return;
- X#endif
- X default:
- X sigtext = "";
- X break;
- X }
- X Raw (FALSE);
- X EndWin ();
- X fprintf (stderr, "\n%s: signal handler caught signal %s(%d).\n",
- X progname, sigtext, sig);
- X if (sig == SIGBUS || sig == SIGSEGV) {
- X fprintf (stderr, "%s: send a bug report to %s%s\n",
- X progname, BUG_REPORT_ADDRESS, add_addr);
- X }
- X fflush (stderr);
- X
- X if (read_news_via_nntp && xindex_supported) {
- X unlink (index_file);
- X }
- X
- X#ifdef INDEX_DAEMON
- X unlink (LOCK_FILE);
- X#endif
- X exit (1);
- X}
- X
- X
- Xint set_win_size (num_lines, num_cols)
- X int *num_lines;
- X int *num_cols;
- X{
- X int old_lines;
- X int old_cols;
- X#ifdef TIOCGSIZE
- X struct ttysize win;
- X#else
- X# ifdef TIOCGWINSZ
- X struct winsize win;
- X# endif
- X#endif
- X
- X old_lines = *num_lines;
- X old_cols = *num_cols;
- X
- X init_screen_array (FALSE); /* deallocate screen array */
- X
- X#ifdef TIOCGSIZE
- X if (ioctl (0, TIOCGSIZE, &win) == 0) {
- X if (win.ts_lines != 0) {
- X *num_lines = win.ts_lines - 1;
- X }
- X if (win.ts_cols != 0) {
- X *num_cols = win.ts_cols;
- X }
- X }
- X#else
- X# ifdef TIOCGWINSZ
- X if (ioctl (0, TIOCGWINSZ, &win) == 0) {
- X if (win.ws_row != 0) {
- X *num_lines = win.ws_row - 1;
- X }
- X if (win.ws_col != 0) {
- X *num_cols = win.ws_col;
- X }
- X }
- X# endif
- X#endif
- X
- X init_screen_array (TRUE); /* allocate screen array for resize */
- X
- X set_subj_from_size (*num_cols);
- X
- X RIGHT_POS = *num_cols - 20;
- X MORE_POS = *num_cols - 15;
- X NOTESLINES = *num_lines - INDEX_TOP - 1;
- X if (NOTESLINES <= 0) {
- X NOTESLINES = 1;
- X }
- X
- X if (*num_lines != old_lines || *num_cols != old_cols) {
- X return TRUE;
- X } else {
- X return FALSE;
- X }
- X}
- X
- X
- X
- Xvoid set_signals_art ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, art_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, art_resize);
- X#endif
- X}
- X
- X
- Xvoid set_signals_group ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, group_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, group_resize);
- X#endif
- X}
- X
- X
- Xvoid set_signals_page ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, page_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, page_resize);
- X#endif
- X}
- X
- X
- Xvoid set_signals_select ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, select_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, select_resize);
- X#endif
- X}
- X
- X
- Xvoid set_signals_spooldir ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, spooldir_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, spooldir_resize);
- X#endif
- X}
- X
- X
- Xvoid set_signals_thread ()
- X{
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X sigdisp (SIGTSTP, thread_suspend);
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, thread_resize);
- X#endif
- X}
- X
- X
- X#ifdef SIGTSTP
- X
- X/* ARGSUSED0 */
- Xvoid art_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, art_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X art_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid main_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, main_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X main_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid select_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, select_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X select_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid spooldir_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, spooldir_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X spooldir_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid group_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, group_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X group_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid page_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, page_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X page_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid thread_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, thread_suspend);
- X
- X if (! update) {
- X Raw (TRUE);
- X thread_resize (0);
- X }
- X set_keypad_on ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid rcfile_suspend (sig)
- X int sig;
- X{
- X set_keypad_off ();
- X Raw (FALSE);
- X wait_message (txt_suspended_message);
- X
- X kill (0, SIGSTOP);
- X
- X sigdisp (SIGTSTP, rcfile_suspend);
- X
- X Raw (TRUE);
- X set_keypad_on ();
- X show_rcfile_menu ();
- X}
- X
- X#endif /* SIGTSTP */
- X
- X
- X/* ARGSUSED0 */
- Xvoid art_resize (sig)
- X int sig;
- X{
- X char buf[LEN];
- X
- X#ifdef SIGWINCH
- X (void) set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, art_resize);
- X#endif
- X mail_setup ();
- X ClearScreen ();
- X sprintf (buf, txt_group, glob_art_group);
- X wait_message (buf);
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid main_resize (sig)
- X int sig;
- X{
- X#ifdef SIGWINCH
- X (void) set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, main_resize);
- X#endif
- X mail_setup ();
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid select_resize (sig)
- X int sig;
- X{
- X int resized = TRUE;
- X
- X#ifdef SIGWINCH
- X resized = set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, select_resize);
- X#endif
- X
- X#ifndef USE_CLEARSCREEN
- X ClearScreen ();
- X#endif
- X mail_setup ();
- X if (resized) {
- X group_selection_page ();
- X }
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid spooldir_resize (sig)
- X int sig;
- X{
- X int resized = TRUE;
- X
- X#ifdef SIGWINCH
- X resized = set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, spooldir_resize);
- X#endif
- X
- X#ifndef USE_CLEARSCREEN
- X ClearScreen ();
- X#endif
- X mail_setup ();
- X if (resized) {
- X show_spooldir_page ();
- X }
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid group_resize (sig)
- X int sig;
- X{
- X int resized = TRUE;
- X
- X#ifdef SIGWINCH
- X resized = set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, group_resize);
- X#endif
- X
- X#ifndef USE_CLEARSCREEN
- X ClearScreen ();
- X#endif
- X mail_setup ();
- X if (resized) {
- X show_group_page (glob_group);
- X }
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid page_resize (sig)
- X int sig;
- X{
- X int resized = TRUE;
- X
- X#ifdef SIGWINCH
- X resized = set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, page_resize);
- X#endif
- X
- X#ifndef USE_CLEARSCREEN
- X ClearScreen ();
- X#endif
- X mail_setup ();
- X if (resized) {
- X redraw_page (glob_respnum, glob_page_group);
- X }
- X}
- X
- X
- X/* ARGSUSED0 */
- Xvoid thread_resize (sig)
- X int sig;
- X{
- X int resized = TRUE;
- X
- X#ifdef SIGWINCH
- X resized = set_win_size (&LINES, &COLS);
- X signal (SIGWINCH, thread_resize);
- X#endif
- X
- X#ifndef USE_CLEARSCREEN
- X ClearScreen ();
- X#endif
- X mail_setup ();
- X if (resized) {
- X show_thread_page ();
- X }
- X}
- END_OF_FILE
- if test 10115 -ne `wc -c <'signal.c'`; then
- echo shar: \"'signal.c'\" unpacked with wrong size!
- fi
- # end of 'signal.c'
- fi
- echo shar: End of archive 13 \(of 15\).
- cp /dev/null ark13isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 15 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-