home *** CD-ROM | disk | FTP | other *** search
- From: skrenta@blekko.commodore.com (Rich Skrenta)
- Newsgroups: alt.sources
- Subject: Tass newsreader (part 2 of 2)
- Message-ID: <146@blekko.commodore.com>
- Date: 14 Feb 91 19:35:43 GMT
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # This archive contains:
- # page.c prompt.c screen.c select.c
- # tass.h time.c
- #
-
- echo x - page.c
- cat >page.c <<'@EOF'
-
- #include <stdio.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "tass.h"
-
-
- #define MAX_PAGES 1000
- #define NOTE_UNAVAIL -1
-
- char note_h_path[LEN]; /* Path: */
- char note_h_date[LEN]; /* Date: */
- char note_h_subj[LEN]; /* Subject: */
- char note_h_from[LEN]; /* From: */
- char note_h_org[LEN]; /* Organization: */
- char note_h_newsgroups[LEN]; /* Newsgroups: */
- char note_h_messageid[LEN]; /* Message-ID: */
- char note_h_distrib[LEN]; /* Distribution: */
- char note_h_followup[LEN]; /* Followup-To: */
-
- int note_line;
- int note_page; /* what page we're on */
- long note_mark[MAX_PAGES]; /* ftells on beginnings of pages */
- FILE *note_fp; /* the body of the current article */
- int note_end; /* we're done showing this article */
- int rotate; /* 0=normal, 13=rot13 decode */
-
- struct stat note_stat; /* so we can tell how big it is */
-
- char note_full_name[100];
- char note_from_addr[100];
-
-
- int last_resp; /* current & previous article for - command */
- int this_resp;
-
- int glob_respnum;
- char *glob_page_group;
- extern int cur_groupnum;
-
-
- #ifdef SIGTSTP
- void
- page_susp(i)
- int i;
- {
-
- Raw(FALSE);
- putchar('\n');
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
-
- signal(SIGTSTP, page_susp);
- mail_setup();
- Raw(TRUE);
- redraw_page(glob_respnum, glob_page_group);
- }
- #endif
-
-
- show_page(respnum, group, group_path)
- int respnum;
- char *group;
- char *group_path;
- {
- char ch;
- int n;
- long art;
-
- restart:
-
- glob_respnum = respnum;
- glob_page_group = group;
-
- #ifdef SIGTSTP
- signal(SIGTSTP, page_susp);
- #endif
-
- if (respnum != this_resp) { /* remember current & previous */
- last_resp = this_resp; /* articles for - command */
- this_resp = respnum;
- }
-
- rotate = 0; /* normal mode, not rot13 */
- art = arts[respnum].artnum;
- arts[respnum].unread = 0; /* mark article as read */
- open_note(art, group_path);
-
- if (note_page == NOTE_UNAVAIL) {
- ClearScreen();
- printf("[Article %ld unvailable]\r\r", art);
- fflush(stdout);
- } else
- show_note_page(respnum, group);
-
- while (1) {
- ch = ReadCh();
-
- if (ch >= '0' && ch <= '9') {
-
- n = prompt_response(ch, respnum);
- if (n != -1) {
- respnum = n;
- goto restart;
- }
-
- } else switch (ch) {
- case '|': /* pipe article into command */
- pipe_article();
- redraw_page(respnum, group);
- break;
-
- case 'I': /* toggle inverse video */
- inverse_okay = !inverse_okay;
- if (inverse_okay)
- info_message("Inverse video enabled");
- else
- info_message("Inverse video disabled");
- goto pager_ctrlr;
- break;
-
- case 's':
- save_art_to_file();
- break;
-
- case 'S':
- save_thread_to_file(respnum, group_path);
- break;
-
- case ctrl('X'):
- case '%': /* toggle rot-13 mode */
- if (rotate)
- rotate = 0;
- else
- rotate = 13;
- goto pager_ctrlr;
- break;
-
- case 'P': /* previous unread article */
- n = prev_unread(prev_response(respnum));
- if (n == -1)
- info_message("No previous unread article");
- else {
- note_cleanup();
- respnum = n;
- goto restart;
- }
- break;
-
- case 'F': /* post a followup to this article */
- if (post_response(group, TRUE)) {
- update_newsrc(group,
- my_group[cur_groupnum]);
- n = which_base(respnum);
- note_cleanup();
- index_group(group, group_path);
- read_newsrc_line(group);
- respnum = choose_resp(n, nresp(n));
- goto restart;
- } else
- redraw_page(respnum, group);
- break;
-
- case 'f': /* post a followup to this article */
- if (post_response(group, FALSE)) {
- update_newsrc(group,
- my_group[cur_groupnum]);
- n = which_base(respnum);
- note_cleanup();
- index_group(group, group_path);
- read_newsrc_line(group);
- respnum = choose_resp(n, nresp(n));
- goto restart;
- } else
- redraw_page(respnum, group);
- break;
-
- case 'z': /* mark article as unread (to return) */
- arts[respnum].unread = 2;
- info_message("Article marked as unread");
- break;
-
- case 'K': /* mark rest of thread as read */
- for (n = respnum; n >= 0; n = arts[n].thread)
- arts[n].unread = 0;
- n = next_unread(next_response(respnum));
- if (n == -1)
- goto return_to_index;
- else {
- note_cleanup();
- respnum = n;
- goto restart;
- }
- break;
-
- case 'i': /* return to index page */
- return_to_index:
- note_cleanup();
- return( which_base(respnum) );
-
- case 't': /* return to group selection page */
- note_cleanup();
- return -1;
-
- case ctrl('R'): /* redraw beginning of article */
- pager_ctrlr:
- if (note_page == NOTE_UNAVAIL) {
- ClearScreen();
- printf("[Article %ld unvailable]\r\n",
- arts[respnum].artnum);
- fflush(stdout);
- } else {
- note_page = 0;
- note_end = FALSE;
- fseek(note_fp, note_mark[0], 0);
- show_note_page(respnum, group);
- }
- break;
-
- case '!':
- shell_escape();
- redraw_page(respnum, group);
- break;
-
- case '\b':
- case 'b': /* back a page */
- if (note_page == NOTE_UNAVAIL
- || note_page <= 1) {
- note_cleanup();
- n = prev_response(respnum);
- if (n == -1)
- return( which_resp(respnum) );
-
- respnum = n;
- goto restart;
-
- } else {
- note_page -= 2;
- note_end = FALSE;
- fseek(note_fp, note_mark[note_page], 0);
- show_note_page(respnum, group);
- }
- break;
-
- case 'm': /* mail article to somebody */
- mail_to_someone();
- redraw_page(respnum, group);
- break;
-
- case 'r': /* reply to author through mail */
- mail_to_author(FALSE);
- redraw_page(respnum, group);
- break;
-
- case 'R': /* reply to author, copy text */
- mail_to_author(TRUE);
- redraw_page(respnum, group);
- break;
-
- case '-': /* show last viewed article */
- if (last_resp < 0) {
- info_message("No last message");
- break;
- }
- note_cleanup();
- respnum = last_resp;
- goto restart;
-
-
- case 'p': /* previous article */
- note_cleanup();
- n = prev_response(respnum);
- if (n == -1)
- return( which_resp(respnum) );
-
- respnum = n;
- goto restart;
-
- case 'n': /* skip to next article */
- note_cleanup();
- n = next_response(respnum);
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
-
- case 'k':
- if (note_page == NOTE_UNAVAIL) {
- n = next_unread(next_response(respnum));
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
-
- } else {
- note_cleanup();
- n = next_unread(next_response(respnum));
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
- }
- break;
-
- case ' ': /* next page or response */
- if (note_page == NOTE_UNAVAIL) {
- n = next_response(respnum);
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
-
- } else if (note_end) {
- note_cleanup();
- n = next_response(respnum);
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
- } else
- show_note_page(respnum, group);
- break;
-
- case '\t': /* next page or unread response */
- if (note_page == NOTE_UNAVAIL) {
- n = next_unread(next_response(respnum));
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
-
- } else if (note_end) {
- note_cleanup();
- n = next_unread(next_response(respnum));
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
- } else
- show_note_page(respnum, group);
- break;
-
- case 'N': /* next unread article */
- n = next_unread(next_response(respnum));
- if (n == -1)
- info_message("No next unread article");
- else {
- note_cleanup();
- respnum = n;
- goto restart;
- }
- break;
-
- case '\r':
- case '\n': /* go to start of next thread */
- note_cleanup();
- n = next_basenote(respnum);
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
-
- case 'q': /* quit */
- return -2;
-
- case 'H': /* show article headers */
- if (note_page == NOTE_UNAVAIL) {
- n = next_response(respnum);
- if (n == -1)
- return( which_base(respnum) );
-
- respnum = n;
- goto restart;
- } else {
- note_page = 0;
- note_end = FALSE;
- fseek(note_fp, 0L, 0);
- show_note_page(respnum, group);
- }
- break;
-
-
- case 'h':
- tass_page_help();
- redraw_page(respnum, group);
- break;
-
- default:
- info_message("Bad command. Type 'h' for help.");
- }
- }
- }
-
-
- note_cleanup() {
-
- if (note_page != NOTE_UNAVAIL)
- fclose(note_fp);
- }
-
-
- redraw_page(respnum, group)
- int respnum;
- char *group;
- {
-
- if (note_page == NOTE_UNAVAIL) {
- ClearScreen();
- printf("[Article %ld unvailable]\r\r", arts[respnum].artnum);
- fflush(stdout);
- } else if (note_page > 0) {
- note_page--;
- fseek(note_fp, note_mark[note_page], 0);
- show_note_page(respnum, group);
- }
- }
-
-
- show_note_page(respnum, group)
- int respnum;
- char *group;
- {
- char buf[LEN];
- char buf2[LEN+50];
- int percent;
- char *p, *q;
- int i, j;
- int ctrl_L; /* form feed character detected */
-
- ClearScreen();
-
- note_line = 1;
-
- if (note_page == 0)
- show_first_header(respnum, group);
- else
- show_cont_header(respnum);
-
- ctrl_L = FALSE;
- while (note_line < LINES) {
- if (fgets(buf, LEN, note_fp) == NULL) {
- note_end = TRUE;
- break;
- }
-
- buf[LEN-1] = '\0';
- if (rotate)
- for (p = buf, q = buf2;
- *p && *p != '\n' && q<&buf2[LEN]; p++) {
- if (*p == '\b' && q > buf2) {
- q--;
- } else if (*p == 12) { /* ^L */
- *q++ = '^';
- *q++ = 'L';
- ctrl_L = TRUE;
- } else if (*p == '\t') {
- i = q - buf2;
- j = (i|7) + 1;
-
- while (i++ < j)
- *q++ = ' ';
- } else if (*p & 0x7F < 32) {
- *q++ = '^';
- *q++ = (*p & 0x7F) + '@';
- } else if (*p >= 'A' && *p <= 'Z')
- *q++ = 'A' + (*p - 'A' + rotate) % 26;
- else if (*p >= 'a' && *p <= 'z')
- *q++ = 'a' + (*p - 'a' + rotate) % 26;
- else
- *q++ = *p;
- }
- else
- for (p = buf, q = buf2;
- *p && *p != '\n' && q<&buf2[LEN]; p++) {
- if (*p == '\b' && q > buf2) {
- q--;
- } else if (*p == 12) { /* ^L */
- *q++ = '^';
- *q++ = 'L';
- ctrl_L = TRUE;
- } else if (*p == '\t') {
- i = q - buf2;
- j = (i|7) + 1;
-
- while (i++ < j)
- *q++ = ' ';
- } else if ((*p & 0x7F) < 32) {
- *q++ = '^';
- *q++ = (*p & 0x7F) + '@';
- } else
- *q++ = *p;
- }
-
- *q = '\0';
-
- printf("%s\r\n", buf2);
-
- #if 1
- note_line += (strlen(buf2) / COLS) + 1;
- #else
- if (*buf2)
- note_line += (strlen(buf2) + COLS) / (COLS+1);
- else
- note_line++;
- #endif
- if (ctrl_L)
- break;
- }
-
- note_mark[++note_page] = ftell(note_fp);
-
- MoveCursor(LINES, MORE_POS);
- /* StartInverse(); */
- if (note_end) {
- if (arts[respnum].thread != -1)
- printf("-- next response --");
- else
- printf("-- last response --");
- } else {
- if (note_stat.st_size > 0) {
- percent = note_mark[note_page] * 100 / note_stat.st_size;
- printf("--More--(%d%%)", percent);
- } else
- printf("--More--");
- }
- /* EndInverse(); */
-
- fflush(stdout);
- }
-
-
- show_first_header(respnum, group)
- int respnum;
- char *group;
- {
- int whichresp;
- int x_resp;
- char buf[200];
- char tmp[200];
- int pos, i;
- int n;
-
- whichresp = which_resp( respnum );
- x_resp = nresp( which_base(respnum) );
-
- ClearScreen();
-
- strcpy(buf, note_h_date);
- pos = (COLS - strlen(group)) / 2;
- for (i = strlen(buf); i < pos; i++)
- buf[i] = ' ';
- buf[i] = '\0';
-
- strcat(buf, group);
-
- for (i = strlen(buf); i < RIGHT_POS; i++)
- buf[i] = ' ';
- buf[i] = '\0';
-
- printf("%sNote %3d of %3d\r\n", buf, which_base(respnum) + 1, top_base);
-
- sprintf(buf, "Article %ld ", arts[respnum].artnum);
- n = strlen(buf);
- fputs(buf, stdout);
-
- pos = (COLS - strlen( note_h_subj )) / 2 - 2;
-
- if (pos > n)
- MoveCursor(1, pos);
- else
- MoveCursor(1, n);
-
- StartInverse();
- strcpy(buf, note_h_subj);
- buf[RIGHT_POS - 2 - n] = '\0';
- fputs(buf, stdout);
- EndInverse();
-
- MoveCursor(1, RIGHT_POS);
- if (whichresp)
- printf("Resp %3d of %3d\r\n", whichresp, x_resp);
- else {
- if (x_resp == 0)
- printf("No responses\r\n");
- else if (x_resp == 1)
- printf("1 Response\r\n");
- else
- printf("%d Responses\r\n", x_resp);
- }
-
- if (*note_h_org)
- sprintf(tmp, "%s at %s", note_full_name, note_h_org);
- else
- strcpy(tmp, note_full_name);
-
- tmp[79] = '\0';
-
- sprintf(buf, "%s ", note_from_addr);
-
- pos = COLS - 1 - strlen(tmp);
- if (strlen(buf) + strlen(tmp) >= COLS - 1) {
- strncat(buf, tmp, COLS - 1 - strlen(buf));
- buf[COLS - 1] = '\0';
- } else {
- for (i = strlen(buf); i < pos; i++)
- buf[i] = ' ';
- buf[i] = '\0';
- strcat(buf, tmp);
- }
- printf("%s\r\n\r\n", buf);
-
- note_line += 4;
- }
-
-
- show_cont_header(respnum)
- int respnum;
- {
- int whichresp;
- int whichbase;
- char buf[200];
-
- whichresp = which_resp(respnum);
- whichbase = which_base(respnum);
-
- assert (whichbase < top_base);
-
- if (whichresp)
- sprintf(buf, "Note %d of %d, Resp %d (page %d): %s",
- whichbase + 1,
- top_base,
- whichresp,
- note_page + 1,
- note_h_subj);
- else
- sprintf(buf, "Note %d of %d (page %d): %s",
- whichbase + 1,
- top_base,
- note_page + 1,
- note_h_subj);
-
- buf[COLS] = '\0';
- printf("%s\r\n\r\n", buf);
-
- note_line += 2;
- }
-
-
- open_note(art, group_path)
- long art;
- char *group_path;
- {
- char buf[1025];
-
- note_page = 0;
-
- sprintf(buf, "/usr/spool/news/%s/%ld", group_path, art);
-
- if (stat(buf, ¬e_stat) < 0)
- note_stat.st_size = 0;
-
- note_fp = fopen(buf, "r");
- if (note_fp == NULL) {
- fprintf(stderr, "can't open %s: ", buf);
- perror("");
- note_page = NOTE_UNAVAIL;
- return;
- }
-
- note_h_from[0] = '\0';
- note_h_path[0] = '\0';
- note_h_subj[0] = '\0';
- note_h_org[0] = '\0';
- note_h_date[0] = '\0';
- note_h_newsgroups[0] = '\0';
- note_h_messageid[0] = '\0';
- note_h_distrib[0] = '\0';
- note_h_followup[0] = '\0';
-
- while (fgets(buf, 1024, note_fp) != NULL) {
- buf[1024] = '\0';
- buf[strlen(buf)-1] = '\0';
-
- if (*buf == '\0')
- break;
-
- if (strncmp(buf, "From: ", 6) == 0) {
- strncpy(note_h_from, &buf[6], LEN);
- note_h_from[LEN-1] = '\0';
- } else if (strncmp(buf, "Path: ", 6) == 0) {
- strncpy(note_h_path, &buf[6], LEN);
- note_h_path[LEN-1] = '\0';
- } else if (strncmp(buf, "Subject: ", 9) == 0) {
- strncpy(note_h_subj, &buf[9], LEN);
- note_h_subj[LEN-1] = '\0';
- } else if (strncmp(buf, "Organization: ", 14) == 0) {
- strncpy(note_h_org, &buf[14], LEN);
- note_h_org[LEN-1] = '\0';
- } else if (strncmp(buf, "Date: ", 6) == 0) {
- strncpy(note_h_date, &buf[6], LEN);
- note_h_date[LEN-1] = '\0';
- } else if (strncmp(buf, "Newsgroups: ", 12) == 0) {
- strncpy(note_h_newsgroups, &buf[12], LEN);
- note_h_newsgroups[LEN-1] = '\0';
- } else if (strncmp(buf, "Message-ID: ", 12) == 0) {
- strncpy(note_h_messageid, &buf[12], LEN);
- note_h_messageid[LEN-1] = '\0';
- } else if (strncmp(buf, "Distribution: ", 14) == 0) {
- strncpy(note_h_distrib, &buf[14], LEN);
- note_h_distrib[LEN-1] = '\0';
- } else if (strncmp(buf, "Followup-To: ", 13) == 0) {
- strncpy(note_h_followup, &buf[13], LEN);
- note_h_followup[LEN-1] = '\0';
- }
- }
-
- note_page = 0;
- note_mark[0] = ftell(note_fp);
-
- parse_from(note_h_from, note_from_addr, note_full_name);
- note_end = FALSE;
-
- return;
- }
-
-
- prompt_response(ch, respnum)
- int respnum;
- {
- int num;
-
- clear_message();
-
- if ((num = parse_num(ch, "Read response> ")) == -1) {
- clear_message();
- return(-1);
- }
-
- return choose_resp( which_base(respnum), num );
- }
-
-
- /*
- * return response number n from thread i
- */
-
- choose_resp(i, n)
- int i;
- int n;
- {
- int j;
-
- j = base[i];
-
- while (n-- && arts[j].thread >= 0)
- j = arts[j].thread;
-
- return j;
- }
-
-
- /*
- * Parse various From: lines into the component mail addresses and
- * real names
- */
-
- parse_from(str, addr, name)
- char *str;
- char *addr;
- char *name;
- {
- while (*str && *str != ' ')
- *addr++ = *str++;
- *addr = '\0';
- if (*str++ == ' ') {
- if (*str++ == '(') {
- if (*str == '"')
- str++; /* Kill "quotes around names" */
- /* But don't touch quotes inside the */
- /* Name (that's what that nonsense */
- /* below is for */
- while (*str && *str != ')' && !(*str=='"'&&str[1]==')'))
- *name++ = *str++;
- }
- }
- *name = '\0';
- }
-
-
- /*
- * Find the previous response. Go to the last response in the previous
- * thread if we go past the beginning of this thread.
- */
-
- prev_response(n)
- int n;
- {
- int resp;
- int i;
-
- resp = which_resp(n);
-
- if (resp > 0)
- return choose_resp( which_base(n), resp-1 );
-
- i = which_base(n) - 1;
-
- if (i < 0)
- return -1;
-
- return choose_resp( i, nresp(i) );
- }
-
-
- /*
- * Find the next response. Go to the next basenote if there
- * are no more responses in this thread
- */
-
- next_response(n)
- int n;
- {
- int i;
-
- if (arts[n].thread >= 0)
- return arts[n].thread;
-
- i = which_base(n) + 1;
-
- if (i >= top_base)
- return -1;
-
- return base[i];
- }
-
-
- /*
- * Given a respnum (index into arts[]), find the respnum of the
- * next basenote
- */
-
- next_basenote(n)
- int n;
- {
- int i;
-
- i = which_base(n) + 1;
- if (i >= top_base)
- return -1;
-
- return base[i];
- }
-
-
- tass_page_help() {
- char ch;
-
- page_help_start:
-
- ClearScreen();
- center_line(0, TASS_HEADER);
- center_line(1, "Article Pager Commands (page 1 of 2)");
-
- MoveCursor(3, 0);
-
- printf("0 Read the base article in this thread\r\n");
- printf("4 Read response 4 in this thread\r\n");
- printf("<CR> Skip to next base article\r\n");
- printf("<TAB> Advance to next page or unread article\r\n");
- printf("b Back a page\r\n");
- printf("f Post a followup\r\n");
- printf("F Post a followup, copy text)\r\n");
- printf("H Show article headers\r\n");
- printf("i Return to index page\r\n");
- printf("k Mark article as read & advance to next unread\r\n");
- printf("K Mark rest of thread as read && advance to next unread\r\n");
- printf("m Mail this article to someone\r\n");
- printf("n Skip to the next article)\r\n");
- printf("N Skip to the next unread article\r\n");
- printf("p Go to the previous article\r\n");
- printf("P Go to the previous unread article\r\n");
-
- center_line(LINES, "-- hit space for more commands --");
- ch = ReadCh();
- if (ch != ' ')
- return;
-
- ClearScreen();
- center_line(0, TASS_HEADER);
- center_line(1, "Article Pager Commands (page 2 of 2)");
-
- MoveCursor(3, 0);
-
- printf("q Quit\r\n");
- printf("r Reply through mail to author\r\n");
- printf("R Reply through mail to author, copy text\r\n");
- printf("s Save article to file\r\n");
- printf("S Save thread to file\r\n");
- printf("t Return to group selection index\r\n");
- printf("z Mark article as unread\r\n");
- printf("^R Redisplay first page of article\r\n");
- printf("%%, ^X Toggle rot-13 decoding for this article\r\n");
- printf("- Show last message\r\n");
- printf("| Pipe article into command\r\n");
-
- center_line(LINES, "-- hit any key --");
- ch = ReadCh();
-
- if (ch == 'b')
- goto page_help_start;
- }
-
-
-
- /*
- * Read a file grabbing the address given for To: and
- * sticking it in mail_to
- */
-
- find_new_to(nam, mail_to)
- char *nam;
- char *mail_to;
- {
- FILE *fp;
- char buf[LEN];
- char buf2[LEN];
- char dummy[LEN];
-
- fp = fopen(nam, "r");
- if (fp == NULL)
- return;
-
- while (fgets(buf, 1024, fp) != NULL) {
- if (*buf == '\n')
- break;
- if (strncmp(buf, "To: ", 4) == 0) {
- buf[strlen(buf)-1] = '\0';
- strncpy(buf2, &buf[4], LEN);
- buf2[LEN-1] = '\0';
- parse_from(buf2, mail_to, dummy);
- break;
- }
- }
-
- fclose(fp);
- }
-
-
- mail_to_someone() {
- char nam[100];
- FILE *fp;
- char ch;
- char buf[200];
- char mail_to[LEN+1];
- char subj[LEN+1];
-
- setuid(real_uid);
- setgid(real_gid);
-
- if (!parse_string("Mail article to: ", mail_to))
- return;
- if (mail_to[0] == '\0')
- return;
-
- sprintf(nam, "%s/.letter", homedir);
- if ((fp = fopen(nam, "w")) == NULL) {
- fprintf(stderr, "can't open %s: ", nam);
- perror("");
- return(FALSE);
- }
- chmod(nam, 0600);
-
- fprintf(fp, "To: %s\n", mail_to);
- fprintf(fp, "Subject: %s\n", note_h_subj);
- if (*note_h_followup)
- fprintf(fp, "Newsgroups: %s\n\n", note_h_followup);
- else
- fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
- if (*my_org)
- fprintf(fp, "Organization: %s\n", my_org);
- fputs("\n", fp);
-
- fseek(note_fp, 0L, 0);
- copy_fp(note_fp, fp, "");
-
- fclose(fp);
-
- while (1) {
- do {
- MoveCursor(LINES, 0);
- fputs("abort, edit, send: ", stdout);
- fflush(stdout);
- ch = ReadCh();
- } while (ch != 'a' && ch != 'e' && ch != 's');
-
- switch (ch) {
- case 'e':
- invoke_editor(nam);
- break;
-
- case 'a':
- return FALSE;
-
- case 's':
- /*
- * Open letter an get the To: line in case they changed it with
- * the editor
- */
-
- find_new_to(nam, mail_to);
- printf("\nMailing to %s...", mail_to);
- fflush(stdout);
- sprintf(buf, "%s \"%s\" < %s", MAILER,
- mail_to, nam);
- if (invoke_cmd(buf)) {
- printf("Message sent\n");
- fflush(stdout);
- goto mail_to_someone_done;
- } else {
- printf("Command failed: %s\n", buf);
- fflush(stdout);
- break;
- }
- }
- }
-
- mail_to_someone_done:
- setuid(tass_uid);
- setgid(tass_gid);
-
- continue_prompt();
-
- return TRUE;
- }
-
-
- mail_to_author(copy_text)
- int copy_text;
- {
- char nam[100];
- FILE *fp;
- char ch;
- char buf[200];
- char mail_to[LEN+1];
-
- setuid(real_uid);
- setgid(real_gid);
-
- printf("\r\nMailing to %s...\r\n\r\n", note_h_from);
-
- sprintf(nam, "%s/.letter", homedir);
- if ((fp = fopen(nam, "w")) == NULL) {
- fprintf(stderr, "can't open %s: ", nam);
- perror("");
- return(FALSE);
- }
- chmod(nam, 0600);
-
- fprintf(fp, "To: %s\n", note_h_from);
- fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj) );
- fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
- if (*my_org)
- fprintf(fp, "Organization: %s\n", my_org);
- fputs("\n", fp);
-
- if (copy_text) { /* if "copy_text" */
- fprintf(fp, "In article %s you write:\n", note_h_messageid);
-
- fseek(note_fp, note_mark[0], 0);
- copy_fp(note_fp, fp, "> ");
- }
-
- fclose(fp);
-
- ch = 'e';
- while (1) {
- switch (ch) {
- case 'e':
- invoke_editor(nam);
- break;
-
- case 'a':
- return FALSE;
-
- case 's':
- strcpy(mail_to, note_from_addr);
- find_new_to(nam, mail_to);
- printf("\nMailing to %s... ", mail_to);
- fflush(stdout);
- sprintf(buf, "/usr/bin/rmail \"%s\" < %s",
- mail_to, nam);
- if (invoke_cmd(buf)) {
- printf("Message sent\n");
- fflush(stdout);
- goto mail_to_author_done;
- } else {
- printf("Command failed: %s\n", buf);
- fflush(stdout);
- break;
- }
- }
-
- do {
- MoveCursor(LINES, 0);
- fputs("abort, edit, send: ", stdout);
- fflush(stdout);
- ch = ReadCh();
- } while (ch != 'a' && ch != 'e' && ch != 's');
- }
-
- mail_to_author_done:
- setuid(tass_uid);
- setgid(tass_gid);
-
- continue_prompt();
-
- return TRUE;
- }
-
-
- post_response(group, respnum)
- int respnum;
- {
- FILE *fp;
- char nam[100];
- char ch;
- char buf[200];
- int post_anyway = FALSE;
-
- if (*note_h_followup && strcmp(note_h_followup, "poster") == 0) {
- clear_message();
- MoveCursor(LINES,0);
- printf("Note: Responses have been directed to the poster");
- if (!prompt_yn("Post anyway? (y/n): "))
- return FALSE;
- *note_h_followup = '\0';
- } else if (*note_h_followup && strcmp(note_h_followup, group) != 0) {
- clear_message();
- MoveCursor(LINES,0);
- printf("Note: Responses have been directed to %s\r\n\r\n",
- note_h_followup);
- if (!prompt_yn("Continue? (y/n): "))
- return FALSE;
- }
-
- setuid(real_uid);
- setgid(real_gid);
-
- sprintf(nam, "%s/.article", homedir);
- if ((fp = fopen(nam, "w")) == NULL) {
- fprintf(stderr, "can't open %s: ", nam);
- perror("");
- return FALSE;
- }
- chmod(nam, 0600);
-
- fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj));
-
- if (*note_h_followup && strcmp(note_h_followup, "poster") != 0)
- fprintf(fp, "Newsgroups: %s\n", note_h_followup);
- else
- fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
-
- if (*my_org)
- fprintf(fp, "Organization: %s\n", my_org);
-
- if (note_h_distrib != '\0')
- fprintf(fp, "Distribution: %s\n", note_h_distrib);
-
- fprintf(fp, "References: %s\n", note_h_messageid);
- fprintf(fp, "\n");
-
- if (respnum) { /* if "copy_text" */
- fprintf(fp, "%s writes:\n", note_h_from);
-
- fseek(note_fp, note_mark[0], 0);
- copy_fp(note_fp, fp, "> ");
- }
-
- fclose(fp);
-
- ch = 'e';
- while (1) {
- switch (ch) {
- case 'e':
- invoke_editor(nam);
- break;
-
- case 'a':
- return FALSE;
-
- case 'p':
- printf("Posting... ");
- fflush(stdout);
- sprintf(buf, "%s/inews -h < %s", LIBDIR, nam);
- if (invoke_cmd(buf)) {
- printf("article posted\n");
- fflush(stdout);
- goto post_response_done;
- } else {
- printf("article rejected\n");
- fflush(stdout);
- break;
- }
- }
-
- do {
- MoveCursor(LINES, 0);
- fputs("abort, edit, post: ", stdout);
- fflush(stdout);
- ch = ReadCh();
- } while (ch != 'a' && ch != 'e' && ch != 'p');
- }
-
- post_response_done:
- setuid(tass_uid);
- setgid(tass_gid);
-
- continue_prompt();
-
- return TRUE;
- }
-
-
- save_art_to_file()
- {
- char nam[LEN];
- FILE *fp;
- char *p;
-
- if (!parse_string("Save article to file: ", nam))
- return;
- if (nam[0] == '\0')
- return;
-
- for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
- if (!*p)
- return;
-
- setuid(real_uid);
- setgid(real_gid);
-
- if ((fp = fopen(p, "a+")) == NULL) {
- fprintf(stderr, "can't open %s: ", nam);
- perror("");
- info_message("-- article not saved --");
- setuid(real_uid);
- setgid(real_gid);
- return;
- }
-
- MoveCursor(LINES, 0);
- fputs("Saving...", stdout);
- fflush(stdout);
-
- fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
-
- fseek(note_fp, 0L, 0);
- copy_fp(note_fp, fp, "");
- fputs("\n", fp);
-
- fclose(fp);
-
- setuid(real_uid);
- setgid(real_gid);
- info_message("-- article saved --");
- }
-
-
- save_thread_to_file(respnum, group_path)
- long respnum;
- char *group_path;
- {
- char nam[LEN];
- FILE *fp;
- FILE *art;
- int i;
- char buf[8192];
- int b;
- int count = 0;
- char *p;
-
- b = which_base(respnum);
-
- if (!parse_string("Save thread to file: ", nam))
- return;
- if (nam[0] == '\0')
- return;
-
- for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
- if (!*p)
- return;
-
- setuid(real_uid);
- setgid(real_gid);
-
- if ((fp = fopen(nam, "a+")) == NULL) {
- fprintf(stderr, "can't open %s: ", nam);
- perror("");
- info_message("-- thread not saved --");
- setuid(real_uid);
- setgid(real_gid);
- return;
- }
-
- MoveCursor(LINES, 0);
- fputs("Saving... ", stdout);
- fflush(stdout);
-
- note_cleanup();
-
- for (i = base[b]; i >= 0; i = arts[i].thread) {
- open_note(arts[i].artnum, group_path);
-
- fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
- fseek(note_fp, 0L, 0);
- copy_fp(note_fp, fp, "");
- fputs("\n", fp);
-
- note_cleanup();
- printf("\b\b\b\b%4d", ++count);
- fflush(stdout);
- }
-
- fclose(fp);
- setuid(real_uid);
- setgid(real_gid);
-
- info_message("-- thread saved --");
- open_note(arts[respnum].artnum, group_path);
- }
-
-
- pipe_article() {
- char command[LEN];
- FILE *fp;
-
- if (!parse_string("Pipe to command: ", command))
- return;
- if (command[0] == '\0')
- return;
-
- fp = popen(command, "w");
- if (fp == NULL) {
- fprintf(stderr, "command failed: ");
- perror("");
- goto pipe_article_done;
- }
-
- fseek(note_fp, 0L, 0);
- copy_fp(note_fp, fp, "");
- pclose(fp);
-
- pipe_article_done:
-
- continue_prompt();
- }
-
- @EOF
-
- chmod 644 page.c
-
- echo x - prompt.c
- cat >prompt.c <<'@EOF'
-
- #include <stdio.h>
- #include "tass.h"
-
-
- /*
- * parse_num
- * get a number from the user
- * Return -1 if missing or bad number typed
- */
-
- parse_num(ch, prompt)
- char ch;
- char *prompt;
- {
- char buf[40];
- int len;
- int i;
- int num;
-
- MoveCursor(LINES,0);
- printf("%s %c",prompt,ch);
- fflush(stdout);
- buf[0] = ch;
- buf[1] = '\0';
- len = 1;
- ch = ReadCh();
- while (ch != '\n'&& ch != '\r') {
- if (ch >= '0' && ch <= '9' && len < 4) {
- buf[len++] = ch;
- buf[len] = '\0';
- putchar(ch);
- } else if (ch == 8 || ch == 127) {
- if (len) {
- len--;
- buf[len] = '\0';
- putchar('\b');
- putchar(' ');
- putchar('\b');
- } else {
- MoveCursor(LINES, 0);
- CleartoEOLN();
- return(-1);
- }
- } else if (ch == 21) { /* control-U */
- for (i = len;i>0;i--) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- }
- buf[0] = '\0';
- len = 0;
- } else
- putchar(7);
- fflush(stdout);
- ch = ReadCh();
- }
-
- MoveCursor(LINES, 0);
- CleartoEOLN();
-
- if (len) {
- num = atoi(buf);
- return(num);
- } else
- return(-1);
- }
-
-
- /*
- * parse_string
- * get a string from the user
- * Return TRUE if a valid string was typed, FALSE otherwise
- */
-
- parse_string(prompt, buf)
- char *prompt;
- char *buf;
- {
- int len;
- int i;
- char ch;
-
- clear_message();
- MoveCursor(LINES,0);
- printf("%s", prompt);
- fflush(stdout);
- buf[0] = '\0';
- len = 0;
- ch = ReadCh();
- while (ch != '\n' && ch != '\r') {
- if (ch >= ' ' && len < 60) {
- buf[len++] = ch;
- buf[len] = '\0';
- putchar(ch);
- } else if (ch == 8 || ch == 127) {
- if (len) {
- len--;
- buf[len] = '\0';
- putchar('\b');
- putchar(' ');
- putchar('\b');
- } else {
- MoveCursor(LINES, 0);
- CleartoEOLN();
- return(FALSE);
- }
- } else if (ch == 21) { /* control-U */
- for (i = len;i>0;i--) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- }
- buf[0] = '\0';
- len = 0;
- } else
- putchar(7);
- fflush(stdout);
- ch = ReadCh();
- }
- MoveCursor(LINES,0);
- CleartoEOLN();
-
- return TRUE;
- }
-
-
- prompt_yn(prompt)
- char *prompt;
- {
- char ch;
-
- clear_message();
- MoveCursor(LINES,0);
- printf("%s", prompt);
- fflush(stdout);
-
- ch = ReadCh();
- clear_message();
-
- if (ch == 'y' || ch == 'Y')
- return TRUE;
-
- return FALSE;
- }
-
-
- continue_prompt() {
-
- printf("-Hit return to continue-");
- fflush(stdout);
- while (ReadCh() != '\n') ;
- }
-
-
- @EOF
-
- chmod 644 prompt.c
-
- echo x - screen.c
- cat >screen.c <<'@EOF'
-
- #include <stdio.h>
- #include "tass.h"
-
-
-
- info_message(msg)
- char *msg;
- {
- clear_message(); /* Clear any old messages hanging around */
- center_line(LINES, msg); /* center the message at screen bottom */
- MoveCursor(LINES, 0);
- }
-
-
- clear_message()
- {
- MoveCursor(LINES, 0);
- CleartoEOLN();
- }
-
-
- center_line(line, str)
- int line;
- char *str;
- {
- int pos;
-
- pos = (COLS - strlen(str)) / 2;
- MoveCursor(line, pos);
- printf("%s", str);
- fflush(stdout);
- }
-
-
- draw_arrow(line)
- int line;
- {
- MoveCursor(line, 0);
- printf("->");
- fflush(stdout);
- MoveCursor(LINES, 0);
- }
-
- erase_arrow(line)
- int line;
- {
- MoveCursor(line, 0);
- printf(" ");
- fflush(stdout);
- }
-
- @EOF
-
- chmod 644 screen.c
-
- echo x - select.c
- cat >select.c <<'@EOF'
-
- #include <stdio.h>
- #include <signal.h>
- #include "tass.h"
-
-
- int first_group_on_screen;
- int last_group_on_screen;
- int cur_groupnum = 0;
- extern int index_point;
- int space_mode;
- extern char *cvers;
-
- char group_search_string[LEN+1];
-
-
-
- #ifdef SIGTSTP
- void
- select_susp(i)
- int i;
- {
-
- Raw(FALSE);
- putchar('\n');
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
-
- signal(SIGTSTP, select_susp);
- Raw(TRUE);
- mail_setup();
- group_selection_page();
- }
- #endif
-
-
- selection_index()
- {
- char ch;
- int n;
- int i;
- char buf[200];
-
- group_selection_page(); /* display group selection page */
-
- while (1) {
- ch = ReadCh();
-
- if (ch > '0' && ch <= '9') {
- prompt_group_num(ch);
- } else switch (ch) {
- case 'c': /* catchup--mark all articles as read */
- if (prompt_yn("Mark group as read? (y/n): ")) {
- unread[cur_groupnum] = 0;
- mark_group_read(
- active[my_group[cur_groupnum]].name,
- my_group[cur_groupnum]);
- group_selection_page();
- }
- break;
-
- case ctrl('K'):
- if (local_top <= 0) {
- info_message("No groups to delete");
- break;
- }
-
- delete_group(
- active[my_group[cur_groupnum]].name);
- active[my_group[cur_groupnum]].flag = NOTGOT;
-
- local_top--;
- for (i = cur_groupnum; i < local_top; i++) {
- my_group[i] = my_group[i+1];
- unread[i] = unread[i+1];
- }
- if (cur_groupnum >= local_top)
- cur_groupnum = local_top - 1;
-
- group_selection_page();
- break;
-
- case ctrl('Y'):
- undel_group();
- group_selection_page();
- break;
-
- case 'I': /* toggle inverse video */
- inverse_okay = !inverse_okay;
- if (inverse_okay)
- info_message("Inverse video enabled");
- else
- info_message("Inverse video disabled");
- break;
-
- case ctrl('R'): /* reset .newsrc */
- if (prompt_yn("Reset newsrc? (y/n): ")) {
- reset_newsrc();
- cur_groupnum = 0;
- group_selection_page();
- }
- break;
-
- case '$': /* reread .newsrc, no unsub groups */
- cur_groupnum = 0;
- local_top = 0;
- for (i = 0; i < num_active; i++)
- active[i].flag = NOTGOT;
- read_newsrc(TRUE);
- group_selection_page();
- break;
-
- case 's': /* subscribe to current group */
- MoveCursor(INDEX_TOP +
- (cur_groupnum-first_group_on_screen), 3);
- putchar(' ');
- fflush(stdout);
- MoveCursor(LINES, 0);
-
- subscribe(active[my_group[cur_groupnum]].name,
- ':', my_group[cur_groupnum], FALSE);
- sprintf(buf, "subscribed to %s",
- active[my_group[cur_groupnum]].name);
- info_message(buf);
- break;
-
- case 'u': /* unsubscribe to current group */
- MoveCursor(INDEX_TOP +
- (cur_groupnum-first_group_on_screen), 3);
- putchar('u');
- fflush(stdout);
- MoveCursor(LINES, 0);
-
- subscribe(active[my_group[cur_groupnum]].name,
- '!', my_group[cur_groupnum], FALSE);
- sprintf(buf, "unsubscribed to %s",
- active[my_group[cur_groupnum]].name);
- info_message(buf);
- break;
-
- case ' ':
- clear_message();
- break;
-
- case '\t':
- for (i = cur_groupnum; i < local_top; i++)
- if (unread[i] != 0)
- break;
- if (i >= local_top) {
- info_message("No more groups to read");
- break;
- }
-
- erase_group_arrow();
- cur_groupnum = i;
- if (cur_groupnum >= last_group_on_screen)
- group_selection_page();
- else
- draw_group_arrow();
- space_mode = TRUE;
- goto go_into_group;
-
- case 'g': /* prompt for a new group name */
- n = choose_new_group();
- if (n >= 0) {
- erase_group_arrow();
- cur_groupnum = n;
- if (cur_groupnum < first_group_on_screen
- || cur_groupnum >= last_group_on_screen)
- group_selection_page();
- else
- draw_group_arrow();
- }
- break;
-
- case 27: /* (ESC) common arrow keys */
- ch = ReadCh();
- if (ch == '[' || ch == 'O')
- ch = ReadCh();
- switch (ch) {
- case 'A':
- case 'D':
- case 'i':
- goto select_up;
-
- case 'B':
- case 'I':
- case 'C':
- goto select_down;
- }
- break;
-
- case 'y': /* pull in rest of groups from active */
- n = local_top;
- for (i = 0; i < num_active; i++)
- active[i].flag = NOTGOT;
- read_newsrc(FALSE);
- for (i = 0; i < num_active; i++)
- if (active[i].flag & NOTGOT) {
- active[i].flag &= ~NOTGOT;
- my_group[local_top] = i;
- unread[local_top] = -1;
- local_top++;
- }
- if (n < local_top) {
- sprintf(buf, "Added %d group%s",
- local_top - n,
- local_top - n == 1 ? "" : "s");
- group_selection_page();
- info_message(buf);
- } else
- info_message("No more groups to yank in");
- break;
-
- case ctrl('U'): /* page up */
- erase_group_arrow();
- cur_groupnum -= NOTESLINES / 2;
- if (cur_groupnum < 0)
- cur_groupnum = 0;
- if (cur_groupnum < first_group_on_screen
- || cur_groupnum >= last_group_on_screen)
- group_selection_page();
- else
- draw_group_arrow();
- break;
-
- case ctrl('D'): /* page down */
- erase_group_arrow();
- cur_groupnum += NOTESLINES / 2;
- if (cur_groupnum >= local_top)
- cur_groupnum = local_top - 1;
-
- if (cur_groupnum <= first_group_on_screen
- || cur_groupnum >= last_group_on_screen)
- group_selection_page();
- else
- draw_group_arrow();
- break;
-
- case '!':
- shell_escape();
- group_selection_page();
- break;
-
- case 'v':
- info_message(cvers);
- break;
-
- case ctrl('N'): /* line down */
- case 'j':
- select_down:
- if (cur_groupnum + 1 >= local_top)
- break;
-
- if (cur_groupnum + 1 >= last_group_on_screen) {
- cur_groupnum++;
- group_selection_page();
- } else {
- erase_group_arrow();
- cur_groupnum++;
- draw_group_arrow();
- }
- break;
-
- case ctrl('P'): /* line up */
- case 'k':
- select_up:
- if (!cur_groupnum)
- break;
-
- if (cur_groupnum <= first_group_on_screen) {
- cur_groupnum--;
- group_selection_page();
- } else {
- erase_group_arrow();
- cur_groupnum--;
- draw_group_arrow();
- }
- break;
-
- case 't': /* redraw */
- case ctrl('W'):
- case ctrl('L'):
- group_selection_page();
- break;
-
- case '\r': /* go into group */
- case '\n':
- space_mode = FALSE;
- go_into_group:
- clear_message();
- index_point = -1;
- do {
- group_page(
- active[my_group[cur_groupnum]].name);
- } while (index_point == -3);
- group_selection_page();
- break;
-
- case '/': /* search forward */
- search_group(TRUE);
- break;
-
- case '?': /* search backward */
- search_group(FALSE);
- break;
-
- case 'q': /* quit */
- tass_done(0);
-
- case 'h':
- tass_select_help();
- group_selection_page();
- break;
-
- default:
- info_message("Bad command. Type 'h' for help.");
- }
- }
- }
-
-
- group_selection_page() {
- int i;
- int n;
- char new[10];
- char subs;
-
- #ifdef SIGTSTP
- signal(SIGTSTP, select_susp);
- #endif
-
- ClearScreen();
- printf("%s\r\n", nice_time()); /* print time in upper left */
-
- if (mail_check()) { /* you have mail message */
- MoveCursor(0, 66); /* in upper right */
- printf("you have mail\n");
- }
-
- center_line(1, "Group Selection");
- MoveCursor(INDEX_TOP, 0);
-
- first_group_on_screen = (cur_groupnum / NOTESLINES) * NOTESLINES;
-
- last_group_on_screen = first_group_on_screen + NOTESLINES;
- if (last_group_on_screen >= local_top)
- last_group_on_screen = local_top;
-
- for (i = first_group_on_screen; i < last_group_on_screen; i++) {
- switch (unread[i]) {
- case -2:
- strcpy(new, "? ");
- break;
-
- case -1:
- strcpy(new, "- ");
- break;
-
- case 0:
- strcpy(new, " ");
- break;
-
- default:
- sprintf(new, "%-4d", unread[i]);
- }
-
- n = my_group[i];
- if (active[n].flag & SUBS) /* subscribed? */
- subs = ' ';
- else
- subs = 'u'; /* u next to unsubscribed groups */
-
- printf(" %c %4d %-35s %s\r\n", subs, i+1,
- active[n].name, new);
- }
-
- draw_group_arrow();
- }
-
-
- prompt_group_num(ch)
- char ch;
- {
- int num;
-
- clear_message();
-
- if ((num = parse_num(ch, "Select group> ")) == -1) {
- clear_message();
- return FALSE;
- }
- num--; /* index from 0 (internal) vs. 1 (user) */
-
- if (num >= local_top)
- num = local_top - 1;
-
- if (num >= first_group_on_screen
- && num < last_group_on_screen) {
- erase_group_arrow();
- cur_groupnum = num;
- draw_group_arrow();
- } else {
- cur_groupnum = num;
- group_selection_page();
- }
-
- return TRUE;
- }
-
- erase_group_arrow() {
- erase_arrow(INDEX_TOP + (cur_groupnum-first_group_on_screen) );
- }
-
- draw_group_arrow() {
- draw_arrow(INDEX_TOP + (cur_groupnum-first_group_on_screen) );
- }
-
- search_group(forward)
- int forward;
- {
- char buf[LEN+1];
- int i;
- extern char *regcmp();
- extern char *regex();
- char *re;
- char *prompt;
-
- clear_message();
-
- if (forward)
- prompt = "/";
- else
- prompt = "?";
-
- if (!parse_string(prompt, buf))
- return;
-
- if (strlen(buf))
- strcpy(group_search_string, buf);
- else if (!strlen(group_search_string)) {
- info_message("No search pattern");
- return;
- }
-
- i = cur_groupnum;
-
- glob_name(group_search_string, buf);
-
- if ((re = regcmp(buf, NULL)) == NULL) {
- info_message("Bad search pattern");
- return;
- }
-
- do {
- if (forward)
- i++;
- else
- i--;
-
- if (i >= local_top)
- i = 0;
- if (i < 0)
- i = local_top - 1;
-
- if (regex(re, active[my_group[i]].name) != NULL) {
- if (i >= first_group_on_screen
- && i < last_group_on_screen) {
- erase_group_arrow();
- cur_groupnum = i;
- draw_group_arrow();
- } else {
- cur_groupnum = i;
- group_selection_page();
- }
- return;
- }
- } while (i != cur_groupnum);
-
- info_message("No match");
- }
-
-
- tass_select_help() {
-
- ClearScreen();
- center_line(0, TASS_HEADER);
- center_line(1, "Group Selection Commands");
-
- MoveCursor(3, 0);
-
- printf("4 Select group 4\r\n");
- printf("^D Page down\r\n");
- printf("^R Reset .newsrc\r\n");
- printf("^U Page up\r\n");
- printf("^K Delete group\r\n");
- printf("^Y Undelete group\r\n");
- printf("<CR> Read current group\r\n");
- printf("<TAB> View next unread group\r\n");
- printf("c Mark group as all read\r\n");
- printf("g Choose a new group by name\r\n");
- printf("j Down a line\r\n");
- printf("k Up a line\r\n");
- printf("q Quit\r\n");
- printf("s Subscribe to current group\r\n");
- printf("u Unsubscribe to current group\r\n");
- printf("y Yank in groups that are not in the .newsrc\r\n");
- printf("$ Reread group list from .newsrc\r\n");
- printf("/ Search forward for group\r\n");
- printf("? Search backward for group\r\n");
-
- center_line(LINES, "-- hit any key --");
- ReadCh();
- }
-
-
- choose_new_group() {
- char buf[LEN+1];
- char *p;
- int ret;
-
- if (!parse_string("Newsgroup> ", buf))
- return -1;
-
- for (p = buf; *p && (*p == ' ' || *p == '\t'); p++) ;
- if (*p == '\0')
- return -1;
-
- ret = add_group(p, TRUE);
- if (ret < 0)
- info_message("Group not found in active file");
-
- return ret;
- }
-
-
- /*
- * Add a group to the selection list (my_group[])
- * Return the index of my_group[] if group is added or was already
- * there. Return -1 if named group is not in active[].
- */
-
- add_group(s, get_unread)
- char *s;
- int get_unread; /* look in .newsrc for sequencer unread info? */
- {
- long h;
- int i, j;
-
- { /* find the hash of the group name */
- char *t = s;
-
- h = *t++;
- while (*t)
- h = (h * 64 + *t++) % TABLE_SIZE;
- }
-
- for (i = group_hash[h]; i >= 0; i = active[i].next)
- if (strcmp(s, active[i].name) == 0) {
- for (j = 0; j < local_top; j++)
- if (my_group[j] == i)
- return j;
-
- active[i].flag &= ~NOTGOT; /* mark that we got it */
- my_group[local_top] = i;
-
- if (get_unread)
- unread[local_top] = get_line_unread(s, i);
- else
- unread[local_top] = -2;
-
- local_top++;
- return local_top - 1;
- }
-
- return -1;
- }
-
-
- @EOF
-
- chmod 644 select.c
-
- echo x - tass.h
- cat >tass.h <<'@EOF'
-
- #define LIBDIR "/usr/lib/news"
- #define SPOOLDIR "/usr/spool/news"
- #define MAILER "/bin/rmail"
-
- #define TRUE 1
- #define FALSE 0
-
- #define LEN 200
-
- #define INDEX_TOP 4
- #define NOTESLINES (LINES - INDEX_TOP - 2)
- #define RIGHT_POS (COLS - 16)
- #define MORE_POS (COLS - 20)
-
- #define MAX_FROM 25
- #define MAX_SUBJ 38
- #define TABLE_SIZE 1409
-
- /* #define MAX_SUBJ (COLS - 42) */
-
-
- struct header {
- long artnum;
- char subject[MAX_SUBJ];
- char *nore; /* pointer into subject after Re: */
- char from[MAX_FROM];
- int thread;
- long hash;
- int inthread;
- int unread; /* has this article been read? */
- /* 0 = read, 1 = unread, 2 = will return */
- };
-
- /*
- * header.artnum:
- * article number in spool directory for group
- *
- * header.nore
- * pointer into header.subject after the Re:'s.
- *
- * header.hash:
- * hash of the subject minus the re's. For fast subject comparison
- *
- * header.thread:
- * initially -1
- * points to another arts[] (struct header): zero and up
- * -2 means article has expired (wasn't found in file search
- * of spool directory for the group)
- *
- * header.inthread:
- * FALSE for the first article in a thread, TRUE for all
- * following articles in thread
- *
- * header.read:
- * boolean, has this article been read or not
- */
-
- struct group_ent {
- char *name;
- long max;
- long min;
- int next; /* next active entry in hash chain */
- int flag;
- };
-
- #define NOTGOT 0x01 /* haven't put in my_group yet */
- #define SUBS 0x02 /* subscribed to */
-
-
- extern int top;
- extern struct header *arts;
- extern long *base;
- extern int max_art;
-
- extern char userid[LEN];
- extern char homedir[LEN];
- extern char indexdir[LEN];
- extern char my_org[LEN];
- extern char active_file[LEN];
- extern char newsrc[LEN];
- extern char newnewsrc[LEN];
- extern char delgroups[LEN];
- extern int top_base;
- extern int LINES, COLS;
- extern char *str_save();
- extern char *my_malloc();
- extern char *my_realloc();
- extern int group_hash[TABLE_SIZE];
-
- extern int num_active;
- extern struct group_ent *active;
- extern int *my_group;
- extern int *unread;
- extern int max_active;
-
- extern int local_top;
- extern char *eat_re();
- extern char *nice_time();
- extern int update;
- extern int inverse_okay;
-
- extern int tass_uid;
- extern int tass_gid;
- extern int real_uid;
- extern int real_gid;
- extern int local_index;
-
- extern char *strcpy();
- extern char *strncat();
- extern char *strncpy();
- extern long atol();
-
-
- #define ctrl(c) ((c) & 0x1F)
-
- /*
- * Assertion verifier
- */
-
- #ifdef __STDC__
- #define assert(p) if(! (p)) asfail(__FILE__, __LINE__, #p); else
- #else
- #define assert(p) if(! (p)) asfail(__FILE__, __LINE__, "p"); else
- #endif
-
- #define TASS_HEADER "Tass 3.0"
-
- @EOF
-
- chmod 644 tass.h
-
- echo x - time.c
- cat >time.c <<'@EOF'
-
- #include <sys/types.h>
- #include <time.h>
-
-
- nicedate(timestr, newstr)
- char *timestr, *newstr;
- {
- int i;
-
- for (i = 0; i <= 7; i++)
- *newstr++ = timestr[i];
- if (timestr[8] != ' ')
- *newstr++ = timestr[8];
- *newstr++ = timestr[9];
- *newstr++ = ',';
- *newstr++ = ' ';
- for (i = 20;i <= 23; i++)
- *newstr++ = timestr[i];
- *newstr++ = '\0';
- }
-
- nicetime(timestr, newstr)
- char *timestr, *newstr;
- {
- int hours;
- char dayornite[3];
-
- if (timestr[11] == ' ')
- hours = timestr[12] - '0';
- else
- hours = (timestr[11]-'0')*10 + (timestr[12]-'0');
- if (hours < 12)
- strcpy(dayornite, "am");
- else
- strcpy(dayornite, "pm");
- if (hours >= 13)
- hours -= 12;
- if (!hours)
- hours = 12;
- sprintf(newstr, "%d:%c%c%s", hours, timestr[14],
- timestr[15], dayornite);
- }
-
- char *nice_time() {
- char *timestr;
- char the_date[17];
- char the_time[8];
- extern char *ctime();
- long time_now;
- static char buf[25];
-
- time(&time_now);
- timestr = ctime(&time_now);
- nicedate(timestr, the_date);
- nicetime(timestr, the_time);
- sprintf(buf,"%s %s", the_date, the_time);
- return(buf);
- }
-
- @EOF
-
- chmod 644 time.c
-
- exit 0
- --
- skrenta@blekko.commodore.com
-