From: frank.kaefer@stasys.sta.sub.org (Frank Kaefer)
Newsgroups: de.comp.sources.os9,comp.os.os9
Subject: Tass for OS-9 Part03/03
Date: 24 Dec 92 13:05:53 GMT
Followup-To: de.comp.sources.d
Organization: Stasys News Server, Starnberg, Germany
NNTP-Posting-Host: stasys.sta.sub.org

Submitted-by: Ulrich Dessauer <ud@Nightmare.ddt.sub.org>
Archive-name: tass/part03

: ----- Cut here ----- Cut here ----- Cut here ----- Cut here -----
: Use  sh filename  to extract shell archive
: This shell archive contains following files:
:     'prompt.c                                     2308 bytes'
:     'screen.c                                      729 bytes'
:     'select.c                                    13169 bytes'
:     'sigs.c                                       1277 bytes'
:     'tass.h                                       3575 bytes'
:     'time.c                                       1094 bytes'
: 
if test -f 'prompt.c' ; then
  echo 'File prompt.c already exists, overwriting it'
  del 'prompt.c'
fi
echo Extracting \"'prompt.c'\"
sed "s/^X//" >'prompt.c' <<'__END__OF__THIS__FILE__'
X
X#include	<stdio.h>
X#include	"tass.h"
X
X
X/*
X *  parse_num
X *  get a number from the user
X *  Return -1 if missing or bad number typed
X */
X
Xparse_num(ch, prompt)
Xchar ch;
Xchar *prompt;
X{
X	char buf[40];
X	int len;
X	int i;
X	int num;
X
X	MoveCursor(LINES,0);
X	printf("%s %c",prompt,ch);
X	fflush(stdout);
X	buf[0] = ch;
X	buf[1] = '\0';
X	len = 1;
X	ch = ReadCh();
X	while (ch != '\n'&& ch != '\r') {
X		if (ch >= '0' && ch <= '9' && len < 4) {
X			buf[len++] = ch;
X			buf[len] = '\0';
X			putchar(ch);
X		} else if (ch == 8 || ch == 127) {
X			if (len) {
X				len--;
X				buf[len] = '\0';
X				putchar('\b');
X				putchar(' ');
X				putchar('\b');
X			} else {
X				MoveCursor(LINES, 0);
X				CleartoEOLN();
X				return(-1);
X			}
X		} else if (ch == 21) {	/* control-U	*/
X			for (i = len;i>0;i--) {
X				putchar('\b');
X				putchar(' ');
X				putchar('\b');
X			}
X			buf[0] = '\0';
X			len = 0;
X		} else
X			putchar(7);
X		fflush(stdout);
X		ch = ReadCh();
X	}
X
X	MoveCursor(LINES, 0);
X	CleartoEOLN();
X
X	if (len) {
X		num = atoi(buf);
X		return(num);
X	} else
X		return(-1);
X}
X
X
X/*
X *  parse_string
X *  get a string from the user
X *  Return TRUE if a valid string was typed, FALSE otherwise
X */
X
Xparse_string(prompt, buf)
Xchar *prompt;
Xchar *buf;
X{
Xint len;
Xint i;
Xchar ch;
X
X	clear_message();
X	MoveCursor(LINES,0);
X	printf("%s", prompt);
X	fflush(stdout);
X	buf[0] = '\0';
X	len = 0;
X	ch = ReadCh();
X	while (ch != '\n' && ch != '\r') {
X		if (ch >= ' ' && len < 60) {
X			buf[len++] = ch;
X			buf[len] = '\0';
X			putchar(ch);
X		} else if (ch == 8 || ch == 127) {
X			if (len) {
X				len--;
X				buf[len] = '\0';
X				putchar('\b');
X				putchar(' ');
X				putchar('\b');
X			} else {
X				MoveCursor(LINES, 0);
X				CleartoEOLN();
X				return(FALSE);
X			}
X		} else if (ch == 21) {	/* control-U	*/
X			for (i = len;i>0;i--) {
X				putchar('\b');
X				putchar(' ');
X				putchar('\b');
X			}
X			buf[0] = '\0';
X			len = 0;
X		} else
X			putchar(7);
X		fflush(stdout);
X		ch = ReadCh();
X	}
X	MoveCursor(LINES,0);
X	CleartoEOLN();
X
X	return TRUE;
X}
X
X
Xprompt_yn(prompt)
Xchar *prompt;
X{
X	char ch;
X
X	clear_message();
X	MoveCursor(LINES,0);
X	printf("%s", prompt);
X	fflush(stdout);
X
X	ch = ReadCh();
X	clear_message();
X
X	if (ch == 'y' || ch == 'Y')
X		return TRUE;
X
X	return FALSE;
X}
X
X
Xcontinue_prompt() {
X
X	printf("-Hit return to continue-");
X	fflush(stdout);
X	while (ReadCh() != '\n') ;
X}
X
X
__END__OF__THIS__FILE__
if test -f 'screen.c' ; then
  echo 'File screen.c already exists, overwriting it'
  del 'screen.c'
fi
echo Extracting \"'screen.c'\"
sed "s/^X//" >'screen.c' <<'__END__OF__THIS__FILE__'
X
X#include	<stdio.h>
X#include	"tass.h"
X
X
X
Xinfo_message(msg)
Xchar *msg;
X{
X	clear_message();	  /* Clear any old messages hanging around */
X	center_line(LINES, msg);  /* center the message at screen bottom  */
X	MoveCursor(LINES, 0);
X}
X
X
Xclear_message()
X{
X	MoveCursor(LINES, 0);
X	CleartoEOLN();
X}
X
X
Xcenter_line(line, str)
Xint line;
Xchar *str;
X{
Xint pos;
X
X	pos = (COLS - strlen(str)) / 2;
X	MoveCursor(line, pos);
X	printf("%s", str);
X	fflush(stdout);
X}
X
X
Xdraw_arrow(line)
Xint line;
X{
X	MoveCursor(line, 0);
X	printf("->");
X	fflush(stdout);
X	MoveCursor(LINES, 0);
X}
X
Xerase_arrow(line)
Xint line;
X{
X	MoveCursor(line, 0);
X	printf("  ");
X	fflush(stdout);
X}
X
X#ifdef	REGEXP
Xvoid
Xregerror (s)
Xchar *s;
X{
X	info_message (s);
X}
X#endif	/* REGEXP */
X
__END__OF__THIS__FILE__
if test -f 'select.c' ; then
  echo 'File select.c already exists, overwriting it'
  del 'select.c'
fi
echo Extracting \"'select.c'\"
sed "s/^X//" >'select.c' <<'__END__OF__THIS__FILE__'
X
X#include	<stdio.h>
X#include	<signal.h>
X#ifdef	REGEXP
X#include	<regexp.h>
X#endif	/* REGEXP */
X#include	"tass.h"
X
X
Xint first_group_on_screen;
Xint last_group_on_screen;
Xint cur_groupnum = 0;
Xextern int index_point;
Xint space_mode;
Xextern char *cvers;
X
Xchar group_search_string[LEN+1];
X
X
X
X#ifdef SIGTSTP
Xvoid
Xselect_susp(i)
Xint i;
X{
X
X	Raw(FALSE);
X	putchar('\n');
X	signal(SIGTSTP, SIG_DFL);
X	kill(0, SIGTSTP);
X
X	signal(SIGTSTP, select_susp);
X	Raw(TRUE);
X	mail_setup();
X	group_selection_page(-1, FALSE);
X}
X#endif
X
X
Xselection_index()
X{
X	char ch;
X	int n;
X	int i;
X	char buf[200];
X
X	group_selection_page(-1, FALSE);	/* display group selection page */
X
X	while (1) {
X		if ((n = ReadCh()) == EOF)
X			longjmp (jmp_buffer, 1);
X		ch = (char) n;
X	
X		if (ch > '0' && ch <= '9') {
X			prompt_group_num(ch);
X		} else switch (ch) {
X			case 'c':	/* catchup--mark all articles as read */
X			    if (prompt_yn("Mark group as read? (y/n): ")) {
X				unread[cur_groupnum] = 0;
X				mark_group_read(
X					    active[my_group[cur_groupnum]].name,
X					    my_group[cur_groupnum]);
X				group_selection_page(cur_groupnum, TRUE);
X			    }
X			    break;
X
X			case ctrl('K'):
X				if (local_top <= 0) {
X					info_message("No groups to delete");
X					break;
X				}
X
X				delete_group(
X					active[my_group[cur_groupnum]].name);
X				active[my_group[cur_groupnum]].flag = NOTGOT;
X
X				local_top--;
X				for (i = cur_groupnum; i < local_top; i++) {
X					my_group[i] = my_group[i+1];
X					unread[i] = unread[i+1];
X				}
X				if (cur_groupnum >= local_top)
X					cur_groupnum = local_top - 1;
X
X				group_selection_page(cur_groupnum, FALSE);
X				break;
X
X			case ctrl('Y'):
X				undel_group();
X				group_selection_page(cur_groupnum, FALSE);
X				break;
X
X			case 'I':		/* toggle inverse video */
X				inverse_okay = !inverse_okay;
X				if (inverse_okay)
X					info_message("Inverse video enabled");
X				else
X					info_message("Inverse video disabled");
X				break;
X
X			case ctrl('R'):	/* reset .newsrc */
X			    if (prompt_yn("Reset newsrc? (y/n): ")) {
X				reset_newsrc();
X				cur_groupnum = 0;
X				group_selection_page(-1, FALSE);
X			    }
X			    break;
X
X			case '$':	/* reread .newsrc, no unsub groups */
X				cur_groupnum = 0;
X				local_top = 0;
X				for (i = 0; i < num_active; i++)
X					active[i].flag = NOTGOT;
X				read_newsrc(TRUE);
X				group_selection_page(-1, FALSE);
X				break;
X
X			case 's':	/* subscribe to current group */
X			    MoveCursor(INDEX_TOP +
X				(cur_groupnum-first_group_on_screen), 3);
X			    putchar(' ');
X			    fflush(stdout);
X			    MoveCursor(LINES, 0);
X
X			    subscribe(active[my_group[cur_groupnum]].name,
X					':', my_group[cur_groupnum], FALSE);
X			    sprintf(buf, "subscribed to %s",
X					active[my_group[cur_groupnum]].name);
X			    info_message(buf);
X			    break;
X
X			case 'u':	/* unsubscribe to current group */
X			    MoveCursor(INDEX_TOP +
X				(cur_groupnum-first_group_on_screen), 3);
X			    putchar('u');
X			    fflush(stdout);
X			    MoveCursor(LINES, 0);
X
X			    subscribe(active[my_group[cur_groupnum]].name,
X					'!', my_group[cur_groupnum], FALSE);
X			    sprintf(buf, "unsubscribed to %s",
X					active[my_group[cur_groupnum]].name);
X			    info_message(buf);
X			    break;
X
X			case ' ':
X				clear_message();
X				break;
X
X			case '\t':
X				for (i = cur_groupnum; i < local_top; i++)
X					if (unread[i] != 0)
X						break;
X				if (i >= local_top) {
X					info_message("No more groups to read");
X					break;
X				}
X
X				erase_group_arrow();
X				cur_groupnum = i;
X				if (cur_groupnum >= last_group_on_screen)
X					group_selection_page(-1, FALSE);
X				else
X					draw_group_arrow();
X				space_mode = TRUE;
X				goto go_into_group;
X
X			case 'g':	/* prompt for a new group name */
X				n = choose_new_group();
X				if (n >= 0) {
X					erase_group_arrow();
X					cur_groupnum = n;
X					if (cur_groupnum < first_group_on_screen
X					|| cur_groupnum >= last_group_on_screen)
X						group_selection_page(-1, FALSE);
X					else
X						draw_group_arrow();
X				}
X				break;
X
X#ifdef	USE_ARROW
X			case 27:	/* (ESC) common arrow keys */
X				ch = ReadCh();
X				if (ch == '[' || ch == 'O')
X					ch = ReadCh();
X				switch (ch) {
X				case 'A':
X				case 'D':
X				case 'i':
X					goto select_up;
X
X				case 'B':
X				case 'I':
X				case 'C':
X					goto select_down;
X				}
X				break;
X#endif	/* USE_ARROW */
X
X			case 'y':	/* pull in rest of groups from active */
X				n = local_top;
X				for (i = 0; i < num_active; i++)
X					active[i].flag = NOTGOT;
X				read_newsrc(FALSE);
X				for (i = 0; i < num_active; i++)
X					if (active[i].flag & NOTGOT) {
X						active[i].flag &= ~NOTGOT;
X						my_group[local_top] = i;
X						unread[local_top] = -1;
X						local_top++;
X					}
X				if (n < local_top) {
X					sprintf(buf, "Added %d group%s",
X						local_top - n,
X						local_top - n == 1 ? "" : "s");
X					group_selection_page(-1, FALSE);
X					info_message(buf);
X				} else
X				    info_message("No more groups to yank in");
X				break;
X
X			case ctrl('U'):		/* page up */
X			case ctrl('Z'):		/* full page up */
X				erase_group_arrow();
X				cur_groupnum -= (ch == ctrl('Z')) ?
X						NOTESLINES :
X						NOTESLINES / 2;
X				if (cur_groupnum < 0)
X					cur_groupnum = 0;
X				if (cur_groupnum < first_group_on_screen
X				||  cur_groupnum >= last_group_on_screen)
X					group_selection_page(-1, FALSE);
X				else
X					draw_group_arrow();
X				break;
X
X			case ctrl('D'):		/* page down */
X			case ctrl('V'):		/* full page down */
X				erase_group_arrow();
X				cur_groupnum += (ch == ctrl ('V')) ?
X						NOTESLINES :
X						NOTESLINES / 2;
X				if (cur_groupnum >= local_top)
X					cur_groupnum = local_top - 1;
X
X				if (cur_groupnum <= first_group_on_screen
X				||  cur_groupnum >= last_group_on_screen)
X					group_selection_page(-1, FALSE);
X				else
X					draw_group_arrow();
X				break;
X
X			case '!':
X				shell_escape();
X				group_selection_page(-1, FALSE);
X				break;
X
X			case 'v':
X				info_message(cvers);
X				break;
X
X			case ctrl('N'):		/* line down */
X			case 'j':
X#ifdef	USE_ARROW
Xselect_down:
X#endif	/* USE_ARROW */
X				if (cur_groupnum + 1 >= local_top)
X					break;
X
X				if (cur_groupnum + 1 >= last_group_on_screen) {
X					cur_groupnum++;
X					group_selection_page(-1, FALSE);
X				} else {
X					erase_group_arrow();
X					cur_groupnum++;
X					draw_group_arrow();
X				}
X				break;
X
X			case ctrl('P'):		/* line up */
X			case 'k':
X#ifdef	USE_ARROW
Xselect_up:
X#endif	/* USE_ARROW */
X				if (!cur_groupnum)
X					break;
X
X				if (cur_groupnum <= first_group_on_screen) {
X					cur_groupnum--;
X					group_selection_page(-1, FALSE);
X				} else {
X					erase_group_arrow();
X					cur_groupnum--;
X					draw_group_arrow();
X				}
X				break;
X
X			case 't':		/* redraw */
X			case ctrl('W'):
X			case ctrl('L'):
X				group_selection_page(-1, FALSE);
X				break;
X
X#ifndef	OSK
X			case '\r':	/* go into group */
X#else	/* OSK */
X			case '\l':	/* go into group */
X#endif	/* OSK */
X			case '\n':
X			case ctrl('F'):	/* cursor key */
X				space_mode = FALSE;
Xgo_into_group:
X				clear_message();
X				index_point = -1;
X				do {
X					group_page(
X					  active[my_group[cur_groupnum]].name);
X				} while (index_point == -3);
X				group_selection_page(-1, FALSE);
X				break;
X
X			case '/':	/* search forward */
X				search_group(TRUE);
X				break;
X
X			case '?':	/* search backward */
X				search_group(FALSE);
X				break;
X
X			case 'q':	/* quit */
X			case ctrl('B'):	/* cursor key */
X				tass_done(0);
X
X			case 'h':
X				tass_select_help();
X				group_selection_page(-1, FALSE);
X				break;
X
X			default:
X			    info_message("Bad command.  Type 'h' for help.");
X		}
X	}
X}
X
X
Xgroup_selection_page(ind, justone) 
Xint ind;
Xint justone;
X{
X	int i;
X	int n;
X	char new[10];
X	char subs;
X
X#ifdef SIGTSTP
X	signal(SIGTSTP, select_susp);
X#endif
X
X	if (ind < 0) {
X		ClearScreen();
X		printf("%s\r\012", nice_time()); /* print time in upper left */
X	}
X
X	show_mail ();
X
X	if (ind < 0)
X		center_line(1, "Group Selection");
X	MoveCursor(INDEX_TOP, 0);
X
X	first_group_on_screen = (cur_groupnum / NOTESLINES) * NOTESLINES;
X
X	last_group_on_screen = first_group_on_screen + NOTESLINES;
X	if (last_group_on_screen >= local_top)
X		last_group_on_screen = local_top;
X
X	for (i = first_group_on_screen; i < last_group_on_screen; i++) {
X		if ((ind >= 0) && (ind > i))
X			continue;
X		switch (unread[i]) {
X		case -2:
X			strcpy(new, "?   ");
X			break;
X
X		case -1:
X			strcpy(new, "-   ");
X			break;
X
X		case 0:
X			strcpy(new, "    ");
X			break;
X
X		default:
X			sprintf(new, "%-4d", unread[i]);
X		}
X
X		n = my_group[i];
X		if (active[n].flag & SUBS)	/* subscribed? */
X			subs = ' ';
X		else
X			subs = 'u';	/* u next to unsubscribed groups */
X
X		MoveCursor (INDEX_TOP + i - first_group_on_screen, 3);
X		printf("%c %4d", subs, i+1);
X		if (!justone)
X			printf (" %s", active[n].name);
X		MoveCursor (INDEX_TOP + i - first_group_on_screen, COLS - 8);
X		printf (" %s", new);
X		CleartoEOLN ();
X		if ((ind >= 0) && justone && (ind == i))
X			break;
X	}
X
X	if (last_group_on_screen < first_group_on_screen + NOTESLINES) {
X		MoveCursor (INDEX_TOP + last_group_on_screen + 1 - first_group_on_screen, 0);
X		CleartoEOLN ();
X	}
X
X	draw_group_arrow();
X}
X
X
Xprompt_group_num(ch)
Xchar ch;
X{
Xint num;
X
X	clear_message();
X
X	if ((num = parse_num(ch, "Select group> ")) == -1) {
X		clear_message();
X		return FALSE;
X	}
X	num--;		/* index from 0 (internal) vs. 1 (user) */
X
X	if (num >= local_top)
X		num = local_top - 1;
X
X	if (num >= first_group_on_screen
X	&&  num < last_group_on_screen) {
X		erase_group_arrow();
X		cur_groupnum = num;
X		draw_group_arrow();
X	} else {
X		cur_groupnum = num;
X		group_selection_page(-1, FALSE);
X	}
X
X	return TRUE;
X}
X
Xerase_group_arrow() {
X	erase_arrow(INDEX_TOP + (cur_groupnum-first_group_on_screen) );
X}
X
Xdraw_group_arrow() {
X	draw_arrow(INDEX_TOP + (cur_groupnum-first_group_on_screen) );
X}
X
Xvoid
Xsearch_group(forward)
Xint forward;
X{
X	char buf[LEN+1];
X	int i;
X#ifndef	REGEXP
X	extern char *regcmp();
X	extern char *regex();
X	char *re;
X#else	/* REGEXP */
X	regexp *re;
X#endif	/* REGEXP */
X	char *prompt;
X
X	clear_message();
X
X	if (forward)
X		prompt = "/";
X	else
X		prompt = "?";
X
X	if (!parse_string(prompt, buf))
X		return;
X
X	if (strlen(buf))
X		strcpy(group_search_string, buf);
X	else if (!strlen(group_search_string)) {
X		info_message("No search pattern");
X		return;
X	}
X
X	i = cur_groupnum;
X
X	glob_name(group_search_string, buf);
X
X#ifndef	REGEXP
X	if ((re = regcmp(buf, NULL)) == NULL) {
X#else	/* REGEXP */
X	if ((re = regcomp (buf)) == NULL) {
X#endif	/* REGEXP */
X		info_message("Bad search pattern");
X		return;
X	}
X
X	do {
X		if (forward)
X			i++;
X		else
X			i--;
X
X		if (i >= local_top)
X			i = 0;
X		if (i < 0)
X			i = local_top - 1;
X
X#ifndef	REGEXP
X		if (regex(re, active[my_group[i]].name) != NULL) {
X#else	/* REGEXP */
X		if (regexec (re, active[my_group[i]].name)) {
X#endif	/* REGEXP */
X			if (i >= first_group_on_screen
X			&&  i < last_group_on_screen) {
X				erase_group_arrow();
X				cur_groupnum = i;
X				draw_group_arrow();
X			} else {
X				cur_groupnum = i;
X				group_selection_page(-1, FALSE);
X			}
X			return;
X		}
X	} while (i != cur_groupnum);
X
X	info_message("No match");
X}
X
X
Xtass_select_help() {
X
X	ClearScreen();
X	center_line(0, TASS_HEADER);
X	center_line(1, "Group Selection Commands");
X
X	MoveCursor(3, 0);
X
X	printf("4        Select group 4\r\012");
X	printf("^D, ^V   half / full Page down\r\012");
X	printf("^R       Reset .newsrc\r\012");
X	printf("^U, ^Z   half / full Page up\r\012");
X	printf("^K       Delete group\r\012");
X	printf("^Y       Undelete group\r\012");
X	printf("<CR>     Read current group\r\012");
X	printf("<TAB>    View next unread group\r\012");
X	printf("c        Mark group as all read\r\012");
X	printf("g        Choose a new group by name\r\012");
X	printf("j        Down a line\r\012");
X	printf("k        Up a line\r\012");
X	printf("q        Quit\r\012");
X	printf("s        Subscribe to current group\r\012");
X	printf("u        Unsubscribe to current group\r\012");
X	printf("y        Yank in groups that are not in the .newsrc\r\012");
X	printf("$        Reread group list from .newsrc\r\012");
X	printf("/        Search forward for group\r\012");
X	printf("?        Search backward for group\r\012");
X
X	center_line(LINES, "-- hit any key --");
X	ReadCh();
X}
X
X
Xchoose_new_group() {
X	char buf[LEN+1];
X	char *p;
X	int ret;
X
X	if (!parse_string("Newsgroup> ", buf))
X		return -1;
X
X	for (p = buf; *p && (*p == ' ' || *p == '\t'); p++) ;
X	if (*p == '\0')
X		return -1;
X
X	ret = add_group(p, TRUE);
X	if (ret < 0)
X		info_message("Group not found in active file");
X
X	return ret;
X}
X
X
X/*
X *  Add a group to the selection list (my_group[])
X *  Return the index of my_group[] if group is added or was already
X *  there.  Return -1 if named group is not in active[].
X */
X
Xadd_group(s, get_unread)
Xchar *s;
Xint get_unread;			/* look in .newsrc for sequencer unread info? */
X{
X	long h;
X	int i, j;
X
X	{			/* find the hash of the group name */
X		char *t = s;
X
X		h = *t++;
X		while (*t)
X			h = (h * 64 + *t++) % TABLE_SIZE;
X	}
X
X	for (i = group_hash[h]; i >= 0; i = active[i].next)
X		if (strcmp(s, active[i].name) == 0) {
X			for (j = 0; j < local_top; j++)
X				if (my_group[j] == i)
X					return j;
X
X			active[i].flag &= ~NOTGOT;   /* mark that we got it */
X			my_group[local_top] = i;
X
X			if (get_unread)
X				unread[local_top] = get_line_unread(s, i);
X			else
X				unread[local_top] = -2;
X
X			local_top++;
X			return local_top - 1;
X		}
X
X	return -1;
X}
X
X
__END__OF__THIS__FILE__
if test -f 'sigs.c' ; then
  echo 'File sigs.c already exists, overwriting it'
  del 'sigs.c'
fi
echo Extracting \"'sigs.c'\"
sed "s/^X//" >'sigs.c' <<'__END__OF__THIS__FILE__'
X#include	<stdio.h>
X#include	"tass.h"
X
X#ifdef	APPEND_SIG
X#ifdef	RAND_SIG
Xstatic void
Xrandom_signature (buf, fpo, cnt)
Xchar *buf;
XFILE *fpo;
Xint cnt;
X{
X	static int	first = 1;
X	FILE		*fp;
X	char		inp[130];
X	int		n;
X
X	sprintf (buf, "%s/.randsig", homedir);
X	if (! (fp = fopen (buf, "r")))
X		return;
X	if (first) {
X		srandom (time (0));
X		first = 0;
X	}
X	n = _gs_size (fileno (fp));
X	n = random () % 
X		((n > (1 << 9)) ?
X			(n >> 7) :
X			((n > (1 << 5)) ?
X				(n >> 3) :
X				10));
X	while (n-- > 0) {
X		while (fgets (inp, 128, fp))
X			if (! strcmp (inp, "%%\n"))
X				break;
X		if (feof (fp)) {
X			clearerr (fp);
X			cleareof (fp);
X			rewind (fp);
X			continue;
X		}
X	}
X	while (fgets (inp, 128, fp) && (cnt-- > 0))
X		if (strcmp (inp, "%%\n"))
X			fputs (inp, fpo);
X		else
X			break;
X	fclose (fp);
X}
X#endif	/* RAND_SIG */
X		
Xvoid
Xadd_signature (fp)
XFILE *fp;
X{
X	extern char	*malloc ();
X	static char	*fn = NULL;
X	FILE		*fpi;
X	int		cnt;
X
X	if (!fn) {
X		if (!(fn = malloc (250)))
X			return;
X	}
X	sprintf (fn, "%s/.signature", homedir);
X	cnt = 4 * 400;
X	if (fpi = fopen (fn, "r")) {
X		putc ('\n', fp);
X		while (fgets (fn, 200, fpi) && (cnt-- > 0))
X			fputs (fn, fp);
X		fclose (fpi);
X	}
X#ifdef	RAND_SIG
X	if (cnt > 0)
X		random_signature (fn, fp, cnt);
X#endif	/* RAND_SIG */
X}
X#endif	/* APPEND_SIG */
X
X
__END__OF__THIS__FILE__
if test -f 'tass.h' ; then
  echo 'File tass.h already exists, overwriting it'
  del 'tass.h'
fi
echo Extracting \"'tass.h'\"
sed "s/^X//" >'tass.h' <<'__END__OF__THIS__FILE__'
X#include	<setjmp.h>
X
X#ifndef		OSK
X#define		LIBDIR		"/usr/lib/news"
X#define		SPOOLDIR	"/usr/spool/news"
X#define		MAILER		"/bin/rmail"
X#else		/* OSK */
X#define		LIBDIR		"/h0/USR/LIB/NEWS"
X#define		SPOOLDIR	"/h0/SPOOL/NEWS"
X#define		MAILER		"rmail"
X#ifdef		USE_UID
X#define		setgid(n)	/* */
X#endif		/* USE_UID */
X#endif		/* OSK */
X
X#ifndef		TRUE
X#define		TRUE		1
X#define		FALSE		0
X#endif		/* TRUE */
X
X#define		LEN		200
X
X#define		INDEX_TOP		4
X#define		NOTESLINES		(LINES - INDEX_TOP - 2)
X#define		RIGHT_POS		(COLS - 16)
X#define		MORE_POS		(COLS - 20)
X
X#define		MAX_FROM	25
X#define		MAX_SUBJ	38
X#define		TABLE_SIZE	1409
X
X/* #define		MAX_SUBJ	(COLS - 42)	*/
X
X
Xstruct header {
X	long artnum;
X	char subject[MAX_SUBJ];
X	char *nore;		/* pointer into subject after Re: */
X	char from[MAX_FROM];
X	int thread;
X	long hash;
X	int inthread;
X	int unread;		/* has this article been read? */
X				/* 0 = read, 1 = unread, 2 = will return */
X};
X
X/*
X *  header.artnum:
X *	article number in spool directory for group
X *
X *  header.nore
X *	pointer into header.subject after the Re:'s.
X *
X *  header.hash:
X *	hash of the subject minus the re's.  For fast subject comparison
X *
X *  header.thread:
X *	initially -1
X *	points to another arts[] (struct header): zero and up
X *	-2 means article has expired (wasn't found in file search
X *	of spool directory for the group)
X *
X *  header.inthread:
X *	FALSE for the first article in a thread, TRUE for all
X *	following articles in thread
X *
X *  header.read:
X *	boolean, has this article been read or not
X */
X
Xstruct group_ent {
X	char *name;
X	long max;
X	long min;
X	int next;		/* next active entry in hash chain */
X	int flag;
X};
X
X#define		NOTGOT		0x01	/* haven't put in my_group yet */
X#define		SUBS		0x02	/* subscribed to */
X
X
Xextern int top;
Xextern struct header *arts;
Xextern long *base;
Xextern int max_art;
X
Xextern char userid[LEN];
Xextern char homedir[LEN];
Xextern char indexdir[LEN];
Xextern char my_org[LEN];
Xextern char active_file[LEN];
X#ifdef	OSK
Xextern char spooldir[LEN];
X#endif	/* OSK */
X#ifdef	INCSTR
Xextern char *incstr;
X#endif	/* INCSTR */
Xextern char newsrc[LEN];
Xextern char newnewsrc[LEN];
Xextern char delgroups[LEN];
Xextern int top_base;
Xextern int LINES, COLS;
Xextern char *str_save();
Xextern char *my_malloc();
Xextern char *my_realloc();
Xextern int group_hash[TABLE_SIZE];
X
Xextern int num_active;
Xextern struct group_ent *active;
Xextern int *my_group;
Xextern int *unread;
Xextern int max_active;
X
Xextern int local_top;
Xextern char *eat_re();
Xextern char *nice_time();
Xextern int update;
Xextern int inverse_okay;
X
X#ifdef	USE_UID
Xextern int tass_uid;
Xextern int tass_gid;
Xextern int real_uid;
Xextern int real_gid;
X#endif	/* USE_UID */
Xextern int local_index;
Xextern int do_mail_check;
Xextern int omask;
X
Xextern jmp_buf jmp_buffer;
X
Xextern char *strcpy();
Xextern char *strncat();
Xextern char *strncpy();
Xextern long atol();
X
X
X#define		ctrl(c)			((c) & 0x1F)
X
X/*
X *  Assertion verifier
X */
X
X#ifdef __STDC__
X#define	assert(p)	if(! (p)) asfail(__FILE__, __LINE__, #p); else
X#else
X#define	assert(p)	if(! (p)) asfail(__FILE__, __LINE__, "p"); else
X#endif
X
X#define		TASS_HEADER	"Tass 3.0"
X
Xextern void	dump_index();
Xextern void	load_index();
Xextern void	find_local_index();
Xextern void	search_subject();
Xextern void	tass_group_help();
Xextern void	read_newsrc();
Xextern void	print_seq();
Xextern void	mark_group_read();
Xextern void	cancel_article();
Xextern void	save_art_to_file();
Xextern void	save_thread_to_file();
Xextern void	pipe_article();
Xextern void	open_note();
Xextern void	tass_page_help();
Xextern void	find_new_to();
Xextern void	search_group();
__END__OF__THIS__FILE__
if test -f 'time.c' ; then
  echo 'File time.c already exists, overwriting it'
  del 'time.c'
fi
echo Extracting \"'time.c'\"
sed "s/^X//" >'time.c' <<'__END__OF__THIS__FILE__'
X
X#include	<sys/types.h>
X#include	<time.h>
X
X
Xnicedate(timestr, newstr)
Xchar *timestr, *newstr;
X{
X	int i;
X
X	for (i = 0; i <= 7; i++)
X		*newstr++ = timestr[i];
X	if (timestr[8] != ' ')
X		*newstr++ = timestr[8];
X	*newstr++ = timestr[9];
X	*newstr++ = ',';
X	*newstr++ = ' ';
X	for (i = 20;i <= 23; i++)
X		*newstr++ = timestr[i];
X	*newstr++ = '\0';
X}
X
Xnicetime(timestr, newstr)
Xchar *timestr, *newstr;
X{
X	int hours;
X	char dayornite[3];
X
X	if (timestr[11] == ' ')
X		hours = timestr[12] - '0';
X	else
X		hours = (timestr[11]-'0')*10 + (timestr[12]-'0');
X	if (hours < 12)
X		strcpy(dayornite, "am");
X	else
X		strcpy(dayornite, "pm");
X	if (hours >= 13)
X		hours -= 12;
X	if (!hours)
X		hours = 12;
X	sprintf(newstr, "%d:%c%c%s", hours, timestr[14],
X					timestr[15], dayornite);
X}
X
Xchar *nice_time() {
X	char *timestr;
X	char the_date[17];
X	char the_time[8];
X#ifndef	OSK
X	extern char *ctime();
X#endif	/* OSK */
X	long time_now;
X	static char buf[25];
X
X	time(&time_now);
X	timestr = ctime(&time_now);
X	nicedate(timestr, the_date);
X	nicetime(timestr, the_time);
X	sprintf(buf,"%s  %s", the_date, the_time);
X	return(buf);
X}
X
__END__OF__THIS__FILE__
exit 0
: end of shell archive

-- 
Frank Kaefer # fkk@stasys.sta.sub.org # Starnberg, Germany
Xref: sparky de.comp.sources.os9:5 comp.os.os9:1547