home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-24 | 67.8 KB | 3,504 lines |
- Xref: sparky de.comp.sources.os9:15 comp.os.os9:1560
- Path: sparky!uunet!elroy.jpl.nasa.gov!ames!sun-barr!news2me.EBay.Sun.COM!seven-up.East.Sun.COM!sungy!stasys!stasys!not-for-mail
- From: frank.kaefer@stasys.sta.sub.org (Frank Kaefer)
- Newsgroups: de.comp.sources.os9,comp.os.os9
- Subject: Tass for OS-9 Part02/03
- Message-ID: <1hccjaINN773@stasys.sta.sub.org>
- Date: 24 Dec 92 13:05:46 GMT
- Sender: news@stasys.sta.sub.org
- Followup-To: de.comp.sources.d
- Organization: Stasys News Server, Starnberg, Germany
- Lines: 3489
- Approved: frank.kaefer@stasys.sta.sub.org (Frank Kaefer)
- NNTP-Posting-Host: stasys.sta.sub.org
-
- Submitted-by: Ulrich Dessauer <ud@Nightmare.ddt.sub.org>
- Archive-name: tass/part02
-
- : ----- Cut here ----- Cut here ----- Cut here ----- Cut here -----
- : Use sh filename to extract shell archive
- : This shell archive contains following files:
- : 'mail.c 836 bytes'
- : 'main.c 23086 bytes'
- : 'misc.c 8468 bytes'
- : 'page.c 31558 bytes'
- :
- if test -f 'mail.c' ; then
- echo 'File mail.c already exists, overwriting it'
- del 'mail.c'
- fi
- echo Extracting \"'mail.c'\"
- sed "s/^X//" >'mail.c' <<'__END__OF__THIS__FILE__'
- X
- X#include <stdio.h>
- X#ifndef OSK
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#else /* OSK */
- X#include <types.h>
- X#include <stat.h>
- Xtypedef long off_t;
- X#endif /* OSK */
- X#include "tass.h"
- X
- Xchar *mailbox_name = NULL;
- Xoff_t mailbox_size;
- X
- X
- X/*
- X * Record size of mailbox so we can detect if new mail has arrived
- X */
- X
- Xmail_setup() {
- X struct stat buf;
- X extern char *getenv();
- X
- X if (do_mail_check) {
- X if (mailbox_name == NULL)
- X mailbox_name = getenv("MAIL");
- X
- X if (mailbox_name == NULL)
- X mailbox_size = 0;
- X else {
- X if (stat(mailbox_name, &buf) >= 0)
- X mailbox_size = buf.st_size;
- X else
- X mailbox_size = 0;
- X }
- X }
- X}
- X
- X
- X/*
- X * Return TRUE if new mail has arrived
- X */
- X
- Xmail_check() {
- X struct stat buf;
- X
- X if (mailbox_name != NULL
- X && stat(mailbox_name, &buf) >= 0
- X && mailbox_size < buf.st_size)
- X return TRUE;
- X
- X return FALSE;
- X}
- X
- __END__OF__THIS__FILE__
- if test -f 'main.c' ; then
- echo 'File main.c already exists, overwriting it'
- del 'main.c'
- fi
- echo Extracting \"'main.c'\"
- sed "s/^X//" >'main.c' <<'__END__OF__THIS__FILE__'
- X
- X/*
- X * Tass, a visual Usenet news reader
- X * (c) Copyright 1990 by Rich Skrenta
- X *
- X * Distribution agreement:
- X *
- X * You may freely copy or redistribute this software, so long
- X * as there is no profit made from its use, sale, trade or
- X * reproduction. You may not change this copyright notice,
- X * and it must be included prominently in any copy made.
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#ifdef OSK
- X#include <modes.h>
- X#include <pwd.h>
- X#else /* OSK */
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#endif /* OSK */
- X#include "tass.h"
- X
- X#ifdef OSK
- Xextern char *index ();
- X
- Xextern
- X#endif /* OSK */
- Xint LINES, COLS;
- X
- Xint max_active;
- Xstruct group_ent *active; /* active file */
- Xint group_hash[TABLE_SIZE]; /* group name --> active[] */
- Xint *my_group; /* .newsrc --> active[] */
- Xint *unread; /* highest art read in group */
- Xint num_active; /* one past top of active */
- Xint local_top; /* one past top of my_group */
- Xint update = FALSE; /* update index files only mode */
- X
- Xstruct header *arts;
- Xlong *base;
- Xint max_art;
- Xint top = 0;
- Xint top_base;
- X
- X#ifdef USE_UID
- Xint tass_uid;
- Xint tass_gid;
- Xint real_uid;
- Xint real_gid;
- X#ifdef OSK
- X#define DEF_TASSUID (39 | (1 << 16))
- X#endif /* OSK */
- X#endif /* USE_UID */
- X
- Xint local_index; /* do private indexing? */
- X
- Xint do_mail_check; /* if we want to check for mail */
- X
- Xint omask;
- X
- Xjmp_buf jmp_buffer;
- X
- Xchar *cvers = "Tass 3.0 (c) Copyright 1991 by Rich Skrenta. All rights reserved";
- X
- X
- X#ifdef SIGTSTP
- Xvoid
- Xmain_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, main_susp);
- X mail_setup();
- X Raw(TRUE);
- X}
- X#endif
- X
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X extern int optind, opterr;
- X extern char *optarg;
- X int errflag = 0;
- X int i;
- X int c;
- X#ifdef OSK
- X struct passwd *pw;
- X#endif /* OSK */
- X
- X for (i = 0; i < TABLE_SIZE; i++)
- X group_hash[i] = -1;
- X
- X#ifdef SIGPIPE
- X signal(SIGPIPE, SIG_IGN);
- X#endif /* SIGPIPE */
- X#ifdef SIGTSTP
- X signal(SIGTSTP, main_susp);
- X#endif
- X#ifdef SIGQUIT
- X signal(SIGQUIT, SIG_IGN);
- X#endif /* SIGQUIT */
- X#ifdef SIGINT
- X signal(SIGINT, SIG_IGN);
- X#endif /* SIGINT */
- X
- X#ifdef USE_UID
- X#ifndef OSK
- X tass_uid = geteuid();
- X tass_gid = getegid();
- X real_uid = getuid();
- X real_gid = getgid();
- X#else /* OSK */
- X real_uid = getuid ();
- X setpwent ();
- X if (pw = getpwnam ("news"))
- X tass_uid = pw->pw_uid | (pw->pw_gid << 16);
- X else
- X tass_uid = DEF_TASSUID;
- X endpwent ();
- X setup_convtable (TRUE, TRUE);
- X setuid (tass_uid);
- X#endif /* OSK */
- X#endif /* USE_UID */
- X
- X omask = umask (0);
- X init_selfinfo(); /* set up char *'s: homedir, newsrc, etc. */
- X init_alloc(); /* allocate initial array sizes */
- X
- X#ifdef USE_UID
- X if (tass_uid == real_uid) { /* run out of someone's account */
- X#endif /* USE_UID */
- X local_index = FALSE; /* index in their home directory */
- X if (access (indexdir, S_IFDIR) == -1)
- X#ifndef OSK
- X mkdir(indexdir, 0755);
- X#else /* OSK */
- X makdir (indexdir, S_IREAD | S_IWRITE, 033);
- X#endif /* OSK */
- X#ifdef USE_UID
- X } else /* we're setuid, index in /usr/spool/news */
- X local_index = FALSE;
- X#endif /* USE_UID */
- X
- X do_mail_check = FALSE;
- X
- X read_active(); /* load the active file into active[] */
- X
- X while ((c = getopt(argc, argv, "f:ugm")) != -1) {
- X switch(c) {
- X case 'f':
- X strcpy(newsrc, optarg);
- X break;
- X
- X case 'u':
- X update = TRUE;
- X break;
- X
- X case 'g':
- X local_index = TRUE;
- X break;
- X
- X case 'm':
- X do_mail_check = TRUE;
- X break;
- X
- X case '?':
- X default:
- X errflag++;
- X }
- X }
- X
- X if (errflag) {
- X fprintf(stderr, "usage: tass [options] [newsgroups]\n");
- X fprintf(stderr, " -f file use file instead of $HOME/.newsrc\n");
- X fprintf(stderr, " -u update index files only\n");
- X fprintf(stderr, " -g don't use global instead of local index files\n");
- X fprintf(stderr, " -m check for new mail while reading news\n");
- X exit(1);
- X }
- X
- X if (!update)
- X printf("Tass 3.0\n");
- X
- X if (optind < argc) {
- X while (optind < argc) {
- X if (add_group(argv[optind], TRUE) < 0)
- X fprintf(stderr,
- X "group %s not found in active file\n",
- X argv[optind]);
- X optind++;
- X }
- X } else
- X read_newsrc(TRUE);
- X
- X if (update) { /* index file updater only */
- X do_update();
- X exit(0);
- X }
- X
- X if (InitScreen() == FALSE) {
- X fprintf(stderr,"Screen initialization failed\n");
- X exit(1);
- X }
- X
- X if (!setjmp (jmp_buffer)) {
- X ScreenSize(&LINES, &COLS);
- X Raw(TRUE);
- X
- X mail_setup(); /* record mailbox size for "you have mail" */
- X selection_index();
- X }
- X
- X tass_done(0);
- X}
- X
- X
- X
- Xtass_done(ret)
- Xint ret;
- X{
- X
- X MoveCursor(LINES, 0);
- X printf("\r\012");
- X Raw(FALSE);
- X umask (omask);
- X exit(ret);
- X}
- X
- X
- X/*
- X * Dynamic table management
- X * These settings are memory conservative: small initial allocations
- X * and a 50% expansion on table overflow. A fast vm system with
- X * much memory might want to start with higher initial allocations
- X * and a 100% expansion on overflow, especially for the arts[] array.
- X */
- X
- Xinit_alloc() {
- X
- X max_active = 100; /* initial alloc */
- X
- X active = (struct group_ent *) my_malloc(sizeof(*active) * max_active);
- X my_group = (int *) my_malloc(sizeof(int) * max_active);
- X unread = (int *) my_malloc(sizeof(int) * max_active);
- X
- X max_art = 300; /* initial alloc */
- X
- X arts = (struct header *) my_malloc(sizeof(*arts) * max_art);
- X base = (long *) my_malloc(sizeof(long) * max_art);
- X}
- X
- X
- Xexpand_art() {
- X
- X max_art += max_art / 2; /* increase by 50% */
- X
- X arts = (struct header *) my_realloc(arts, sizeof(*arts) * max_art);
- X base = (long *) my_realloc(base, sizeof(long) * max_art);
- X}
- X
- X
- Xexpand_active() {
- X
- X max_active += max_active / 2; /* increase by 50% */
- X
- X active = (struct group_ent *) my_realloc(active,
- X sizeof(*active) * max_active);
- X my_group = (int *) my_realloc(my_group, sizeof(int) * max_active);
- X unread = (int *) my_realloc(unread, sizeof(int) * max_active);
- X}
- X
- X
- X/*
- X * Load the active file into active[]
- X */
- X
- Xread_active()
- X{
- X FILE *fp;
- X char *p, *q;
- X char buf[200];
- X long h;
- X int i;
- X
- X num_active = 0;
- X
- X if ((fp = fopen(active_file, "r")) == NULL) {
- X fprintf(stderr, "can't open %s: ", active_file);
- X perror("");
- X exit(1);
- X }
- X
- X while (fgets(buf, 200, fp) != NULL) {
- X for (p = buf; *p && *p != ' '; p++) ;
- X if (*p != ' ') {
- X#ifndef OSK
- X fprintf(stderr, "active file corrupt\n");
- X#else /* OSK */
- X fprintf(stderr, "active file corrupt in line '%s'\n", buf);
- X#endif /* OSK */
- X continue;
- X }
- X
- X *p++ = '\0';
- X
- X if (num_active >= max_active)
- X expand_active();
- X
- X { /* hash group name for fast lookup later */
- X char *t = buf;
- X
- X h = *t++;
- X while (*t)
- X h = (h * 64 + *t++) % TABLE_SIZE;
- X }
- X
- X if (group_hash[h] == -1)
- X group_hash[h] = num_active;
- X else { /* hash linked list chaining */
- X for (i = group_hash[h]; active[i].next >= 0;
- X i = active[i].next) {
- X if (strcmp(active[i].name, buf) == 0)
- X goto read_active_continue;
- X /* kill dups */
- X }
- X if (strcmp(active[i].name, buf) == 0)
- X goto read_active_continue;
- X active[i].next = num_active;
- X }
- X
- X for (q = p; *q && *q != ' '; q++) ;
- X if (*q != ' ') {
- X fprintf(stderr, "active file corrupt\n");
- X continue;
- X }
- X
- X active[num_active].name = str_save(buf);
- X
- X active[num_active].max = atol(p);
- X active[num_active].min = atol(q);
- X
- X active[num_active].next = -1; /* hash chaining */
- X active[num_active].flag = NOTGOT; /* not in my_group[] yet */
- X
- X num_active++;
- X
- Xread_active_continue:;
- X
- X }
- X
- X fclose(fp);
- X}
- X
- X
- X
- X/*
- X * Read $HOME/.newsrc into my_group[]. my_group[] ints point to
- X * active[] entries. Sub_only determines whether we just read
- X * subscribed groups or all of them.
- X */
- Xvoid
- Xread_newsrc(sub_only)
- Xint sub_only; /* TRUE=subscribed groups only, FALSE=all groups */
- X{
- X FILE *fp;
- X char *p;
- X char buf[8192];
- X char c;
- X int i;
- X
- X local_top = 0;
- X
- X#ifdef USE_UID
- X setuid(real_uid); /* become the user to write in his */
- X setgid(real_gid); /* home directory */
- X#endif /* USE_UID */
- X
- X fp = fopen(newsrc, "r");
- X if (fp == NULL) { /* attempt to make a .newsrc */
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X for (i = 0; i < num_active; i++) {
- X if (local_top >= max_active)
- X expand_active();
- X my_group[local_top] = i;
- X active[i].flag = 0;
- X#if 0
- X unread[local_top] = active[i].max - active[i].min;
- X#else
- X unread[local_top] = -1;
- X#endif
- X local_top++;
- X }
- X write_newsrc();
- X return;
- X }
- X
- X while (fgets(buf, 8192, fp) != NULL) {
- X p = buf;
- X while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X *p++ = '\0';
- X if (c == '!' && sub_only)
- X continue; /* unsubscribed */
- X
- X if ((i = add_group(buf, FALSE)) < 0) {
- X fprintf(stderr, "group %s not found in active file\n", buf);
- X continue;
- X }
- X
- X if (c != '!') /* if we're subscribed to it */
- X active[my_group[i]].flag |= SUBS;
- X
- X unread[i] = parse_unread(p, my_group[i]);
- X }
- X fclose(fp);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- X
- X
- X/*
- X * Write a new newsrc from my_group[] and active[]
- X * Used to a create a new .newsrc if there isn't one already, or when
- X * the newsrc is reset.
- X */
- X
- Xwrite_newsrc() {
- X FILE *fp;
- X int i;
- X
- X#ifdef USE_UID
- X setuid(real_uid); /* become the user to write in his */
- X setgid(real_gid); /* home directory */
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "w");
- X if (fp == NULL)
- X goto write_newsrc_done;
- X
- X for (i = 0; i < num_active; i++)
- X fprintf(fp, "%s: \n", active[i].name);
- X
- X fclose(fp);
- X
- Xwrite_newsrc_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- X
- X
- X/*
- X * Load the sequencer rang lists and mark arts[] according to the
- X * .newsrc info for a particular group. i.e. rec.arts.comics: 1-94,97
- X */
- X
- Xread_newsrc_line(group)
- Xchar *group;
- X{
- X FILE *fp;
- X char buf[8192];
- X char *p;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X fp = fopen(newsrc, "r");
- X if (fp == NULL)
- X goto read_newsrc_line_done;
- X
- X while (fgets(buf, 8192, fp) != NULL) {
- X p = buf;
- X while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X *p++ = '\0';
- X if (strcmp(buf, group) != 0)
- X continue;
- X parse_seq(p);
- X break;
- X }
- X
- X fclose(fp);
- Xread_newsrc_line_done:
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#else /* USE UID */
- X ;
- X#endif /* USE_UID */
- X}
- X
- X
- X/*
- X * For our current group, update the sequencer information in .newsrc
- X */
- X
- Xupdate_newsrc(group, groupnum)
- Xchar *group;
- Xint groupnum; /* index into active[] for this group */
- X{
- X FILE *fp;
- X FILE *newfp;
- X char buf[8192];
- X char *p;
- X char c;
- X int gotit = FALSE;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "r");
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL)
- X goto update_done;
- X
- X if (fp != NULL) {
- X while (fgets(buf, 8192, fp) != NULL) {
- X for (p = buf; *p; p++)
- X if (*p == '\n') {
- X *p = '\0';
- X break;
- X }
- X
- X p = buf;
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X if (strcmp(buf, group) == 0) {
- X fprintf(newfp, "%s%c ", buf, c);
- X gotit = TRUE;
- X print_seq(newfp, groupnum);
- X fprintf(newfp, "\n");
- X } else
- X fprintf(newfp, "%s%c%s\n", buf, c, p);
- X }
- X fclose(fp);
- X }
- X
- X fclose(newfp);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X
- Xupdate_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- X
- X
- X/*
- X * Subscribe/unsubscribe to a group in .newsrc. ch should either be
- X * '!' to unsubscribe or ':' to subscribe. num is the group's index
- X * in active[].
- X */
- X
- Xsubscribe(group, ch, num, out_seq)
- Xchar *group;
- Xchar ch;
- Xint num;
- Xint out_seq; /* output sequencer info? */
- X{
- X FILE *fp;
- X FILE *newfp;
- X char buf[8192];
- X char *p;
- X char c;
- X int gotit = FALSE;
- X
- X if (ch == '!')
- X active[num].flag &= ~SUBS;
- X else
- X active[num].flag |= SUBS;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "r");
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL)
- X goto update_done;
- X
- X if (fp != NULL) {
- X while (fgets(buf, 8192, fp) != NULL) {
- X for (p = buf; *p; p++)
- X if (*p == '\n') {
- X *p = '\0';
- X break;
- X }
- X
- X p = buf;
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X if (strcmp(buf, group) == 0) {
- X fprintf(newfp, "%s%c%s\n", buf, ch, p);
- X gotit = TRUE;
- X } else
- X fprintf(newfp, "%s%c%s\n", buf, c, p);
- X }
- X fclose(fp);
- X }
- X
- X if (!gotit) {
- X if (out_seq) {
- X fprintf(newfp, "%s%c ", group, ch);
- X print_seq(newfp, num);
- X fprintf(newfp, "\n");
- X } else
- X fprintf(newfp, "%s%c\n", group, ch);
- X }
- X
- X fclose(newfp);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X
- Xupdate_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- X
- Xvoid
- Xprint_seq(fp, groupnum)
- XFILE *fp;
- Xint groupnum; /* index into active[] for this group */
- X{
- X int i;
- X int flag = FALSE;
- X
- X if (top <= 0) {
- X if (active[groupnum].min > 1) {
- X fprintf(fp, "1-%ld", active[groupnum].min);
- X fflush(fp);
- X }
- X return;
- X }
- X
- X i = 0;
- X if (arts[0].artnum > 1) {
- X for (; i < top && !arts[i].unread; i++) ;
- X if (i > 0)
- X fprintf(fp, "1-%ld", arts[i-1].artnum);
- X else
- X fprintf(fp, "1-%ld", arts[0].artnum - 1);
- X flag = TRUE;
- X }
- X
- X for (; i < top; i++) {
- X if (!arts[i].unread) {
- X if (flag)
- X fprintf(fp, ",");
- X else
- X flag = TRUE;
- X fprintf(fp, "%ld", arts[i].artnum);
- X if (i+1 < top && !arts[i+1].unread) {
- X while (i+1 < top && !arts[i+1].unread)
- X i++;
- X fprintf(fp, "-%ld", arts[i].artnum);
- X }
- X }
- X }
- X
- X if (!flag && active[groupnum].min > 1)
- X fprintf(fp, "1-%ld", active[groupnum].min);
- X fflush(fp);
- X}
- X
- X
- Xparse_seq(s)
- Xchar *s;
- X{
- X long low, high;
- X int i;
- X
- X while (*s) {
- X while (*s && (*s < '0' || *s > '9'))
- X s++;
- X
- X if (*s && *s >= '0' && *s <= '9') {
- X low = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X if (*s == '-') {
- X s++;
- X high = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X } else
- X high = low;
- X
- X for (i = 0; i < top; i++)
- X if (arts[i].artnum >= low &&
- X arts[i].artnum <= high)
- X arts[i].unread = 0;
- X }
- X }
- X}
- X
- X
- Xparse_unread(s, groupnum)
- Xchar *s;
- Xint groupnum; /* index for group in active[] */
- X{
- X long low, high;
- X long last_high;
- X int i;
- X int sum = 0;
- X int gotone = FALSE;
- X int n;
- X
- X/*
- X * Read the first range from the .newsrc sequencer information. If the
- X * top of the first range is higher than what the active file claims is
- X * the bottom, use it as the new bottom instead
- X */
- X
- X high = 0;
- X if (*s) {
- X while (*s && (*s < '0' || *s > '9'))
- X s++;
- X
- X if (*s && *s >= '0' && *s <= '9') {
- X low = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X if (*s == '-') {
- X s++;
- X high = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X } else
- X high = low;
- X gotone = TRUE;
- X }
- X }
- X
- X if (high < active[groupnum].min)
- X high = active[groupnum].min;
- X
- X#ifdef OSK
- X if (! gotone) {
- X high = active [groupnum].min;
- X low = high;
- X gotone = low != active[groupnum].max;
- X }
- X#endif /* OSK */
- X
- X while (*s) {
- X last_high = high;
- X
- X while (*s && (*s < '0' || *s > '9'))
- X s++;
- X
- X if (*s && *s >= '0' && *s <= '9') {
- X low = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X if (*s == '-') {
- X s++;
- X high = atol(s);
- X while (*s && *s >= '0' && *s <= '9')
- X s++;
- X } else
- X high = low;
- X
- X if (low > last_high) /* otherwise seq out of order */
- X sum += (low - last_high) - 1;
- X }
- X }
- X
- X if (gotone) {
- X if (active[groupnum].max > high)
- X sum += active[groupnum].max - high;
- X return sum;
- X }
- X
- X n = (int) (active[groupnum].max - active[groupnum].min);
- X if (n < 2)
- X return 0;
- X
- X return -1;
- X}
- X
- X
- Xget_line_unread(group, groupnum)
- Xchar *group;
- Xint groupnum; /* index for group in active[] */
- X{
- X FILE *fp;
- X char buf[8192];
- X char *p;
- X int ret = -1;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X fp = fopen(newsrc, "r");
- X if (fp == NULL) {
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X return -1;
- X }
- X
- X while (fgets(buf, 8192, fp) != NULL) {
- X p = buf;
- X while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X *p++ = '\0';
- X if (strcmp(buf, group) != 0)
- X continue;
- X ret = parse_unread(p, groupnum);
- X break;
- X }
- X
- X fclose(fp);
- X
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X return ret;
- X}
- X
- X
- Xreset_newsrc()
- X{
- X FILE *fp;
- X FILE *newfp;
- X char buf[8192];
- X char *p;
- X char c;
- X int gotit = FALSE;
- X int i;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "r");
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL)
- X goto update_done;
- X
- X if (fp != NULL) {
- X while (fgets(buf, 8192, fp) != NULL) {
- X for (p = buf; *p && *p != '\n'; p++) ;
- X *p = '\0';
- X
- X p = buf;
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X fprintf(newfp, "%s%c\n", buf, c);
- X }
- X fclose(fp);
- X }
- X
- X fclose(newfp);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X
- Xupdate_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X for (i = 0; i < local_top; i++)
- X unread[i] = -1;
- X}
- X
- X
- Xdelete_group(group)
- Xchar *group;
- X{
- X FILE *fp;
- X FILE *newfp;
- X char buf[8192];
- X char *p;
- X char c;
- X int gotit = FALSE;
- X FILE *del;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "r");
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL)
- X goto del_done;
- X del = fopen(delgroups, "a+");
- X if (del == NULL)
- X goto del_done;
- X
- X if (fp != NULL) {
- X while (fgets(buf, 8192, fp) != NULL) {
- X for (p = buf; *p && *p != '\n'; p++) ;
- X *p = '\0';
- X
- X p = buf;
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X if (strcmp(buf, group) == 0) {
- X fprintf(del, "%s%c%s\n", buf, c, p);
- X gotit = TRUE;
- X } else
- X fprintf(newfp, "%s%c%s\n", buf, c, p);
- X }
- X fclose(fp);
- X }
- X
- X fclose(newfp);
- X
- X if (!gotit)
- X fprintf(del, "%s! \n", group);
- X
- X fclose(del);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X
- Xdel_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- X
- X
- Xundel_group() {
- X FILE *del;
- X FILE *newfp;
- X FILE *fp;
- X char buf[2][8192];
- X char *p;
- X int which = 0;
- X long h;
- X extern int cur_groupnum;
- X int i, j;
- X char c;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X del = fopen(delgroups, "r");
- X if (del == NULL) {
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return FALSE;
- X }
- X unlink(delgroups);
- X umask (omask);
- X newfp = fopen(delgroups, "w");
- X if (newfp == NULL) {
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return FALSE;
- X }
- X
- X buf[0][0] = '\0';
- X buf[1][0] = '\0';
- X
- X while (fgets(buf[which], 8192, del) != NULL) {
- X which = !which;
- X if (*buf[which])
- X fputs(buf[which], newfp);
- X }
- X
- X fclose(del);
- X fclose(newfp);
- X which = !which;
- X
- X if (!*buf[which]) {
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return FALSE;
- X }
- X
- X for (p = buf[which]; *p && *p != '\n'; p++) ;
- X *p = '\0';
- X
- X p = buf[which];
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X { /* find the hash of the group name */
- X char *t = buf[which];
- 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(buf[which], active[i].name) == 0) {
- X for (j = 0; j < local_top; j++)
- X if (my_group[j] == i) {
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return j;
- X }
- X
- X active[i].flag &= ~NOTGOT; /* mark that we got it */
- X if (c != '!')
- X active[i].flag |= SUBS;
- X
- X if (local_top >= max_active)
- X expand_active();
- X local_top++;
- X for (j = local_top; j > cur_groupnum; j--) {
- X my_group[j] = my_group[j-1];
- X unread[j] = unread[j-1];
- X }
- X my_group[cur_groupnum] = i;
- X unread[cur_groupnum] = parse_unread(p, i);
- X
- X fp = fopen(newsrc, "r");
- X if (fp == NULL) {
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return FALSE;
- X }
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL) {
- X fclose(fp);
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return FALSE;
- X }
- X i = 0;
- X while (fgets(buf[!which], 8192, fp) != NULL) {
- X for (p = buf[!which]; *p && *p != '\n'; p++) ;
- X *p = '\0';
- X
- X p = buf[!which];
- X while (*p && *p!=' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X while (i < cur_groupnum) {
- X if (strcmp(buf[!which],
- X active[my_group[i]].name) == 0) {
- X fprintf(newfp, "%s%c%s\n",
- X buf[!which], c, p);
- X goto foo_cont;
- X }
- X i++;
- X }
- X fprintf(newfp, "%s%c%s\n", buf[which], c, p);
- X fprintf(newfp, "%s%c%s\n", buf[!which], c, p);
- X break;
- Xfoo_cont:;
- X }
- X
- X while (fgets(buf[!which], 8192, fp) != NULL)
- X fputs(buf[!which], newfp);
- X
- X fclose(newfp);
- X fclose(fp);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X return TRUE;
- X }
- X }
- X
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X return FALSE;
- X}
- X
- Xvoid
- Xmark_group_read(group, groupnum)
- Xchar *group;
- Xint groupnum; /* index into active[] for this group */
- X{
- X FILE *fp;
- X FILE *newfp;
- X char buf[8192];
- X char *p;
- X char c;
- X int gotit = FALSE;
- X
- X if (active[groupnum].max < 2)
- X return;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X fp = fopen(newsrc, "r");
- X newfp = fopen(newnewsrc, "w");
- X if (newfp == NULL)
- X goto mark_group_read_done;
- X
- X if (fp != NULL) {
- X while (fgets(buf, 8192, fp) != NULL) {
- X for (p = buf; *p; p++)
- X if (*p == '\n') {
- X *p = '\0';
- X break;
- X }
- X
- X p = buf;
- X while (*p && *p != ' ' && *p != ':' && *p != '!')
- X p++;
- X c = *p;
- X if (c != '\0')
- X *p++ = '\0';
- X
- X if (c != '!')
- X c = ':';
- X
- X if (strcmp(buf, group) == 0) {
- X fprintf(newfp, "%s%c 1-%ld\n", buf, c,
- X active[groupnum].max);
- X gotit = TRUE;
- X } else
- X fprintf(newfp, "%s%c%s\n", buf, c, p);
- X }
- X fclose(fp);
- X }
- X
- X fclose(newfp);
- X unlink(newsrc);
- X#ifndef OSK
- X link(newnewsrc, newsrc);
- X unlink(newnewsrc);
- X#else /* OSK */
- X rename(newnewsrc, newsrc);
- X#endif /* OSK */
- X
- Xmark_group_read_done:
- X umask (0);
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X}
- __END__OF__THIS__FILE__
- if test -f 'misc.c' ; then
- echo 'File misc.c already exists, overwriting it'
- del 'misc.c'
- fi
- echo Extracting \"'misc.c'\"
- sed "s/^X//" >'misc.c' <<'__END__OF__THIS__FILE__'
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <pwd.h>
- X#ifndef OSK
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#else /* OSK */
- X#include <types.h>
- X#include <stat.h>
- X#endif /* OSK */
- X#include "tass.h"
- X
- Xextern char *rindex ();
- X
- Xchar active_file[LEN];
- X#ifdef OSK
- Xchar spooldir[LEN];
- X#endif /* OSK */
- Xchar homedir[LEN];
- Xchar userid[LEN];
- Xchar delgroups[LEN];
- Xchar newsrc[LEN];
- Xchar newnewsrc[LEN];
- Xchar indexdir[LEN];
- Xchar my_org[LEN]; /* organization */
- X#ifdef INCSTR
- Xchar *incstr;
- X#endif /* INCSTR */
- X
- X/*
- X * Which base note (an index into base[]) does a respnum
- X * (an index into arts[]) corresponsd to?
- X *
- X * In other words, base[] points to an entry in arts[] which is
- X * the head of a thread, linked with arts[].thread. For any q: arts[q],
- X * find i such that base[i]->arts[n]->arts[o]->...->arts[q]
- X */
- X
- Xwhich_base(n)
- Xint n;
- X{
- X int i, j;
- X
- X for (i = 0; i < top_base; i++)
- X for (j = base[i]; j >= 0; j = arts[j].thread)
- X if (j == n)
- X return i;
- X
- X fprintf(stderr, "can't find base article\n");
- X return 0;
- X}
- X
- X
- X/*
- X * Find how deep in a thread a response is. Start counting at zero
- X */
- X
- Xwhich_resp(n)
- Xint n;
- X{
- X int i, j;
- X int num = 0;
- X
- X i = which_base(n);
- X
- X for (j = base[i]; j != -1; j = arts[j].thread)
- X if (j == n)
- X break;
- X else
- X num++;
- X
- X return num;
- X}
- X
- X
- X/*
- X * Given an index into base[], find the number of responses for
- X * that basenote
- X */
- X
- Xnresp(n)
- Xint n;
- X{
- X int i;
- X int oldi = -3;
- X int sum = 0;
- X
- X assert(n < top_base);
- X
- X for (i = base[n]; i != -1; i = arts[i].thread) {
- X assert(i != -2);
- X assert(i != oldi);
- X oldi = i;
- X sum++;
- X }
- X
- X return sum - 1;
- X}
- X
- X
- Xasfail(file, line, cond)
- Xchar *file;
- Xint line;
- Xchar *cond;
- X{
- X fprintf(stderr, "tass: assertion failure: %s (%d): %s\n",
- X file, line, cond);
- X exit(1);
- X}
- X
- X
- X/*
- X * Make regular expressions pleasant for the masses: glob them
- X */
- X
- Xglob_name(group, grp)
- Xchar *group;
- Xchar *grp;
- X{
- Xchar *p, *q;
- X
- X/*
- X * Prefix the .'s in the group name so they won't be interpreted
- X * as regular expression commands. Change 'all' into '*'
- X */
- X
- X p = group;
- X q = grp;
- X
- X if (strncmp(p, "all", 3) == 0 && (p[3] == '.' || p[3] == '\0')) {
- X *q++ = '.';
- X *q++ = '*';
- X p = &p[3];
- X }
- X while (*p != '\0') {
- X if (*p == '.') {
- X *q++ = '\\';
- X *q++ = '.';
- X p++;
- X
- X if (strncmp(p, "all", 3) == 0 &&
- X (p[3] == '.' || p[3] == '\0')) {
- X *q++ = '.';
- X *q++ = '*';
- X p = &p[3];
- X }
- X } else if (*p == '*') {
- X *q++ = '.';
- X *q++ = '*';
- X p++;
- X } else
- X *q++ = *p++;
- X }
- X *q = '\0';
- X}
- X
- X
- X/*
- X * init_selfinfo
- X * Deterimines users home directory, userid, and a path
- X * for an rc file in the home directory
- X */
- X
- Xinit_selfinfo()
- X{
- X struct passwd *myentry;
- X extern struct passwd *getpwuid();
- X struct stat sb;
- X char nam[LEN];
- X char *p;
- X extern char *getenv();
- X FILE *fp;
- X
- X#ifndef OSK
- X myentry = getpwuid(getuid());
- X#else /* OSK */
- X setpwent ();
- X#ifdef USE_UID
- X myentry = getpwuid(real_uid () & 0xffff);
- X#else /* USE_UID */
- X myentry = getpwuid(getuid () & 0xffff);
- X#endif /* USE_UID */
- X endpwent ();
- X#endif /* OSK */
- X strcpy(userid, myentry->pw_name);
- X strcpy(homedir, myentry->pw_dir);
- X
- X sprintf(newsrc, "%s/.newsrc", homedir);
- X sprintf(newnewsrc, "%s/.newnewsrc", homedir);
- X sprintf(delgroups, "%s/.delgroups", homedir);
- X sprintf(indexdir, "%s/.tindex", homedir);
- X#ifndef OSK
- X sprintf(active_file, "%s/active", LIBDIR);
- X#else /* OSK */
- X if (!info_str ("MNEWS.LIB", active_file, LEN - 20))
- X strcpy (active_file, LIBDIR);
- X strcat (active_file, "/Active");
- X if (!info_str ("MNEWS.DIR", spooldir, LEN))
- X strcpy (spooldir, SPOOLDIR);
- X#endif /* OSK */
- X#ifdef INCSTR
- X if (!(incstr = getenv ("INCSTR")))
- X incstr = "> ";
- X#endif /* INCSTR */
- X
- X if (stat(active_file, &sb) >= 0)
- X goto got_active;
- X
- X#ifndef OSK
- X/*
- X * I hate forgetting to define LIBDIR correctly. Guess a
- X * couple of likely places if it's not where LIBDIR says it is.
- X */
- X
- X strcpy(active_file, "/usr/lib/news/active");
- X if (stat(active_file, &sb) >= 0)
- X goto got_active;
- X
- X strcpy(active_file, "/usr/local/lib/news/active");
- X if (stat(active_file, &sb) >= 0)
- X goto got_active;
- X
- X strcpy(active_file, "/usr/public/lib/news/active");
- X if (stat(active_file, &sb) >= 0)
- X goto got_active;
- X
- X/*
- X * Oh well. Revert to what LIBDIR says it is to produce a
- X * useful error message when read_active() fails later.
- X */
- X
- X sprintf(active_file, "%s/active", LIBDIR);
- X#endif /* OSK */
- X
- Xgot_active:
- X
- X *my_org = '\0';
- X p = getenv("ORGANIZATION");
- X if (p != NULL) {
- X strcpy(my_org, p);
- X goto got_org;
- X }
- X
- X#ifndef OSK
- X sprintf(nam, "%s/organization", LIBDIR);
- X fp = fopen(nam, "r");
- X
- X if (fp == NULL) {
- X sprintf(nam, "/usr/lib/news/organization");
- X fp = fopen(nam, "r");
- X }
- X
- X if (fp == NULL) {
- X sprintf(nam, "/usr/local/lib/news/organization");
- X fp = fopen(nam, "r");
- X }
- X
- X if (fp == NULL) {
- X sprintf(nam, "/usr/public/lib/news/organization");
- X fp = fopen(nam, "r");
- X }
- X
- X if (fp == NULL) {
- X sprintf(nam, "/etc/organization");
- X fp = fopen(nam, "r");
- X }
- X
- X if (fp != NULL) {
- X if (fgets(my_org, LEN, fp) != NULL) {
- X for (p = my_org; *p && *p != '\n'; p++) ;
- X *p = '\0';
- X }
- X fclose(fp);
- X }
- X#endif /* OSK */
- X
- Xgot_org:;
- X
- X}
- X
- X
- Xchar *
- Xmy_malloc(size)
- Xunsigned size;
- X{
- X char *p;
- X extern char *malloc();
- X
- X p = malloc(size);
- X if (p == NULL) {
- X fprintf(stderr, "tass: out of memory\n");
- X exit(1);
- X }
- X return p;
- X}
- X
- X
- Xchar *
- Xmy_realloc(p, size)
- Xchar *p;
- Xunsigned size;
- X{
- X extern char *malloc();
- X extern char *realloc();
- X
- X if (p == NULL)
- X p = malloc(size);
- X else
- X p = realloc(p, size);
- X
- X if (p == NULL) {
- X fprintf(stderr, "tass: out of memory\n");
- X exit(1);
- X }
- X return p;
- X}
- X
- X
- Xchar *
- Xstr_save(s)
- Xchar *s;
- X{
- Xchar *p;
- X
- X assert(s != NULL);
- X
- X p = my_malloc(strlen(s) + 1);
- X strcpy(p, s);
- X
- X return(p);
- X}
- X
- X
- Xcopy_fp(a, b, prefix)
- XFILE *a;
- XFILE *b;
- Xchar *prefix;
- X{
- X char buf[8192];
- X
- X while (fgets(buf, 8192, a) != NULL) {
- X#ifdef MNEWS
- X conv_charset (buf, strlen (buf));
- X#endif /* MNEWS */
- X fprintf(b, "%s%s", prefix, buf);
- X }
- X}
- X
- X
- Xchar *
- Xget_val(env, def)
- Xchar *env; /* Environment variable we're looking for */
- Xchar *def; /* Default value if no environ value found */
- X{
- X extern char *getenv();
- X char *ptr;
- X
- X if ((ptr = getenv(env)) != NULL)
- X return(ptr);
- X else
- X return(def);
- X}
- X
- X
- Xinvoke_editor(nam, line)
- Xchar *nam;
- Xint line;
- X{
- X char buf[200];
- X static int first = TRUE;
- X static char editor[200];
- X static int type = -1;
- X char *ptr;
- X
- X if (first) {
- X#ifndef OSK
- X strcpy(editor, get_val("EDITOR", "/usr/bin/vi"));
- X#else /* OSK */
- X strcpy(editor, get_val("EDITOR", "me"));
- X#endif /* OSK */
- X if (ptr = rindex (editor, '/'))
- X ++ptr;
- X else
- X ptr = editor;
- X if (!strncmp (ptr, "vi", 2))
- X type = 0;
- X else if ((!strncmp (ptr, "me", 2)) || (!strncmp (ptr, "emacs")))
- X type = 1;
- X first = FALSE;
- X }
- X
- X ++line;
- X switch (type) {
- X case -1:
- X default:
- X sprintf(buf, "%s %s", editor, nam);
- X break;
- X case 0:
- X sprintf (buf, "%s +%d %s", editor, line, nam);
- X break;
- X case 1:
- X sprintf (buf, "%s -g=%d %s", editor, line, nam);
- X break;
- X }
- X printf("\r%s", buf);
- X CleartoEOLN ();
- X return invoke_cmd(buf);
- X}
- X
- X
- Xinvoke_cmd(nam)
- Xchar *nam;
- X{
- X int ret;
- X#ifdef SIGTSTP
- X void (*susp)();
- X#endif
- X
- X Raw(FALSE);
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X#ifndef OSK
- X#ifdef SIGTSTP
- X susp = signal(SIGTSTP, SIG_DFL);
- X#endif
- X
- X ret = system(nam);
- X
- X#ifdef SIGTSTP
- X signal(SIGTSTP, susp);
- X#endif
- X#else /* OSK */
- X ret = system (nam);
- X#endif /* OSK */
- X
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X Raw(TRUE);
- X
- X return ret == 0;
- X}
- X
- X
- Xshell_escape() {
- X char shell[LEN];
- X char *p;
- X#ifdef SIGTSTP
- X void (*susp)();
- X#endif
- X
- X if (!parse_string("!", shell))
- X strcpy(shell, get_val("SHELL", "/bin/sh"));
- X
- X for (p = shell; *p && (*p == ' ' || *p == '\t'); p++) ;
- X
- X if (!*p)
- X strcpy(shell, get_val("SHELL", "/bin/sh"));
- X
- X Raw(FALSE);
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X fputs("\r\012", stdout);
- X
- X#ifndef OSK
- X#ifdef SIGTSTP
- X susp = signal(SIGTSTP, SIG_DFL);
- X#endif
- X
- X system(p);
- X
- X#ifdef SIGTSTP
- X signal(SIGTSTP, susp);
- X#endif
- X#else /* OSK */
- X system (p);
- X#endif /* OSK */
- X
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X Raw(TRUE);
- X
- X continue_prompt();
- X mail_setup();
- X}
- X
- X
- X/*
- X * Find the next unread response in this group
- X */
- X
- Xnext_unread(n)
- Xint n;
- X{
- X
- X while (n >= 0) {
- X if (arts[n].unread == 1)
- X return n;
- X n = next_response(n);
- X }
- X
- X return -1;
- X}
- X
- X
- X/*
- X * Find the previous unread response in this thread
- X */
- X
- Xprev_unread(n)
- Xint n;
- X{
- X
- X while (n >= 0) {
- X if (arts[n].unread == 1)
- X return n;
- X n = prev_response(n);
- X }
- X
- X return -1;
- X}
- X
- __END__OF__THIS__FILE__
- if test -f 'page.c' ; then
- echo 'File page.c already exists, overwriting it'
- del 'page.c'
- fi
- echo Extracting \"'page.c'\"
- sed "s/^X//" >'page.c' <<'__END__OF__THIS__FILE__'
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#ifndef OSK
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#else /* OSK */
- X#include <types.h>
- X#include <stat.h>
- X
- Xextern FILE *popen ();
- X#endif /* OSK */
- X#include "tass.h"
- X
- X#define MAX_PAGES 1000
- X#define NOTE_UNAVAIL -1
- X
- Xchar note_h_path[LEN]; /* Path: */
- Xchar note_h_date[LEN]; /* Date: */
- Xchar note_h_subj[LEN]; /* Subject: */
- Xchar note_h_from[LEN]; /* From: */
- Xchar note_h_reply[LEN]; /* Reply-To: */
- Xchar note_h_org[LEN]; /* Organization: */
- Xchar note_h_newsgroups[LEN]; /* Newsgroups: */
- Xchar note_h_messageid[LEN]; /* Message-ID: */
- Xchar note_h_distrib[LEN]; /* Distribution: */
- Xchar note_h_followup[LEN]; /* Followup-To: */
- X
- Xint note_line;
- Xint note_page; /* what page we're on */
- Xlong note_mark[MAX_PAGES]; /* ftells on beginnings of pages */
- XFILE *note_fp; /* the body of the current article */
- Xint note_end; /* we're done showing this article */
- Xint rotate; /* 0=normal, 13=rot13 decode */
- X
- Xstruct stat note_stat; /* so we can tell how big it is */
- X
- Xchar note_full_name[100];
- Xchar note_from_addr[100];
- X
- X
- Xint last_resp; /* current & previous article for - command */
- Xint this_resp;
- X
- Xint glob_respnum;
- Xchar *glob_page_group;
- Xextern int cur_groupnum;
- X
- X
- X#ifdef SIGTSTP
- Xvoid
- Xpage_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, page_susp);
- X mail_setup();
- X Raw(TRUE);
- X redraw_page(glob_respnum, glob_page_group);
- X}
- X#endif
- X
- X
- Xshow_page(respnum, group, group_path)
- Xint respnum;
- Xchar *group;
- Xchar *group_path;
- X{
- X char ch;
- X int n;
- X long art;
- X int sav_unread;
- X
- Xrestart:
- X
- X glob_respnum = respnum;
- X glob_page_group = group;
- X
- X#ifdef SIGTSTP
- X signal(SIGTSTP, page_susp);
- X#endif
- X
- X if (respnum != this_resp) { /* remember current & previous */
- X last_resp = this_resp; /* articles for - command */
- X this_resp = respnum;
- X }
- X
- X rotate = 0; /* normal mode, not rot13 */
- X art = arts[respnum].artnum;
- X sav_unread = arts[respnum].unread;
- X arts[respnum].unread = 0; /* mark article as read */
- X open_note(art, group_path);
- X
- X if (note_page == NOTE_UNAVAIL) {
- X ClearScreen();
- X printf("[Article %ld unvailable]\r\012", art);
- X fflush(stdout);
- X } else
- X show_note_page(respnum, group);
- 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') || (ch == '=')) {
- X
- X if (ch != '=')
- X n = prompt_response(ch, respnum);
- X else {
- X n = choose_resp (which_base (respnum), 0);
- X info_message ("Base note selected");
- X }
- X
- X if (n != -1) {
- X arts[respnum].unread = sav_unread;
- X respnum = n;
- X goto restart;
- X }
- X
- X } else switch (ch) {
- X case '|': /* pipe article into command */
- X pipe_article();
- X redraw_page(respnum, group);
- 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 goto pager_ctrlr;
- X break;
- X
- X case 's':
- X save_art_to_file();
- X break;
- X
- X case 'S':
- X save_thread_to_file(respnum, group_path);
- X break;
- X
- X case ctrl('X'):
- X case '%': /* toggle rot-13 mode */
- X if (rotate)
- X rotate = 0;
- X else
- X rotate = 13;
- X goto pager_ctrlr;
- X break;
- X
- X case 'P': /* previous unread article */
- X n = prev_unread(prev_response(respnum));
- X if (n == -1)
- X info_message("No previous unread article");
- X else {
- X note_cleanup();
- X respnum = n;
- X goto restart;
- X }
- X break;
- X
- X case 'F': /* post a followup to this article */
- X case 'W': /* ... compatible to notes */
- X if (post_response(group, TRUE)) {
- X update_newsrc(group,
- X my_group[cur_groupnum]);
- X n = which_base(respnum);
- X note_cleanup();
- X index_group(group, group_path);
- X read_newsrc_line(group);
- X respnum = choose_resp(n, nresp(n));
- X goto restart;
- X } else
- X redraw_page(respnum, group);
- X break;
- X
- X case 'f': /* post a followup to this article */
- X case 'w': /* ... compatible to notes */
- X if (post_response(group, FALSE)) {
- X update_newsrc(group,
- X my_group[cur_groupnum]);
- X n = which_base(respnum);
- X note_cleanup();
- X index_group(group, group_path);
- X read_newsrc_line(group);
- X respnum = choose_resp(n, nresp(n));
- X goto restart;
- X } else
- X redraw_page(respnum, group);
- X break;
- X
- X case 'z': /* mark article as unread (to return) */
- X arts[respnum].unread = 2;
- X info_message("Article marked as unread");
- X break;
- X
- X case 'K': /* mark rest of thread as read */
- X case 'J': /* ... compatible to notes */
- X for (n = respnum; n >= 0; n = arts[n].thread)
- X arts[n].unread = 0;
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X goto return_to_index;
- X else {
- X note_cleanup();
- X respnum = n;
- X goto restart;
- X }
- X break;
- X
- X case 'i': /* return to index page */
- X case ctrl('B'): /* possibly cursor doen */
- Xreturn_to_index:
- X note_cleanup();
- X return( which_base(respnum) );
- X
- X case 't': /* return to group selection page */
- X note_cleanup();
- X return -1;
- X
- X case ctrl('R'): /* redraw beginning of article */
- Xpager_ctrlr:
- X if (note_page == NOTE_UNAVAIL) {
- X ClearScreen();
- X printf("[Article %ld unvailable]\r\012",
- X arts[respnum].artnum);
- X fflush(stdout);
- X } else {
- X note_page = 0;
- X note_end = FALSE;
- X fseek(note_fp, note_mark[0], 0);
- X show_note_page(respnum, group);
- X }
- X break;
- X
- X case '!':
- X shell_escape();
- X redraw_page(respnum, group);
- X break;
- X
- X case '\b':
- X case 'b': /* back a page */
- X case ctrl('P'): /* possibly cursor doen */
- X if (note_page == NOTE_UNAVAIL
- X || note_page <= 1) {
- X note_cleanup();
- X n = prev_response(respnum);
- X if (n == -1)
- X return( which_resp(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X } else {
- X note_page -= 2;
- X note_end = FALSE;
- X fseek(note_fp, note_mark[note_page], 0);
- X show_note_page(respnum, group);
- X }
- X break;
- X
- X case 'm': /* mail article to somebody */
- X mail_to_someone();
- X redraw_page(respnum, group);
- X break;
- X
- X case 'r': /* reply to author through mail */
- X mail_to_author(FALSE);
- X redraw_page(respnum, group);
- X break;
- X
- X case 'R': /* reply to author, copy text */
- X mail_to_author(TRUE);
- X redraw_page(respnum, group);
- X break;
- X
- X case '-': /* show last viewed article */
- X if (last_resp < 0) {
- X info_message("No last message");
- X break;
- X }
- X note_cleanup();
- X respnum = last_resp;
- X goto restart;
- X
- X
- X case 'p': /* previous article */
- X note_cleanup();
- X n = prev_response(respnum);
- X if (n == -1)
- X return( which_resp(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X case 'n': /* skip to next article */
- X note_cleanup();
- X n = next_response(respnum);
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X case 'k':
- X case 'j': /* ... compatible to notes */
- X if (note_page == NOTE_UNAVAIL) {
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X } else {
- X note_cleanup();
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X }
- X break;
- X
- X case ' ': /* next page or response */
- X case ctrl('N'): /* possibly cursor doen */
- X if (note_page == NOTE_UNAVAIL) {
- X n = next_response(respnum);
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X } else if (note_end) {
- X note_cleanup();
- X n = next_response(respnum);
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X } else
- X show_note_page(respnum, group);
- X break;
- X
- X case '\t': /* next page or unread response */
- X if (note_page == NOTE_UNAVAIL) {
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X } else if (note_end) {
- X note_cleanup();
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X } else
- X show_note_page(respnum, group);
- X break;
- X
- X case 'N': /* next unread article */
- X n = next_unread(next_response(respnum));
- X if (n == -1)
- X info_message("No next unread article");
- X else {
- X note_cleanup();
- X respnum = n;
- X goto restart;
- X }
- X break;
- X
- X case 'C': /* Cancel */
- X case 'd': /* delete */
- X case 'Z': /* zap (director option in notes) */
- X note_cleanup();
- X cancel_article ();
- X note_page = NOTE_UNAVAIL;
- X /* Fall through ... */
- X
- X#ifndef OSK
- X case '\r':
- X#else /* OSK */
- X case '\l':
- X#endif /* OSK */
- X case '\n': /* go to start of next thread */
- X case ctrl('F'): /* possibly cursor down */
- X note_cleanup();
- X n = next_basenote(respnum);
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X
- X#ifndef OSK
- X case 'q': /* quit */
- X return -2;
- X#endif /* OSK */
- X
- X case 'H': /* show article headers */
- X if (note_page == NOTE_UNAVAIL) {
- X n = next_response(respnum);
- X if (n == -1)
- X return( which_base(respnum) );
- X
- X respnum = n;
- X goto restart;
- X } else {
- X note_page = 0;
- X note_end = FALSE;
- X fseek(note_fp, 0L, 0);
- X show_note_page(respnum, group);
- X }
- X break;
- X
- X
- X case 'h':
- X tass_page_help();
- X redraw_page(respnum, group);
- X break;
- X
- X default:
- X info_message("Bad command. Type 'h' for help.");
- X }
- X }
- X}
- X
- X
- Xnote_cleanup() {
- X
- X if (note_page != NOTE_UNAVAIL)
- X fclose(note_fp);
- X}
- X
- X
- Xredraw_page(respnum, group)
- Xint respnum;
- Xchar *group;
- X{
- X
- X if (note_page == NOTE_UNAVAIL) {
- X ClearScreen();
- X printf("[Article %ld unvailable]\r\012", arts[respnum].artnum);
- X fflush(stdout);
- X } else if (note_page > 0) {
- X note_page--;
- X fseek(note_fp, note_mark[note_page], 0);
- X show_note_page(respnum, group);
- X }
- X}
- X
- X
- Xshow_note_page(respnum, group)
- Xint respnum;
- Xchar *group;
- X{
- X char buf[LEN];
- X char buf2[LEN+50];
- X int percent;
- X char *p, *q;
- X int i, j;
- X int ctrl_L; /* form feed character detected */
- X
- X ClearScreen();
- X
- X note_line = 1;
- X
- X if (note_page == 0)
- X show_first_header(respnum, group);
- X else
- X show_cont_header(respnum);
- X
- X ctrl_L = FALSE;
- X while (note_line < LINES) {
- X if (fgets(buf, LEN, note_fp) == NULL) {
- X note_end = TRUE;
- X break;
- X }
- X
- X buf[LEN-1] = '\0';
- X#ifdef MNEWS
- X conv_charset (buf, strlen (buf));
- X#endif /* MNEWS */
- X if (rotate)
- X for (p = buf, q = buf2;
- X *p && *p != '\n' && q<&buf2[LEN]; p++) {
- X if (*p == '\b' && q > buf2) {
- X q--;
- X } else if (*p == 12) { /* ^L */
- X *q++ = '^';
- X *q++ = 'L';
- X ctrl_L = TRUE;
- X } else if (*p == '\t') {
- X i = q - buf2;
- X j = (i|7) + 1;
- X
- X while (i++ < j)
- X *q++ = ' ';
- X } else if (*p & 0x7F < 32) {
- X *q++ = '^';
- X *q++ = (*p & 0x7F) + '@';
- X } else if (*p >= 'A' && *p <= 'Z')
- X *q++ = 'A' + (*p - 'A' + rotate) % 26;
- X else if (*p >= 'a' && *p <= 'z')
- X *q++ = 'a' + (*p - 'a' + rotate) % 26;
- X else
- X *q++ = *p;
- X }
- X else
- X for (p = buf, q = buf2;
- X *p && *p != '\n' && q<&buf2[LEN]; p++) {
- X if (*p == '\b' && q > buf2) {
- X q--;
- X } else if (*p == 12) { /* ^L */
- X *q++ = '^';
- X *q++ = 'L';
- X ctrl_L = TRUE;
- X } else if (*p == '\t') {
- X i = q - buf2;
- X j = (i|7) + 1;
- X
- X while (i++ < j)
- X *q++ = ' ';
- X } else if ((*p & 0x7F) < 32) {
- X *q++ = '^';
- X *q++ = (*p & 0x7F) + '@';
- X } else
- X *q++ = *p;
- X }
- X
- X *q = '\0';
- X
- X printf("%s\r\012", buf2);
- X
- X#if 1
- X note_line += (strlen(buf2) / COLS) + 1;
- X#else
- X if (*buf2)
- X note_line += (strlen(buf2) + COLS) / (COLS+1);
- X else
- X note_line++;
- X#endif
- X if (ctrl_L)
- X break;
- X }
- X
- X note_mark[++note_page] = ftell(note_fp);
- X
- X MoveCursor(LINES, MORE_POS);
- X/* StartInverse(); */
- X if (note_end) {
- X if (arts[respnum].thread != -1)
- X printf("-- next response --");
- X else
- X printf("-- last response --");
- X } else {
- X if (note_stat.st_size > 0) {
- X percent = note_mark[note_page] * 100 / note_stat.st_size;
- X printf("--More--(%d%%)", percent);
- X } else
- X printf("--More--");
- X }
- X/* EndInverse(); */
- X
- X fflush(stdout);
- X}
- X
- X
- Xshow_first_header(respnum, group)
- Xint respnum;
- Xchar *group;
- X{
- X int whichresp;
- X int x_resp;
- X char buf[200];
- X char tmp[200];
- X int pos, i;
- X int n;
- X
- X whichresp = which_resp( respnum );
- X x_resp = nresp( which_base(respnum) );
- X
- X ClearScreen();
- X
- X strcpy(buf, note_h_date);
- X pos = (COLS - strlen(group)) / 2;
- X for (i = strlen(buf); i < pos; i++)
- X buf[i] = ' ';
- X buf[i] = '\0';
- X
- X strcat(buf, group);
- X
- X for (i = strlen(buf); i < RIGHT_POS; i++)
- X buf[i] = ' ';
- X buf[i] = '\0';
- X
- X printf("%sNote %3d of %3d\r\012", buf, which_base(respnum) + 1, top_base);
- X
- X sprintf(buf, "Article %ld ", arts[respnum].artnum);
- X n = strlen(buf);
- X fputs(buf, stdout);
- X
- X pos = (COLS - strlen( note_h_subj )) / 2 - 2;
- X
- X if (pos > n)
- X MoveCursor(1, pos);
- X else
- X MoveCursor(1, n);
- X
- X StartInverse();
- X strcpy(buf, note_h_subj);
- X buf[RIGHT_POS - 2 - n] = '\0';
- X fputs(buf, stdout);
- X EndInverse();
- X
- X MoveCursor(1, RIGHT_POS);
- X if (whichresp)
- X printf("Resp %3d of %3d\r\012", whichresp, x_resp);
- X else {
- X if (x_resp == 0)
- X printf("No responses\r\012");
- X else if (x_resp == 1)
- X printf("1 Response\r\012");
- X else
- X printf("%d Responses\r\012", x_resp);
- X }
- X
- X if (*note_h_org)
- X sprintf(tmp, "%s at %s", note_full_name, note_h_org);
- X else
- X strcpy(tmp, note_full_name);
- X
- X tmp[79] = '\0';
- X
- X sprintf(buf, "%s ", note_from_addr);
- X
- X pos = COLS - 1 - strlen(tmp);
- X if (strlen(buf) + strlen(tmp) >= COLS - 1) {
- X strncat(buf, tmp, COLS - 1 - strlen(buf));
- X buf[COLS - 1] = '\0';
- X } else {
- X for (i = strlen(buf); i < pos; i++)
- X buf[i] = ' ';
- X buf[i] = '\0';
- X strcat(buf, tmp);
- X }
- X printf("%s\r\012\r\012", buf);
- X
- X note_line += 4;
- X}
- X
- X
- Xshow_cont_header(respnum)
- Xint respnum;
- X{
- Xint whichresp;
- Xint whichbase;
- Xchar buf[LEN+60];
- X
- X whichresp = which_resp(respnum);
- X whichbase = which_base(respnum);
- X
- X assert (whichbase < top_base);
- X
- X if (whichresp)
- X sprintf(buf, "Note %d of %d, Resp %d (page %d): %s",
- X whichbase + 1,
- X top_base,
- X whichresp,
- X note_page + 1,
- X note_h_subj);
- X else
- X sprintf(buf, "Note %d of %d (page %d): %s",
- X whichbase + 1,
- X top_base,
- X note_page + 1,
- X note_h_subj);
- X
- X buf[COLS] = '\0';
- X printf("%s\r\012\r\012", buf);
- X
- X note_line += 2;
- X}
- X
- Xvoid
- Xopen_note(art, group_path)
- Xlong art;
- Xchar *group_path;
- X{
- X char buf[1025];
- X
- X note_page = 0;
- X
- X#ifndef OSK
- X sprintf(buf, "/usr/spool/news/%s/%ld", group_path, art);
- X#else /* OSK */
- X sprintf(buf, "%s/%s/%ld", spooldir, group_path, art);
- X#endif /* OSK */
- X
- X if (stat(buf, ¬e_stat) < 0)
- X note_stat.st_size = 0;
- X
- X note_fp = fopen(buf, "r");
- X
- X#ifdef MNEWS
- X if (note_fp)
- X if (fgets (buf, 256, note_fp)) {
- X rewind (note_fp);
- X if (!strncmp (buf, "%(#)$ ", 6)) {
- X char sav[200];
- X
- X buf[strlen (buf) - 1] = '\0';
- X strcpy (sav, buf + 6);
- X sprintf (buf, "%s/%s", spooldir, sav);
- X fclose (note_fp);
- X if (stat (buf, ¬e_stat) < 0)
- X note_stat.st_size = 0;
- X note_fp = fopen (buf, "r");
- X }
- X }
- X#endif /* MNEWS */
- X
- X if (note_fp == NULL) {
- X fprintf(stderr, "can't open %s: ", buf);
- X perror("");
- X note_page = NOTE_UNAVAIL;
- X return;
- X }
- X
- X note_h_from[0] = '\0';
- X note_h_reply[0] = '\0';
- X note_h_path[0] = '\0';
- X note_h_subj[0] = '\0';
- X note_h_org[0] = '\0';
- X note_h_date[0] = '\0';
- X note_h_newsgroups[0] = '\0';
- X note_h_messageid[0] = '\0';
- X note_h_distrib[0] = '\0';
- X note_h_followup[0] = '\0';
- X
- X while (fgets(buf, 1024, note_fp) != NULL) {
- X buf[1024] = '\0';
- X buf[strlen(buf)-1] = '\0';
- X#ifdef MNEWS
- X conv_charset (buf, strlen (buf));
- X#endif /* MNEWS */
- X
- X if (*buf == '\0')
- X break;
- X
- X if (strncmp(buf, "From: ", 6) == 0) {
- X strncpy(note_h_from, &buf[6], LEN);
- X note_h_from[LEN-1] = '\0';
- X } else if (strncmp(buf, "Reply-To: ", 10) == 0) {
- X strncpy(note_h_reply, &buf[10], LEN);
- X note_h_reply[LEN-1] = '\0';
- X } else if (strncmp(buf, "Path: ", 6) == 0) {
- X strncpy(note_h_path, &buf[6], LEN);
- X note_h_path[LEN-1] = '\0';
- X } else if (strncmp(buf, "Subject: ", 9) == 0) {
- X strncpy(note_h_subj, &buf[9], LEN);
- X note_h_subj[LEN-1] = '\0';
- X } else if (strncmp(buf, "Organization: ", 14) == 0) {
- X strncpy(note_h_org, &buf[14], LEN);
- X note_h_org[LEN-1] = '\0';
- X } else if (strncmp(buf, "Date: ", 6) == 0) {
- X strncpy(note_h_date, &buf[6], LEN);
- X note_h_date[LEN-1] = '\0';
- X } else if (strncmp(buf, "Newsgroups: ", 12) == 0) {
- X strncpy(note_h_newsgroups, &buf[12], LEN);
- X note_h_newsgroups[LEN-1] = '\0';
- X } else if (strncmp(buf, "Message-ID: ", 12) == 0) {
- X strncpy(note_h_messageid, &buf[12], LEN);
- X note_h_messageid[LEN-1] = '\0';
- X } else if (strncmp(buf, "Distribution: ", 14) == 0) {
- X strncpy(note_h_distrib, &buf[14], LEN);
- X note_h_distrib[LEN-1] = '\0';
- X } else if (strncmp(buf, "Followup-To: ", 13) == 0) {
- X strncpy(note_h_followup, &buf[13], LEN);
- X note_h_followup[LEN-1] = '\0';
- X }
- X }
- X
- X note_page = 0;
- X note_mark[0] = ftell(note_fp);
- X
- X parse_from(note_h_from, note_from_addr, note_full_name);
- X note_end = FALSE;
- X
- X return;
- X}
- X
- X
- Xprompt_response(ch, respnum)
- Xint respnum;
- X{
- X int num;
- X
- X clear_message();
- X
- X if ((num = parse_num(ch, "Read response> ")) == -1) {
- X clear_message();
- X return(-1);
- X }
- X
- X return choose_resp( which_base(respnum), num );
- X}
- X
- X
- X/*
- X * return response number n from thread i
- X */
- X
- Xchoose_resp(i, n)
- Xint i;
- Xint n;
- X{
- X int j;
- X
- X j = base[i];
- X
- X while (n-- && arts[j].thread >= 0)
- X j = arts[j].thread;
- X
- X return j;
- X}
- X
- X
- X/*
- X * Parse various From: lines into the component mail addresses and
- X * real names
- X */
- X
- Xparse_from(str, addr, name)
- Xchar *str;
- Xchar *addr;
- Xchar *name;
- X{
- X while (*str && *str != ' ')
- X *addr++ = *str++;
- X *addr = '\0';
- X if (*str++ == ' ') {
- X if (*str++ == '(') {
- X if (*str == '"')
- X str++; /* Kill "quotes around names" */
- X /* But don't touch quotes inside the */
- X /* Name (that's what that nonsense */
- X /* below is for */
- X while (*str && *str != ')' && !(*str=='"'&&str[1]==')'))
- X *name++ = *str++;
- X }
- X }
- X *name = '\0';
- X}
- X
- X
- X/*
- X * Find the previous response. Go to the last response in the previous
- X * thread if we go past the beginning of this thread.
- X */
- X
- Xprev_response(n)
- Xint n;
- X{
- X int resp;
- X int i;
- X
- X resp = which_resp(n);
- X
- X if (resp > 0)
- X return choose_resp( which_base(n), resp-1 );
- X
- X i = which_base(n) - 1;
- X
- X if (i < 0)
- X return -1;
- X
- X return choose_resp( i, nresp(i) );
- X}
- X
- X
- X/*
- X * Find the next response. Go to the next basenote if there
- X * are no more responses in this thread
- X */
- X
- Xnext_response(n)
- Xint n;
- X{
- X int i;
- X
- X if (arts[n].thread >= 0)
- X return arts[n].thread;
- X
- X i = which_base(n) + 1;
- X
- X if (i >= top_base)
- X return -1;
- X
- X return base[i];
- X}
- X
- X
- X/*
- X * Given a respnum (index into arts[]), find the respnum of the
- X * next basenote
- X */
- X
- Xnext_basenote(n)
- Xint n;
- X{
- X int i;
- X
- X i = which_base(n) + 1;
- X if (i >= top_base)
- X return -1;
- X
- X return base[i];
- X}
- X
- Xvoid
- Xtass_page_help() {
- X char ch;
- X
- Xpage_help_start:
- X
- X ClearScreen();
- X center_line(0, TASS_HEADER);
- X center_line(1, "Article Pager Commands (page 1 of 2)");
- X
- X MoveCursor(3, 0);
- X
- X printf("0, = Read the base article in this thread\r\012");
- X printf("4 Read response 4 in this thread\r\012");
- X printf("<CR> Skip to next base article\r\012");
- X printf("<TAB> Advance to next page or unread article\r\012");
- X printf("b Back a page\r\012");
- X printf("f, w Post a followup\r\012");
- X printf("F, W Post a followup, copy text)\r\012");
- X printf("H Show article headers\r\012");
- X printf("i Return to index page\r\012");
- X printf("k, j Mark article as read & advance to next unread\r\012");
- X printf("K, J Mark rest of thread as read && advance to next unread\r\012");
- X printf("m Mail this article to someone\r\012");
- X printf("n Skip to the next article)\r\012");
- X printf("N Skip to the next unread article\r\012");
- X printf("p Go to the previous article\r\012");
- X printf("P Go to the previous unread article\r\012");
- X
- X center_line(LINES, "-- hit space for more commands --");
- X ch = ReadCh();
- X if (ch != ' ')
- X return;
- X
- X ClearScreen();
- X center_line(0, TASS_HEADER);
- X center_line(1, "Article Pager Commands (page 2 of 2)");
- X
- X MoveCursor(3, 0);
- X
- X printf("q Quit\r\012");
- X printf("r Reply through mail to author\r\012");
- X printf("R Reply through mail to author, copy text\r\012");
- X printf("s Save article to file\r\012");
- X printf("S Save thread to file\r\012");
- X printf("t Return to group selection index\r\012");
- X printf("z Mark article as unread\r\012");
- X printf("d, C, Z delete article (if it's yours)\r\012");
- X printf("^R Redisplay first page of article\r\012");
- X printf("%%, ^X Toggle rot-13 decoding for this article\r\012");
- X printf("- Show last message\r\012");
- X printf("| Pipe article into command\r\012");
- X
- X center_line(LINES, "-- hit any key --");
- X ch = ReadCh();
- X
- X if (ch == 'b')
- X goto page_help_start;
- X}
- X
- X
- X
- X/*
- X * Read a file grabbing the address given for To: and
- X * sticking it in mail_to
- X */
- Xvoid
- Xfind_new_to(nam, mail_to)
- Xchar *nam;
- Xchar *mail_to;
- X{
- X FILE *fp;
- X char buf[LEN];
- X char buf2[LEN];
- X char dummy[LEN];
- X char *ptr;
- X
- X fp = fopen(nam, "r");
- X if (fp != NULL) {
- X
- X while (fgets(buf, 1024, fp) != NULL) {
- X if (*buf == '\n')
- X break;
- X if (strncmp(buf, "To: ", 4) == 0) {
- X buf[strlen(buf)-1] = '\0';
- X strncpy(buf2, &buf[4], LEN);
- X buf2[LEN-1] = '\0';
- X parse_from(buf2, mail_to, dummy);
- X break;
- X }
- X }
- X
- X fclose(fp);
- X }
- X for (ptr = mail_to; *ptr; ++ptr)
- X if (*ptr == ',')
- X *ptr++ = ' ';
- X else if (*ptr == '(') {
- X int nest = 0;
- X while (*ptr) {
- X if (*ptr == '(')
- X ++nest;
- X else if (*ptr == ')')
- X --nest;
- X *ptr++ = ' ';
- X if (nest <= 0)
- X break;
- X }
- X } else
- X ++ptr;
- X}
- X
- Xvoid
- Xcancel_article () {
- X char buf[LEN+40];
- X FILE *pp;
- X int err;
- X
- X if (!note_h_messageid[0]) {
- X printf ("\rLost message-id!");
- X CleartoEOLN ();
- X return;
- X }
- X printf("\rCancel %s... ", note_h_messageid);
- X CleartoEOLN ();
- X#ifndef MNEWS
- X Insert your cancel-cmd here!
- X#else /* MNEWS */
- X sprintf(buf, "inews '-c=cancel:%s'", note_h_messageid);
- X#endif /* MNEWS */
- X if (pp = popen (buf, "w")) {
- X fprintf (pp, "\nArticle canceled from tass\n");
- X err = pclose (pp);
- X } else
- X err = 1;
- X if (! err)
- X printf("article canceled ");
- X else
- X printf("article not canceled ");
- X continue_prompt();
- X}
- X
- Xmail_to_someone() {
- X char nam[100];
- X FILE *fp;
- X char ch;
- X char buf[200];
- X char mail_to[LEN+1];
- X char subj[LEN+1];
- X int line;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X if (!parse_string("Mail article to: ", mail_to))
- X return(FALSE);
- X if (mail_to[0] == '\0')
- X return(FALSE);
- X
- X sprintf(nam, "%s/.letter", homedir);
- X umask (omask);
- X if ((fp = fopen(nam, "w")) == NULL) {
- X umask (0);
- X fprintf(stderr, "can't open %s: ", nam);
- X perror("");
- X return(FALSE);
- X }
- X#ifndef OSK
- X chmod(nam, 0600);
- X#else /* OSK */
- X chmod(nam, 013);
- X#endif /* OSK */
- X
- X fprintf(fp, "To: %s\n", mail_to);
- X fprintf(fp, "Subject: %s\n", note_h_subj);
- X if (*note_h_followup)
- X fprintf(fp, "Newsgroups: %s\n\n", note_h_followup);
- X else
- X fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
- X line = 3;
- X if (*my_org) {
- X fprintf(fp, "Organization: %s\n", my_org);
- X ++line;
- X }
- X fputs("\n", fp);
- X ++line;
- X
- X fseek(note_fp, 0L, 0);
- X copy_fp(note_fp, fp, "");
- X
- X fclose(fp);
- X umask (0);
- X
- X while (1) {
- X do {
- X MoveCursor(LINES, 0);
- X fputs("abort, edit, send: ", stdout);
- X fflush(stdout);
- X ch = ReadCh();
- X } while (ch != 'a' && ch != 'e' && ch != 's');
- X
- X switch (ch) {
- X case 'e':
- X invoke_editor(nam, line);
- X break;
- X
- X case 'a':
- X return FALSE;
- X
- X case 's':
- X/*
- X * Open letter an get the To: line in case they changed it with
- X * the editor
- X */
- X
- X find_new_to(nam, mail_to);
- X printf("\rMailing to %s...", mail_to);
- X CleartoEOLN ();
- X#ifndef OSK
- X sprintf(buf, "%s \"%s\" < %s", MAILER,
- X#else /* OSK */
- X sprintf(buf, "%s \"%s\" <%s", MAILER,
- X#endif /* OSK */
- X mail_to, nam);
- X if (invoke_cmd(buf)) {
- X printf("Message sent ");
- X fflush(stdout);
- X goto mail_to_someone_done;
- X } else {
- X printf("Command failed: %s ", buf);
- X fflush(stdout);
- X break;
- X }
- X }
- X }
- X
- Xmail_to_someone_done:
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X continue_prompt();
- X
- X return TRUE;
- X}
- X
- Xmail_to_author(copy_text)
- Xint copy_text;
- X{
- X char nam[100];
- X FILE *fp;
- X char ch;
- X char buf[200];
- X char mail_to[LEN+1];
- X int line;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X printf("\r\012Mailing to %s...\r\012\r\012", note_h_from);
- X
- X sprintf(nam, "%s/.letter", homedir);
- X umask (omask);
- X if ((fp = fopen(nam, "w")) == NULL) {
- X umask (0);
- X fprintf(stderr, "can't open %s: ", nam);
- X perror("");
- X return(FALSE);
- X }
- X#ifndef OSK
- X chmod(nam, 0600);
- X#else /* OSK */
- X chmod(nam, 013);
- X#endif /* OSK */
- X
- X fprintf(fp, "To: %s\n", note_h_from);
- X fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj) );
- X fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
- X line = 3;
- X if (*my_org) {
- X fprintf(fp, "Organization: %s\n", my_org);
- X ++line;
- X }
- X fputs("\n", fp);
- X ++line;
- X
- X if (copy_text) { /* if "copy_text" */
- X fprintf(fp, "In article %s you write:\n", note_h_messageid);
- X
- X fseek(note_fp, note_mark[0], 0);
- X#ifndef INCSTR
- X copy_fp(note_fp, fp, "> ");
- X#else /* INCSTR */
- X copy_fp(note_fp, fp, incstr);
- X#endif /* INCSTR */
- X }
- X
- X#ifdef APPEND_SIG
- X add_signature (fp);
- X#endif /* APPEND_SIG */
- X
- X fclose(fp);
- X umask (0);
- X
- X ch = 'e';
- X while (1) {
- X switch (ch) {
- X case 'e':
- X invoke_editor(nam, line);
- X break;
- X
- X case 'a':
- X return FALSE;
- X
- X case 's':
- X strcpy(mail_to, note_h_reply[0] ? note_h_reply : note_from_addr);
- X find_new_to(nam, mail_to);
- X printf("\rMailing to %s... ", mail_to);
- X CleartoEOLN ();
- X#ifndef OSK
- X sprintf(buf, "/usr/bin/rmail \"%s\" < %s",
- X#else /* OSK */
- X sprintf(buf, "%s \"%s\" <%s", MAILER,
- X#endif /* OSK */
- X mail_to, nam);
- X if (invoke_cmd(buf)) {
- X printf("Message sent ");
- X fflush(stdout);
- X goto mail_to_author_done;
- X } else {
- X printf("Command failed: %s ", buf);
- X fflush(stdout);
- X break;
- X }
- X }
- X
- X do {
- X MoveCursor(LINES, 0);
- X fputs("abort, edit, send: ", stdout);
- X fflush(stdout);
- X ch = ReadCh();
- X } while (ch != 'a' && ch != 'e' && ch != 's');
- X }
- X
- Xmail_to_author_done:
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X continue_prompt();
- X
- X return TRUE;
- X}
- X
- X
- Xpost_response(group, respnum)
- Xint respnum;
- X{
- X FILE *fp;
- X char nam[100];
- X char ch;
- X char buf[200];
- X int post_anyway = FALSE;
- X int line;
- X
- X if (*note_h_followup && strcmp(note_h_followup, "poster") == 0) {
- X clear_message();
- X MoveCursor(LINES,0);
- X printf("Note: Responses have been directed to the poster");
- X if (!prompt_yn("Post anyway? (y/n): "))
- X return FALSE;
- X *note_h_followup = '\0';
- X } else if (*note_h_followup && strcmp(note_h_followup, group) != 0) {
- X clear_message();
- X MoveCursor(LINES,0);
- X printf("Note: Responses have been directed to %s\r\012\r\012",
- X note_h_followup);
- X if (!prompt_yn("Continue? (y/n): "))
- X return FALSE;
- X }
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X sprintf(nam, "%s/.article", homedir);
- X umask (omask);
- X if ((fp = fopen(nam, "w")) == NULL) {
- X umask (0);
- X fprintf(stderr, "can't open %s: ", nam);
- X perror("");
- X return FALSE;
- X }
- X#ifndef OSK
- X chmod(nam, 0600);
- X#else /* OSK */
- X chmod(nam, 013);
- X#endif /* OSK */
- X
- X fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj));
- X
- X if (*note_h_followup && strcmp(note_h_followup, "poster") != 0)
- X fprintf(fp, "Newsgroups: %s\n", note_h_followup);
- X else
- X fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
- X line = 2;
- X
- X if (*my_org) {
- X fprintf(fp, "Organization: %s\n", my_org);
- X ++line;
- X }
- X
- X if (note_h_distrib != '\0') {
- X fprintf(fp, "Distribution: %s\n", note_h_distrib);
- X ++line;
- X }
- X
- X fprintf(fp, "References: %s\n", note_h_messageid);
- X fprintf(fp, "\n");
- X line += 2;
- X
- X if (respnum) { /* if "copy_text" */
- X fprintf(fp, "%s writes:\n", note_h_from);
- X ++line;
- X
- X fseek(note_fp, note_mark[0], 0);
- X#ifndef INCSTR
- X copy_fp(note_fp, fp, "> ");
- X#else /* INCSTR */
- X copy_fp(note_fp, fp, incstr);
- X#endif /* INCSTR */
- X }
- X
- X#ifdef APPEND_SIG
- X add_signature (fp);
- X#endif /* APPEND_SIG */
- X
- X fclose(fp);
- X umask (0);
- X
- X ch = 'e';
- X while (1) {
- X switch (ch) {
- X case 'e':
- X invoke_editor(nam, line);
- X break;
- X
- X case 'a':
- X return FALSE;
- X
- X case 'p':
- X printf("\rPosting... ");
- X CleartoEOLN ();
- X#ifndef OSK
- X sprintf(buf, "%s/inews -h < %s", LIBDIR, nam);
- X#else /* OSK */
- X sprintf(buf, "inews -h <%s", nam);
- X#endif /* OSK */
- X if (invoke_cmd(buf)) {
- X printf("article posted ");
- X fflush(stdout);
- X goto post_response_done;
- X } else {
- X printf("article rejected ");
- X fflush(stdout);
- X break;
- X }
- X }
- X
- X do {
- X MoveCursor(LINES, 0);
- X fputs("abort, edit, post: ", stdout);
- X fflush(stdout);
- X ch = ReadCh();
- X } while (ch != 'a' && ch != 'e' && ch != 'p');
- X }
- X
- Xpost_response_done:
- X#ifdef USE_UID
- X setuid(tass_uid);
- X setgid(tass_gid);
- X#endif /* USE_UID */
- X
- X continue_prompt();
- X
- X return TRUE;
- X}
- X
- Xvoid
- Xsave_art_to_file()
- X{
- X char nam[LEN];
- X FILE *fp;
- X char *p;
- X
- X if (!parse_string("Save article to file: ", nam))
- X return;
- X if (nam[0] == '\0')
- X return;
- X
- X for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
- X if (!*p)
- X return;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X if ((fp = fopen(p, "a+")) == NULL) {
- X umask (0);
- X fprintf(stderr, "can't open %s: ", nam);
- X perror("");
- X info_message("-- article not saved --");
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X return;
- X }
- X
- X MoveCursor(LINES, 0);
- X fputs("Saving...", stdout);
- X fflush(stdout);
- X
- X fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
- X
- X fseek(note_fp, 0L, 0);
- X copy_fp(note_fp, fp, "");
- X fputs("\n", fp);
- X
- X fclose(fp);
- X umask (0);
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X info_message("-- article saved --");
- X}
- X
- Xvoid
- Xsave_thread_to_file(respnum, group_path)
- Xlong respnum;
- Xchar *group_path;
- X{
- X char nam[LEN];
- X FILE *fp;
- X FILE *art;
- X int i;
- X char buf[8192];
- X int b;
- X int count = 0;
- X char *p;
- X
- X b = which_base(respnum);
- X
- X if (!parse_string("Save thread to file: ", nam))
- X return;
- X if (nam[0] == '\0')
- X return;
- X
- X for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
- X if (!*p)
- X return;
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X umask (omask);
- X if ((fp = fopen(nam, "a+")) == NULL) {
- X umask (0);
- X fprintf(stderr, "can't open %s: ", nam);
- X perror("");
- X info_message("-- thread not saved --");
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X return;
- X }
- X
- X MoveCursor(LINES, 0);
- X fputs("Saving... ", stdout);
- X fflush(stdout);
- X
- X note_cleanup();
- X
- X for (i = base[b]; i >= 0; i = arts[i].thread) {
- X open_note(arts[i].artnum, group_path);
- X
- X fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
- X fseek(note_fp, 0L, 0);
- X copy_fp(note_fp, fp, "");
- X fputs("\n", fp);
- X
- X note_cleanup();
- X printf("\b\b\b\b%4d", ++count);
- X fflush(stdout);
- X }
- X
- X fclose(fp);
- X umask (0);
- X
- X#ifdef USE_UID
- X setuid(real_uid);
- X setgid(real_gid);
- X#endif /* USE_UID */
- X
- X info_message("-- thread saved --");
- X open_note(arts[respnum].artnum, group_path);
- X}
- X
- Xvoid
- Xpipe_article() {
- X char command[LEN];
- X FILE *fp;
- X
- X if (!parse_string("Pipe to command: ", command))
- X return;
- X if (command[0] == '\0')
- X return;
- X
- X fp = popen(command, "w");
- X if (fp == NULL) {
- X fprintf(stderr, "command failed: ");
- X perror("");
- X goto pipe_article_done;
- X }
- X
- X fseek(note_fp, 0L, 0);
- X copy_fp(note_fp, fp, "");
- X pclose(fp);
- X
- Xpipe_article_done:
- X
- X continue_prompt();
- X}
- X
- __END__OF__THIS__FILE__
- exit 0
- : end of shell archive
-
- --
- Frank Kaefer # fkk@stasys.sta.sub.org # Starnberg, Germany
-