home *** CD-ROM | disk | FTP | other *** search
- From: skrenta@blekko.commodore.com (Rich Skrenta)
- Newsgroups: alt.sources
- Subject: Tass 3.2 newsreader part 2/3
- Message-ID: <160@blekko.commodore.com>
- Date: 17 Apr 91 17:01:20 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:
- # mail.c main.c misc.c nntp.h
- # nntp_open.c prompt.c tass.h time.c
- #
-
- echo x - mail.c
- cat >mail.c <<'@EOF'
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #define TRUE 1
- #define FALSE 0
-
-
- char *mailbox_name = NULL;
- off_t mailbox_size;
-
-
- /*
- * Record size of mailbox so we can detect if new mail has arrived
- */
-
- mail_setup() {
- struct stat buf;
- extern char *getenv();
-
- if (mailbox_name == NULL)
- mailbox_name = getenv("MAIL");
-
- if (mailbox_name == NULL)
- mailbox_size = 0;
- else {
- if (stat(mailbox_name, &buf) >= 0)
- mailbox_size = buf.st_size;
- else
- mailbox_size = 0;
- }
- }
-
-
- /*
- * Return TRUE if new mail has arrived
- */
-
- mail_check() {
- struct stat buf;
-
- if (mailbox_name != NULL
- && stat(mailbox_name, &buf) >= 0
- && mailbox_size < buf.st_size)
- return TRUE;
-
- return FALSE;
- }
-
- @EOF
-
- chmod 640 mail.c
-
- echo x - main.c
- cat >main.c <<'@EOF'
-
- /*
- * Tass, a visual Usenet news reader
- * (c) Copyright 1990 by Rich Skrenta
- *
- * Distribution agreement:
- *
- * You may freely copy or redistribute this software, so long
- * as there is no profit made from its use, sale, trade or
- * reproduction. You may not change this copyright notice,
- * and it must be included prominently in any copy made.
- */
-
- #include <stdio.h>
- #include <signal.h>
- #include <termio.h> /* for struct winsize */
- #ifdef SCO_UNIX
- #include <sys/types.h>
- #include <sys/stream.h>
- #include <sys/ptem.h>
- #endif
- #include "tass.h"
-
-
- int LINES, COLS;
-
- int max_active;
- struct group_ent *active; /* active file */
- int group_hash[TABLE_SIZE]; /* group name --> active[] */
- int *my_group; /* .newsrc --> active[] */
- int *unread; /* highest art read in group */
- int num_active; /* one past top of active */
- int local_top; /* one past top of my_group */
- int update = FALSE; /* update index files only mode */
-
- struct header *arts;
- long *base;
- int max_art;
- int top = 0;
- int top_base;
-
- int tass_uid;
- int tass_gid;
- int real_uid;
- int real_gid;
-
- int local_index; /* do private indexing? */
-
- char *cvers = "Tass 3.2 (c) Copyright 1991 by Rich Skrenta. All rights reserved";
-
-
- #ifdef SIGTSTP
- void
- main_susp(i)
- int i;
- {
-
- Raw(FALSE);
- putchar('\n');
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
-
- signal(SIGTSTP, main_susp);
- mail_setup();
- Raw(TRUE);
- }
- #endif
-
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- extern int optind, opterr;
- extern char *optarg;
- int errflag = 0;
- int i;
- int c;
- extern char group_search_string[];
- extern char author_search_string[];
- extern char subject_search_string[];
- extern char *is_remote();
-
- group_search_string[0] = '\0';
- author_search_string[0] = '\0';
- subject_search_string[0] = '\0';
-
- hash_init();
- for (i = 0; i < TABLE_SIZE; i++)
- group_hash[i] = -1;
-
- signal(SIGPIPE, SIG_IGN);
- #ifdef SIGTSTP
- signal(SIGTSTP, main_susp);
- #endif
-
- tass_uid = geteuid();
- tass_gid = getegid();
- real_uid = getuid();
- real_gid = getgid();
-
- init_selfinfo(); /* set up char *'s: homedir, newsrc, etc. */
- init_alloc(); /* allocate initial array sizes */
-
- if (tass_uid == real_uid) { /* run out of someone's account */
- local_index = TRUE; /* index in their home directory */
- mkdir(indexdir, 0755);
- } else /* we're setuid, index in /usr/spool/news */
- local_index = FALSE;
-
- while ((c = getopt(argc, argv, "f:u")) != -1) {
- switch(c) {
- case 'f':
- strcpy(newsrc, optarg);
- break;
-
- case 'u':
- update = TRUE;
- break;
-
- case '?':
- default:
- errflag++;
- }
- }
-
- if (errflag) {
- fprintf(stderr, "usage: tass [options] [newsgroups]\n");
- fprintf(stderr, " -f file use file instead of $HOME/.newsrc\n");
- fprintf(stderr, " -u update index files only\n");
- exit(1);
- }
-
- if (!update)
- printf("Tass 3.2%s\n", is_remote());
-
- nntp_startup(); /* connect to server if we're using nntp */
- read_active(); /* load the active file into active[] */
-
- if (optind < argc) {
- while (optind < argc) {
- if (add_group(argv[optind], TRUE) < 0)
- fprintf(stderr,
- "group %s not found in active file\n",
- argv[optind]);
- optind++;
- }
- } else
- read_newsrc(TRUE);
-
- if (update) { /* index file updater only */
- do_update();
- exit(0);
- }
-
- if (InitScreen() == FALSE) {
- fprintf(stderr,"Screen initialization failed\n");
- exit(1);
- }
-
- ScreenSize(&LINES, &COLS);
- Raw(TRUE);
-
- #ifdef TIOCGWINSZ
- {
- struct winsize win;
-
- if (ioctl(0, TIOCGWINSZ, &win) == 0) {
- if (win.ws_row != 0)
- LINES = win.ws_row - 1;
- if (win.ws_col != 0)
- COLS = win.ws_col;
- }
- }
- #endif
-
- mail_setup(); /* record mailbox size for "you have mail" */
- selection_index();
-
- tass_done(0);
- }
-
-
-
- tass_done(ret)
- int ret;
- {
-
- nntp_finish(); /* close connection if we're using nntp */
- MoveCursor(LINES, 0);
- printf("\r\n");
- Raw(FALSE);
- exit(ret);
- }
-
-
- /*
- * Dynamic table management
- * These settings are memory conservative: small initial allocations
- * and a 50% expansion on table overflow. A fast vm system with
- * much memory might want to start with higher initial allocations
- * and a 100% expansion on overflow, especially for the arts[] array.
- */
-
- init_alloc() {
-
- max_active = 100; /* initial alloc */
-
- active = (struct group_ent *) my_malloc(sizeof(*active) * max_active);
- my_group = (int *) my_malloc(sizeof(int) * max_active);
- unread = (int *) my_malloc(sizeof(int) * max_active);
-
- max_art = 300; /* initial alloc */
-
- arts = (struct header *) my_malloc(sizeof(*arts) * max_art);
- base = (long *) my_malloc(sizeof(long) * max_art);
- }
-
-
- expand_art() {
-
- max_art += max_art / 2; /* increase by 50% */
-
- arts = (struct header *) my_realloc(arts, sizeof(*arts) * max_art);
- base = (long *) my_realloc(base, sizeof(long) * max_art);
- }
-
-
- expand_active() {
-
- max_active += max_active / 2; /* increase by 50% */
-
- active = (struct group_ent *) my_realloc(active,
- sizeof(*active) * max_active);
- my_group = (int *) my_realloc(my_group, sizeof(int) * max_active);
- unread = (int *) my_realloc(unread, sizeof(int) * max_active);
- }
-
-
- /*
- * Load the active file into active[]
- */
-
- read_active()
- {
- FILE *fp;
- char *p, *q;
- char buf[200];
- long h;
- int i;
- extern long hash_groupname();
- FILE *open_active_fp();
-
- num_active = 0;
-
- fp = open_active_fp();
- if (fp == NULL) {
- fprintf(stderr, "can't get active file\n");
- exit(1);
- }
-
- while (fgets(buf, 200, fp) != NULL) {
- for (p = buf; *p && *p != ' '; p++) ;
- if (*p != ' ') {
- fprintf(stderr, "active file corrupt\n");
- continue;
- }
- *p++ = '\0';
-
- if (num_active >= max_active)
- expand_active();
-
- h = hash_groupname(buf);
-
- if (group_hash[h] == -1)
- group_hash[h] = num_active;
- else { /* hash linked list chaining */
- for (i = group_hash[h]; active[i].next >= 0;
- i = active[i].next) {
- if (strcmp(active[i].name, buf) == 0)
- goto read_active_continue;
- /* kill dups */
- }
- if (strcmp(active[i].name, buf) == 0)
- goto read_active_continue;
- active[i].next = num_active;
- }
-
- for (q = p; *q && *q != ' '; q++) ;
- if (*q != ' ') {
- fprintf(stderr, "active file corrupt\n");
- continue;
- }
-
- active[num_active].name = str_save(buf);
- active[num_active].max = atol(p);
- active[num_active].min = atol(q);
- active[num_active].next = -1; /* hash chaining */
- active[num_active].flag = NOTGOT; /* not in my_group[] yet */
-
- num_active++;
-
- read_active_continue:;
-
- }
-
- fclose(fp);
- }
-
-
-
- /*
- * Read $HOME/.newsrc into my_group[]. my_group[] ints point to
- * active[] entries. Sub_only determines whether we just read
- * subscribed groups or all of them.
- */
-
- read_newsrc(sub_only)
- int sub_only; /* TRUE=subscribed groups only, FALSE=all groups */
- {
- FILE *fp;
- char *p;
- char buf[8192];
- char c;
- int i;
-
- local_top = 0;
-
- fp = fopen(newsrc, "r");
- if (fp == NULL) { /* attempt to make a .newsrc */
- for (i = 0; i < num_active; i++) {
- if (local_top >= max_active)
- expand_active();
- my_group[local_top] = i;
- active[i].flag = 0;
- unread[local_top] = -1;
- local_top++;
- }
- write_newsrc();
- return;
- }
-
- while (fgets(buf, 8192, fp) != NULL) {
- p = buf;
- while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- *p++ = '\0';
- if (c == '!' && sub_only)
- continue; /* unsubscribed */
-
- if ((i = add_group(buf, FALSE)) < 0) {
- fprintf(stderr, "group %s not found in active file\n", buf);
- continue;
- }
-
- if (c != '!') /* if we're subscribed to it */
- active[my_group[i]].flag |= SUBS;
-
- unread[i] = parse_unread(p, my_group[i]);
- }
- fclose(fp);
- }
-
-
- /*
- * Write a new newsrc from my_group[] and active[]
- * Used to a create a new .newsrc if there isn't one already, or when
- * the newsrc is reset.
- */
-
- write_newsrc() {
- FILE *fp;
- int i;
-
- setuid(real_uid); /* become the user to write in his */
- setgid(real_gid); /* home directory */
-
- fp = fopen(newsrc, "w");
- if (fp == NULL)
- goto write_newsrc_done;
-
- for (i = 0; i < num_active; i++)
- fprintf(fp, "%s: \n", active[i].name);
-
- fclose(fp);
-
- write_newsrc_done:
- setuid(tass_uid);
- setgid(tass_gid);
- }
-
-
- /*
- * Load the sequencer rang lists and mark arts[] according to the
- * .newsrc info for a particular group. i.e. rec.arts.comics: 1-94,97
- */
-
- read_newsrc_line(group)
- char *group;
- {
- FILE *fp;
- char buf[8192];
- char *p;
-
- fp = fopen(newsrc, "r");
- if (fp == NULL)
- return;
-
- while (fgets(buf, 8192, fp) != NULL) {
- p = buf;
- while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- p++;
- *p++ = '\0';
- if (strcmp(buf, group) != 0)
- continue;
- parse_seq(p);
- break;
- }
-
- fclose(fp);
- }
-
-
- /*
- * For our current group, update the sequencer information in .newsrc
- */
-
- update_newsrc(group, groupnum)
- char *group;
- int groupnum; /* index into active[] for this group */
- {
- FILE *fp;
- FILE *newfp;
- char buf[8192];
- char *p;
- char c;
- int gotit = FALSE;
-
- setuid(real_uid);
- setgid(real_gid);
-
- fp = fopen(newsrc, "r");
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL)
- goto update_done;
-
- if (fp != NULL) {
- while (fgets(buf, 8192, fp) != NULL) {
- for (p = buf; *p; p++)
- if (*p == '\n') {
- *p = '\0';
- break;
- }
-
- p = buf;
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- if (strcmp(buf, group) == 0) {
- fprintf(newfp, "%s%c ", buf, c);
- gotit = TRUE;
- print_seq(newfp, groupnum);
- fprintf(newfp, "\n");
- } else
- fprintf(newfp, "%s%c%s\n", buf, c, p);
- }
- fclose(fp);
- }
-
- fclose(newfp);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
-
- update_done:
- setuid(tass_uid);
- setgid(tass_gid);
- }
-
-
- /*
- * Subscribe/unsubscribe to a group in .newsrc. ch should either be
- * '!' to unsubscribe or ':' to subscribe. num is the group's index
- * in active[].
- */
-
- subscribe(group, ch, num, out_seq)
- char *group;
- char ch;
- int num;
- int out_seq; /* output sequencer info? */
- {
- FILE *fp;
- FILE *newfp;
- char buf[8192];
- char *p;
- char c;
- int gotit = FALSE;
-
- if (ch == '!')
- active[num].flag &= ~SUBS;
- else
- active[num].flag |= SUBS;
-
- setuid(real_uid);
- setgid(real_gid);
-
- fp = fopen(newsrc, "r");
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL)
- goto subscribe_done;
-
- if (fp != NULL) {
- while (fgets(buf, 8192, fp) != NULL) {
- for (p = buf; *p; p++)
- if (*p == '\n') {
- *p = '\0';
- break;
- }
-
- p = buf;
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- if (strcmp(buf, group) == 0) {
- fprintf(newfp, "%s%c%s\n", buf, ch, p);
- gotit = TRUE;
- } else
- fprintf(newfp, "%s%c%s\n", buf, c, p);
- }
- fclose(fp);
- }
-
- if (!gotit) {
- if (out_seq) {
- fprintf(newfp, "%s%c ", group, ch);
- print_seq(newfp, num);
- fprintf(newfp, "\n");
- } else
- fprintf(newfp, "%s%c\n", group, ch);
- }
-
- fclose(newfp);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
-
- subscribe_done:
- setuid(tass_uid);
- setgid(tass_gid);
- }
-
-
- print_seq(fp, groupnum)
- FILE *fp;
- int groupnum; /* index into active[] for this group */
- {
- int i;
- int flag = FALSE;
-
- if (top <= 0) {
- if (active[groupnum].min > 1) {
- fprintf(fp, "1-%ld", active[groupnum].min);
- fflush(fp);
- }
- return;
- }
-
- i = 0;
- if (arts[0].artnum > 1) {
- for (; i < top && !arts[i].unread; i++) ;
- if (i > 0)
- fprintf(fp, "1-%ld", arts[i-1].artnum);
- else
- fprintf(fp, "1-%ld", arts[0].artnum - 1);
- flag = TRUE;
- }
-
- for (; i < top; i++) {
- if (!arts[i].unread) {
- if (flag)
- fprintf(fp, ",");
- else
- flag = TRUE;
- fprintf(fp, "%ld", arts[i].artnum);
- if (i+1 < top && !arts[i+1].unread) {
- while (i+1 < top && !arts[i+1].unread)
- i++;
- fprintf(fp, "-%ld", arts[i].artnum);
- }
- }
- }
-
- if (!flag && active[groupnum].min > 1)
- fprintf(fp, "1-%ld", active[groupnum].min);
- fflush(fp);
- }
-
-
- parse_seq(s)
- char *s;
- {
- long low, high;
- int i;
-
- while (*s) {
- while (*s && (*s < '0' || *s > '9'))
- s++;
-
- if (*s && *s >= '0' && *s <= '9') {
- low = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- if (*s == '-') {
- s++;
- high = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- } else
- high = low;
-
- for (i = 0; i < top; i++)
- if (arts[i].artnum >= low &&
- arts[i].artnum <= high)
- arts[i].unread = 0;
- }
- }
- }
-
-
- parse_unread(s, groupnum)
- char *s;
- int groupnum; /* index for group in active[] */
- {
- long low, high;
- long last_high;
- int i;
- int sum = 0;
- int gotone = FALSE;
- int n;
-
- /*
- * Read the first range from the .newsrc sequencer information. If the
- * top of the first range is higher than what the active file claims is
- * the bottom, use it as the new bottom instead
- */
-
- high = 0;
- if (*s) {
- while (*s && (*s < '0' || *s > '9'))
- s++;
-
- if (*s && *s >= '0' && *s <= '9') {
- low = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- if (*s == '-') {
- s++;
- high = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- } else
- high = low;
- gotone = TRUE;
- }
- }
-
- if (high < active[groupnum].min)
- high = active[groupnum].min;
-
- while (*s) {
- last_high = high;
-
- while (*s && (*s < '0' || *s > '9'))
- s++;
-
- if (*s && *s >= '0' && *s <= '9') {
- low = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- if (*s == '-') {
- s++;
- high = atol(s);
- while (*s && *s >= '0' && *s <= '9')
- s++;
- } else
- high = low;
-
- if (low > last_high) /* otherwise seq out of order */
- sum += (low - last_high) - 1;
- }
- }
-
- if (gotone) {
- if (active[groupnum].max > high)
- sum += active[groupnum].max - high;
- return sum;
- }
-
- n = (int) (active[groupnum].max - active[groupnum].min);
- if (n < 2)
- return 0;
-
- return -1;
- }
-
-
- get_line_unread(group, groupnum)
- char *group;
- int groupnum; /* index for group in active[] */
- {
- FILE *fp;
- char buf[8192];
- char *p;
- int ret = -1;
-
- fp = fopen(newsrc, "r");
- if (fp == NULL)
- return -1;
-
- while (fgets(buf, 8192, fp) != NULL) {
- p = buf;
- while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- p++;
- *p++ = '\0';
- if (strcmp(buf, group) != 0)
- continue;
- ret = parse_unread(p, groupnum);
- break;
- }
-
- fclose(fp);
- return ret;
- }
-
-
- reset_newsrc()
- {
- FILE *fp;
- FILE *newfp;
- char buf[8192];
- char *p;
- char c;
- int gotit = FALSE;
- int i;
-
- setuid(real_uid);
- setgid(real_gid);
-
- fp = fopen(newsrc, "r");
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL)
- goto update_done;
-
- if (fp != NULL) {
- while (fgets(buf, 8192, fp) != NULL) {
- for (p = buf; *p && *p != '\n'; p++) ;
- *p = '\0';
-
- p = buf;
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- fprintf(newfp, "%s%c\n", buf, c);
- }
- fclose(fp);
- }
-
- fclose(newfp);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
-
- update_done:
- setuid(tass_uid);
- setgid(tass_gid);
-
- for (i = 0; i < local_top; i++)
- unread[i] = -1;
- }
-
-
- delete_group(group)
- char *group;
- {
- FILE *fp;
- FILE *newfp;
- char buf[8192];
- char *p;
- char c;
- int gotit = FALSE;
- FILE *del;
-
- setuid(real_uid);
- setgid(real_gid);
-
- fp = fopen(newsrc, "r");
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL)
- goto del_done;
- del = fopen(delgroups, "a+");
- if (del == NULL)
- goto del_done;
-
- if (fp != NULL) {
- while (fgets(buf, 8192, fp) != NULL) {
- for (p = buf; *p && *p != '\n'; p++) ;
- *p = '\0';
-
- p = buf;
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- if (strcmp(buf, group) == 0) {
- fprintf(del, "%s%c%s\n", buf, c, p);
- gotit = TRUE;
- } else
- fprintf(newfp, "%s%c%s\n", buf, c, p);
- }
- fclose(fp);
- }
-
- fclose(newfp);
-
- if (!gotit)
- fprintf(del, "%s! \n", group);
-
- fclose(del);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
-
- del_done:
- setuid(tass_uid);
- setgid(tass_gid);
- }
-
-
- undel_group() {
- FILE *del;
- FILE *newfp;
- FILE *fp;
- char buf[2][8192];
- char *p;
- int which = 0;
- long h;
- extern int cur_groupnum;
- int i, j;
- char c;
-
- setuid(real_uid);
- setgid(real_gid);
-
- del = fopen(delgroups, "r");
- if (del == NULL) {
- setuid(tass_uid);
- setgid(tass_gid);
- return FALSE;
- }
- unlink(delgroups);
- newfp = fopen(delgroups, "w");
- if (newfp == NULL) {
- setuid(tass_uid);
- setgid(tass_gid);
- return FALSE;
- }
-
- buf[0][0] = '\0';
- buf[1][0] = '\0';
-
- while (fgets(buf[which], 8192, del) != NULL) {
- which = !which;
- if (*buf[which])
- fputs(buf[which], newfp);
- }
-
- fclose(del);
- fclose(newfp);
- which = !which;
-
- if (!*buf[which]) {
- setuid(tass_uid);
- setgid(tass_gid);
- return FALSE;
- }
-
- for (p = buf[which]; *p && *p != '\n'; p++) ;
- *p = '\0';
-
- p = buf[which];
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- { /* find the hash of the group name */
- char *t = buf[which];
-
- h = *t++;
- while (*t)
- h = (h * 64 + *t++) % TABLE_SIZE;
- }
-
- for (i = group_hash[h]; i >= 0; i = active[i].next) {
- if (strcmp(buf[which], active[i].name) == 0) {
- for (j = 0; j < local_top; j++)
- if (my_group[j] == i) {
- setuid(tass_uid);
- setgid(tass_gid);
- return j;
- }
-
- active[i].flag &= ~NOTGOT; /* mark that we got it */
- if (c != '!')
- active[i].flag |= SUBS;
-
- if (local_top >= max_active)
- expand_active();
- local_top++;
- for (j = local_top; j > cur_groupnum; j--) {
- my_group[j] = my_group[j-1];
- unread[j] = unread[j-1];
- }
- my_group[cur_groupnum] = i;
- unread[cur_groupnum] = parse_unread(p, i);
-
- fp = fopen(newsrc, "r");
- if (fp == NULL) {
- setuid(tass_uid);
- setgid(tass_gid);
- return FALSE;
- }
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL) {
- fclose(fp);
- setuid(tass_uid);
- setgid(tass_gid);
- return FALSE;
- }
- i = 0;
- while (fgets(buf[!which], 8192, fp) != NULL) {
- for (p = buf[!which]; *p && *p != '\n'; p++) ;
- *p = '\0';
-
- p = buf[!which];
- while (*p && *p!=' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- while (i < cur_groupnum) {
- if (strcmp(buf[!which],
- active[my_group[i]].name) == 0) {
- fprintf(newfp, "%s%c%s\n",
- buf[!which], c, p);
- goto foo_cont;
- }
- i++;
- }
- fprintf(newfp, "%s%c%s\n", buf[which], c, p);
- fprintf(newfp, "%s%c%s\n", buf[!which], c, p);
- break;
- foo_cont:;
- }
-
- while (fgets(buf[!which], 8192, fp) != NULL)
- fputs(buf[!which], newfp);
-
- fclose(newfp);
- fclose(fp);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
- setuid(tass_uid);
- setgid(tass_gid);
- return TRUE;
- }
- }
-
- setuid(tass_uid);
- setgid(tass_gid);
-
- return FALSE;
- }
-
-
- mark_group_read(group, groupnum)
- char *group;
- int groupnum; /* index into active[] for this group */
- {
- FILE *fp;
- FILE *newfp;
- char buf[8192];
- char *p;
- char c;
- int gotit = FALSE;
-
- if (active[groupnum].max < 2)
- return;
-
- setuid(real_uid);
- setgid(real_gid);
-
- fp = fopen(newsrc, "r");
- newfp = fopen(newnewsrc, "w");
- if (newfp == NULL)
- goto mark_group_read_done;
-
- if (fp != NULL) {
- while (fgets(buf, 8192, fp) != NULL) {
- for (p = buf; *p; p++)
- if (*p == '\n') {
- *p = '\0';
- break;
- }
-
- p = buf;
- while (*p && *p != ' ' && *p != ':' && *p != '!')
- p++;
- c = *p;
- if (c != '\0')
- *p++ = '\0';
-
- if (c != '!')
- c = ':';
-
- if (strcmp(buf, group) == 0) {
- fprintf(newfp, "%s%c 1-%ld\n", buf, c,
- active[groupnum].max);
- gotit = TRUE;
- } else
- fprintf(newfp, "%s%c%s\n", buf, c, p);
- }
- fclose(fp);
- }
-
- fclose(newfp);
- unlink(newsrc);
- link(newnewsrc, newsrc);
- unlink(newnewsrc);
-
- mark_group_read_done:
- setuid(tass_uid);
- setgid(tass_gid);
- }
-
-
- long
- hash_groupname(buf) /* hash group name for fast lookup later */
- char *buf;
- {
- char *t = buf;
- unsigned long h;
-
- h = *t++;
- while (*t)
- h = ((h << 1) ^ *t++) % TABLE_SIZE;
- /* h = (h * 64 + *t++) % TABLE_SIZE; */
-
- return h;
- }
-
-
- #ifdef M_XENIX
- mkdir(path, mode)
- char *path;
- int mode;
- {
- char buf[200];
-
- sprintf(buf, "mkdir %s", path);
- system(buf);
- chmod(path, mode);
- }
- #endif
-
- @EOF
-
- chmod 644 main.c
-
- echo x - misc.c
- cat >misc.c <<'@EOF'
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include <pwd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "tass.h"
-
-
- char active_file[LEN];
- char homedir[LEN];
- char userid[LEN];
- char delgroups[LEN];
- char newsrc[LEN];
- char newnewsrc[LEN];
- char indexdir[LEN];
- char my_org[LEN]; /* organization */
- char sig[LEN];
- char signature[LEN];
-
-
- /*
- * Which base note (an index into base[]) does a respnum
- * (an index into arts[]) corresponsd to?
- *
- * In other words, base[] points to an entry in arts[] which is
- * the head of a thread, linked with arts[].thread. For any q: arts[q],
- * find i such that base[i]->arts[n]->arts[o]->...->arts[q]
- */
-
- which_base(n)
- int n;
- {
- int i, j;
-
- for (i = 0; i < top_base; i++)
- for (j = base[i]; j >= 0; j = arts[j].thread)
- if (j == n)
- return i;
-
- fprintf(stderr, "can't find base article\n");
- return 0;
- }
-
-
- /*
- * Find how deep in a thread a response is. Start counting at zero
- */
-
- which_resp(n)
- int n;
- {
- int i, j;
- int num = 0;
-
- i = which_base(n);
-
- for (j = base[i]; j != -1; j = arts[j].thread)
- if (j == n)
- break;
- else
- num++;
-
- return num;
- }
-
-
- /*
- * Given an index into base[], find the number of responses for
- * that basenote
- */
-
- nresp(n)
- int n;
- {
- int i;
- int oldi = -3;
- int sum = 0;
-
- assert(n < top_base);
-
- for (i = base[n]; i != -1; i = arts[i].thread) {
- assert(i != -2);
- assert(i != oldi);
- oldi = i;
- sum++;
- }
-
- return sum - 1;
- }
-
-
- asfail(file, line, cond)
- char *file;
- int line;
- char *cond;
- {
- fprintf(stderr, "tass: assertion failure: %s (%d): %s\n",
- file, line, cond);
- exit(1);
- }
-
-
- /*
- * init_selfinfo
- * Deterimines users home directory, userid, and a path
- * for an rc file in the home directory
- */
-
- init_selfinfo()
- {
- struct passwd *myentry;
- extern struct passwd *getpwuid();
- struct stat sb;
- char nam[LEN];
- char *p;
- extern char *getenv();
- FILE *fp;
-
- myentry = getpwuid(getuid());
- strcpy(userid, myentry->pw_name);
- strcpy(homedir, myentry->pw_dir);
-
- sprintf(signature, "%s/.signature", homedir);
- sprintf(sig, "%s/.Sig", homedir);
- sprintf(newsrc, "%s/.newsrc", homedir);
- sprintf(newnewsrc, "%s/.newnewsrc", homedir);
- sprintf(delgroups, "%s/.delgroups", homedir);
- sprintf(indexdir, "%s/.tindx", homedir);
- sprintf(active_file, "%s/active", LIBDIR);
- if (stat(active_file, &sb) >= 0)
- goto got_active;
-
- /*
- * I hate forgetting to define LIBDIR correctly. Guess a
- * couple of likely places if it's not where LIBDIR says it is.
- */
-
- strcpy(active_file, "/usr/lib/news/active");
- if (stat(active_file, &sb) >= 0)
- goto got_active;
-
- strcpy(active_file, "/usr/local/lib/news/active");
- if (stat(active_file, &sb) >= 0)
- goto got_active;
-
- strcpy(active_file, "/usr/public/lib/news/active");
- if (stat(active_file, &sb) >= 0)
- goto got_active;
-
- /*
- * Oh well. Revert to what LIBDIR says it is to produce a
- * useful error message when read_active() fails later.
- */
-
- sprintf(active_file, "%s/active", LIBDIR);
-
- got_active:
-
- *my_org = '\0';
- p = getenv("ORGANIZATION");
- if (p != NULL) {
- strcpy(my_org, p);
- goto got_org;
- }
-
- sprintf(nam, "%s/organization", LIBDIR);
- fp = fopen(nam, "r");
-
- if (fp == NULL) {
- sprintf(nam, "/usr/lib/news/organization");
- fp = fopen(nam, "r");
- }
-
- if (fp == NULL) {
- sprintf(nam, "/usr/local/lib/news/organization");
- fp = fopen(nam, "r");
- }
-
- if (fp == NULL) {
- sprintf(nam, "/usr/public/lib/news/organization");
- fp = fopen(nam, "r");
- }
-
- if (fp == NULL) {
- sprintf(nam, "/etc/organization");
- fp = fopen(nam, "r");
- }
-
- if (fp != NULL) {
- if (fgets(my_org, LEN, fp) != NULL) {
- for (p = my_org; *p && *p != '\n'; p++) ;
- *p = '\0';
- }
- fclose(fp);
- }
-
- got_org:;
-
- }
-
-
- char *
- my_malloc(size)
- unsigned size;
- {
- char *p;
- extern char *malloc();
-
- p = malloc(size);
- if (p == NULL) {
- fprintf(stderr, "tass: out of memory\n");
- exit(1);
- }
- return p;
- }
-
-
- char *
- my_realloc(p, size)
- char *p;
- unsigned size;
- {
- extern char *malloc();
- extern char *realloc();
-
- if (p == NULL)
- p = malloc(size);
- else
- p = realloc(p, size);
-
- if (p == NULL) {
- fprintf(stderr, "tass: out of memory\n");
- exit(1);
- }
- return p;
- }
-
-
- char *
- str_save(s)
- char *s;
- {
- char *p;
-
- assert(s != NULL);
-
- p = my_malloc(strlen(s) + 1);
- strcpy(p, s);
-
- return(p);
- }
-
-
- copy_fp(a, b, prefix)
- FILE *a;
- FILE *b;
- char *prefix;
- {
- char buf[8192];
-
- while (fgets(buf, 8192, a) != NULL)
- fprintf(b, "%s%s", prefix, buf);
- }
-
-
- char *
- get_val(env, def)
- char *env; /* Environment variable we're looking for */
- char *def; /* Default value if no environ value found */
- {
- extern char *getenv();
- char *ptr;
-
- if ((ptr = getenv(env)) != NULL)
- return(ptr);
- else
- return(def);
- }
-
-
- invoke_editor(nam)
- char *nam;
- {
- char buf[200];
- static int first = TRUE;
- static char editor[200];
- int ret;
-
- if (first) {
- strcpy(editor, get_val("EDITOR", DEF_EDITOR));
- first = FALSE;
- }
-
- sprintf(buf, "%s %s", editor, nam);
- printf("\r%s\n", buf);
- ret = invoke_cmd(buf);
- setuid(real_uid);
- setgid(real_gid);
-
- return ret;
- }
-
-
- invoke_cmd(nam)
- char *nam;
- {
- int ret;
- #ifdef SIGTSTP
- void (*susp)();
- #endif
-
- Raw(FALSE);
- setuid(real_uid);
- setgid(real_gid);
-
- #ifdef SIGTSTP
- susp = signal(SIGTSTP, SIG_DFL);
- #endif
-
- ret = system(nam);
-
- #ifdef SIGTSTP
- signal(SIGTSTP, susp);
- #endif
-
- setuid(tass_uid);
- setgid(tass_gid);
- Raw(TRUE);
-
- return ret == 0;
- }
-
-
- shell_escape() {
- char shell[LEN];
- char *p;
- #ifdef SIGTSTP
- void (*susp)();
- #endif
-
- if (!parse_string("!", shell))
- strcpy(shell, get_val("SHELL", "/bin/sh"));
-
- for (p = shell; *p && (*p == ' ' || *p == '\t'); p++) ;
-
- if (!*p)
- strcpy(shell, get_val("SHELL", "/bin/sh"));
-
- Raw(FALSE);
-
- setuid(real_uid);
- setgid(real_gid);
-
- fputs("\r\n", stdout);
-
- #ifdef SIGTSTP
- susp = signal(SIGTSTP, SIG_DFL);
- #endif
-
- system(p);
-
- #ifdef SIGTSTP
- signal(SIGTSTP, susp);
- #endif
-
- setuid(tass_uid);
- setgid(tass_gid);
-
- Raw(TRUE);
-
- continue_prompt();
- mail_setup();
- }
-
-
- /*
- * 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];
- }
-
-
-
- /*
- * Find the next unread response in this group
- */
-
- next_unread(n)
- int n;
- {
-
- while (n >= 0) {
- if (arts[n].unread == 1)
- return n;
- n = next_response(n);
- }
-
- return -1;
- }
-
-
- /*
- * Find the previous unread response in this thread
- */
-
- prev_unread(n)
- int n;
- {
-
- while (n >= 0) {
- if (arts[n].unread == 1)
- return n;
- n = prev_response(n);
- }
-
- return -1;
- }
-
-
- add_signature(fp, flag)
- FILE *fp;
- int flag;
- {
- FILE *sigf;
-
- sigf = fopen(signature, "r");
- if (sigf != NULL) {
- if (flag) {
- fprintf(fp, "\n--\n");
- copy_fp(sigf, fp, "");
- }
- fclose(sigf);
- return;
- }
-
- sigf = fopen(sig, "r");
- if (sigf != NULL) {
- fprintf(fp, "\n--\n");
- copy_fp(sigf, fp, "");
- fclose(sigf);
- }
- }
-
-
- make_lower(s, t)
- char *s;
- char *t;
- {
-
- while (*s) {
- if (isupper(*s))
- *t = tolower(*s);
- else
- *t = *s;
- s++;
- t++;
- }
- *t = 0;
- }
-
-
- match(s, t, n)
- char *s;
- char *t;
- int n;
- {
-
- while (*t) {
- if (*s == *t && strncmp(s, t, n) == 0)
- return TRUE;
- t++;
- }
-
- return FALSE;
- }
-
- @EOF
-
- chmod 644 misc.c
-
- echo x - nntp.h
- cat >nntp.h <<'@EOF'
- /* nntp.h -- nntp support for tass */
-
- /* Changed a bit so nntp knows about Tass */
-
- /*
- * This file is originally from the nntp 1.5 source,
- * but modified a bit
- */
-
- #define NNTP_SERVER "/etc/nntpserver"
-
- /*
- * External routine declarations
- */
-
- extern char *getserverbyfile();
- extern int server_init();
- extern int get_tcp_socket();
- extern int handle_server_response();
- extern void put_server();
- extern int get_server();
- extern void close_server();
-
- /*
- * External file descriptors for the server connection
- */
-
- extern FILE *ser_wr_fp;
- extern FILE *ser_wr_fp;
-
-
- /*
- * Response codes for NNTP server
- *
- * @(#)nntp.h 1.7 (Berkeley) 1/11/88
- *
- * First digit:
- *
- * 1xx Informative message
- * 2xx Command ok
- * 3xx Command ok so far, continue
- * 4xx Command was correct, but couldn't be performed
- * for some specified reason.
- * 5xx Command unimplemented, incorrect, or a
- * program error has occured.
- *
- * Second digit:
- *
- * x0x Connection, setup, miscellaneous
- * x1x Newsgroup selection
- * x2x Article selection
- * x3x Distribution
- * x4x Posting
- */
-
- #define CHAR_INF '1'
- #define CHAR_OK '2'
- #define CHAR_CONT '3'
- #define CHAR_ERR '4'
- #define CHAR_FATAL '5'
-
- #define INF_HELP 100 /* Help text on way */
- #define INF_DEBUG 199 /* Debug output */
-
- #define OK_CANPOST 200 /* Hello; you can post */
- #define OK_NOPOST 201 /* Hello; you can't post */
- #define OK_SLAVE 202 /* Slave status noted */
- #define OK_GOODBYE 205 /* Closing connection */
- #define OK_GROUP 211 /* Group selected */
- #define OK_GROUPS 215 /* Newsgroups follow */
-
- #define OK_TASSINDEX 218 /* Tass index follows */
-
- #define OK_ARTICLE 220 /* Article (head & body) follows */
- #define OK_HEAD 221 /* Head follows */
- #define OK_BODY 222 /* Body follows */
- #define OK_NOTEXT 223 /* No text sent -- stat, next, last */
- #define OK_NEWNEWS 230 /* New articles by message-id follow */
- #define OK_NEWGROUPS 231 /* New newsgroups follow */
- #define OK_XFERED 235 /* Article transferred successfully */
- #define OK_POSTED 240 /* Article posted successfully */
-
- #define CONT_XFER 335 /* Continue to send article */
- #define CONT_POST 340 /* Continue to post article */
-
- #define ERR_GOODBYE 400 /* Have to hang up for some reason */
- #define ERR_NOGROUP 411 /* No such newsgroup */
- #define ERR_NCING 412 /* Not currently in newsgroup */
-
- #define ERR_NOTASS 418 /* No tass index for this group */
-
- #define ERR_NOCRNT 420 /* No current article selected */
- #define ERR_NONEXT 421 /* No next article in this group */
- #define ERR_NOPREV 422 /* No previous article in this group */
- #define ERR_NOARTIG 423 /* No such article in this group */
- #define ERR_NOART 430 /* No such article at all */
- #define ERR_GOTIT 435 /* Already got that article, don't send */
- #define ERR_XFERFAIL 436 /* Transfer failed */
- #define ERR_XFERRJCT 437 /* Article rejected, don't resend */
- #define ERR_NOPOST 440 /* Posting not allowed */
- #define ERR_POSTFAIL 441 /* Posting failed */
-
- #define ERR_COMMAND 500 /* Command not recognized */
- #define ERR_CMDSYN 501 /* Command syntax error */
- #define ERR_ACCESS 502 /* Access to server denied */
- #define ERR_FAULT 503 /* Program fault, command not performed */
-
- /* RFC 977 defines this; don't change it. */
-
- #define NNTP_STRLEN 512
- @EOF
-
- chmod 644 nntp.h
-
- echo x - nntp_open.c
- cat >nntp_open.c <<'@EOF'
-
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "nntp.h"
- #include "tass.h"
-
-
- char *
- is_remote() {
-
- return " (remote)";
- }
-
-
- nntp_startup() {
- char *server_name;
- int ret;
- extern char *getenv();
-
- server_name = getserverbyfile(NNTP_SERVER);
- if (server_name == NULL) {
- fprintf(stderr, "Can't get nntp server name\n");
- fprintf(stderr, "Either put the name in the file %s, or put\n",
- NNTP_SERVER);
- fprintf(stderr, "it in the environment variable NNTPSERVER\n");
- exit(1);
- }
-
- ret = server_init(server_name);
-
- switch (ret) {
- case OK_CANPOST:
- case OK_NOPOST:
- break;
-
- case -1:
- fprintf(stderr, "failed to connect to server\n");
- exit(1);
-
- default:
- fprintf(stderr, "rejected by server, nntp error %d\n", ret);
- exit(1);
- }
- }
-
-
- nntp_finish() {
- close_server();
- }
-
-
- /*
- * get_respcode
- * get a response code from the server and return it to the caller
- */
-
- int get_respcode() {
- char line[NNTP_STRLEN];
-
- if (get_server(line, NNTP_STRLEN) == -1) {
- fprintf(stderr, "connection to server broken\n");
- tass_done(1);
- }
-
- return atoi(line);
- }
-
-
-
- stuff_nntp(fnam)
- char *fnam;
- {
- FILE *fp;
- char line[NNTP_STRLEN];
- extern char *mktemp();
- struct stat sb;
- extern long note_size;
-
- strcpy(fnam, "/tmp/tass_nntpXXXXXX");
- mktemp(fnam);
-
- fp = fopen(fnam, "w");
- if (fp == NULL) {
- fprintf(stderr, "stuff_nntp: can't open %s: ", fnam);
- perror("");
- return FALSE;
- }
-
- while (1) {
- if (get_server(line, NNTP_STRLEN) == -1) {
- fprintf(stderr, "connection to server broken\n");
- tass_done(1);
- }
- if (strcmp(line, ".") == 0)
- break; /* end of text */
- strcat(line, "\n");
- if (line[0] == '.') /* reduce leading .'s */
- fputs(&line[1], fp);
- else
- fputs(line, fp);
- }
- fclose(fp);
-
- if (stat(fnam, &sb) < 0)
- note_size = 0;
- else
- note_size = sb.st_size;
-
- return TRUE;
- }
-
-
- FILE *
- nntp_to_fp() {
- char fnam[LEN];
- FILE *fp;
-
- if (!stuff_nntp(fnam))
- return NULL;
-
- fp = fopen(fnam, "r");
- if (fp == NULL) {
- fprintf(stderr, "nntp_to_fp: can't reopen %s: ", fnam);
- perror("");
- return NULL;
- }
- unlink(fnam);
- return fp;
- }
-
-
- nntp_to_fd() {
- char fnam[LEN];
- int fd;
-
- if (!stuff_nntp(fnam))
- return NULL;
-
- fd = open(fnam, 0);
- if (fd == NULL) {
- fprintf(stderr, "nntp_to_fd: can't reopen %s: ", fnam);
- perror("");
- return -1;
- }
- unlink(fnam);
- return fd;
- }
-
-
-
- FILE *
- open_active_fp() {
-
- put_server("list");
- if (get_respcode() != OK_GROUPS)
- return NULL;
-
- return nntp_to_fp();
- }
-
-
- FILE *
- open_art_fp(group_path, art)
- char *group_path;
- long art;
- {
- char buf[LEN];
-
- sprintf(buf, "article %ld", art);
-
- put_server(buf);
- if (get_respcode() != OK_ARTICLE)
- return NULL;
-
- return nntp_to_fp();
- }
-
-
- open_header_fd(group_path, art)
- char *group_path;
- long art;
- {
- char buf[LEN];
-
- sprintf(buf, "head %ld", art);
- put_server(buf);
- if (get_respcode() != OK_HEAD)
- return -1;
-
- return nntp_to_fd();
- }
-
-
- setup_base(group, group_path)
- char *group;
- char *group_path;
- {
- char buf[LEN];
- char line[NNTP_STRLEN];
- long start, last, dummy, count;
-
- top_base = 0;
-
- sprintf(buf, "group %s", group);
- put_server(buf);
-
- if (get_server(line, NNTP_STRLEN) == -1) {
- fprintf(stderr, "connection to server broken\n");
- tass_done(1);
- }
-
- if (atoi(line) != OK_GROUP)
- return;
-
- sscanf(line,"%ld %ld %ld %ld", &dummy, &count, &start, &last);
- if (last - count > start)
- start = last - count;
-
- while (start <= last) {
- if (top_base >= max_art)
- expand_art();
- base[top_base++] = start++;
- }
- }
-
-
- @EOF
-
- chmod 644 nntp_open.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);
- ReadCh();
- }
-
-
- @EOF
-
- chmod 644 prompt.c
-
- echo x - tass.h
- cat >tass.h <<'@EOF'
-
- #define LIBDIR "/usr/lib/news"
- #define SPOOLDIR "/usr/spool/news"
- #define MAILER "/bin/rmail"
- #define DEF_EDITOR "/usr/bin/vi"
-
- #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 /* should be prime */
-
- /* #define MAX_SUBJ (COLS - 42) */
-
-
- struct header {
- long artnum;
- char *subject;
- char *from;
- int thread;
- 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.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 sig[LEN];
- extern char signature[LEN];
- 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.2"
-
- @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
-