home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gdead.berkeley.edu
/
gdead.berkeley.edu.tar
/
gdead.berkeley.edu
/
pub
/
gdead
/
miscellaneous
/
vdig.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-10
|
33KB
|
1,660 lines
/*
* vdig - Display a digest the way vnews displays news.
*
* DESCRIPTION:
* vdig is a program that reads an internet digest format message
* (like the Dead-Flames), and displays it like vnews. For each
* message, vdig first displays the subject of the message,
* the name of the sender, the number of lines in the message,
* and a list of any other newsgroups to which the message cross-posted.
* vdig then prints a "more?" prompt in the lower left hand corner
* of the screen. If you want to see the message, type the space bar,
* and vdig will display the first page. If you want to skip the
* message, type the n key, and vdig will go on to the next message.
* After vdig displays the first page of a message, you can page
* through the message by typing the space bar. After vdig displays
* the last page of a message, when you type the space bar, vdig
* goes on to the next message.
*
* vdig has a number of other features like scrolling through a message
* a line or page at a time, saving an individual message in a file,
* replying to the sender of an individual message with email, etc.
* Type the question mark key for a list of what each key does.
*
* USAGE:
* vdig can read the digest from a named file, or from the standard
* input if no filename is given:
* % vdig file
* % vdig < file
* You can also use vdig within the Berkeley mailer (/usr/ucb/Mail)
* and just pipe the digest message directly to vdig, without having
* to save it in a file:
% Mail
Mail version SMI 4.0 Mon Aug 10 16:41:36 EDT 1992 Type ? for help.
"/usr/spool/mail/juo": 1 message 1 new
>N 1 Dead-Flames-Request@fuggles.acc.virginia.edu Thu Sep 10 00:05 711/26064 Dead-Flames Digest #240
& | vdig
Pipe to: "vdig"
*
* That also works with the System V mailer mailx.
*
* INSTALLATION:
* vdig uses the curses library. On most unix machines, you
* can compile it like this:
* % cc -o vdig vdig.c -lcurses
* On some, curses uses the termcap library, so you have to say
* this, instead:
* % cc -o vdig vdig.c -lcurses -ltermcap.
* I'm not sure how to do this on a PC.
* HISTORY:
* I picked this program up from a friend a while ago and haven't
* had to do much of anything to it. I've been using it for about
* a year without any major problems (on rare occasions things get
* hung when I run vdig from vmail and suspend them, but I've never
* bothered tracking that down to see if it is a vmail bug or a vdig
* bug; in either case it doesn't happen often). If you find any
* problems (or make any improvements) you can send mail to
* juo@cs.rutgers.edu.
*
* Version 0.1, 9/11/91
* Final "initial" version.
* Version 1.1, 9/10/92
* Add these comments, no code changes.
*
*/
#include <stdio.h>
#include <curses.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/stat.h>
extern int errno;
extern char *Malloc();
extern char *Realloc();
#define GROWTH (128)
#define MAXLINLEN (1024)
/* these shouldn't be hardwired */
int scrwidth = 79; /* set this to 1 less than your screen width to
minimize worries about getting screen boundary
just exactly perfect. */
int scrheight = 24;
struct mess
{
char *subject;
char *from;
char *crosspost;
int lines;
int len;
char *headers;
char *text;
char **bos;
char **eos;
int screenlines;
int headlines;
char **screen;
};
struct grow
{
int curlen;
int maxlen;
char *text;
};
struct mess *readmess ();
char *expandfilename ();
struct mess **messlist = NULL;
int nummess;
void catch ();
void catch2 ();
int caught = 0;
int tty_fd;
static jmp_buf pipe_env;
char title [128];
char status1 [1024];
char status2 [1024];
FILE *debug_fp = NULL;
main (argc, argv)
int argc;
char *argv [];
{
FILE *fp;
struct mess *m;
char *p;
char c;
int notdone;
int insamemsg;
char prompt [80];
char tmps [1024];
int lastpage;
int k;
int curmess;
int print_flag;
int prevmess;
int count;
int optind;
optind = 1;
if (optind < argc)
{
p = argv [optind];
if (*p == '-')
{
++p;
if (*p == 'd')
{
++p;
debug_fp = fopen (p, "w");
if (debug_fp == NULL)
{
perror (argv [0]);
exit (1);
}
++optind;
}
}
}
if (optind < argc)
{
fp = fopen (argv [optind], "r");
if (fp == NULL)
{
perror (argv [optind]);
exit (1);
}
readallmess (fp);
}
else
{
readallmess (stdin);
fp = freopen ("/dev/tty", "r", stdin);
if (fp == NULL)
{
perror (argv [0]);
exit (1);
}
}
screenon (0);
signal (SIGINT, catch);
if ( (nummess > 0) && (messlist [0]) && (messlist [0]->subject) )
strcpy (title, messlist [0]->subject);
else
strcpy (title, "");
notdone = 1;
curmess = 0;
prevmess = 0;
caught = 0;
status2 [0] = '\0';
while (notdone)
{
m = messlist [curmess];
if (m == NULL)
break;
setstatus1 (title, curmess, nummess - 1);
insamemsg = 1;
m->bos = m->screen;
m->eos = m->screen;
/* -1 only header, 1 skip header, 0 figure it */
print_flag = -1;
printmoremess (m, print_flag);
strcpy (prompt, "more? ");
lastpage = 0;
while (insamemsg)
{
caught = 0;
c = getcmdchar (prompt, &count);
switch (c)
{
case ' ' :
if (lastpage)
{
if ( (curmess + 1) < nummess)
{
++curmess;
insamemsg = 0;
}
break;
}
if (print_flag == -1)
print_flag = 1;
lastpage = printmoremess (m, print_flag);
print_flag = 0;
if (lastpage)
strcpy (prompt, "more? ");
else
sprintf (prompt, "more(%d%%)? ", percent (m) );
break;
case 'A' :
if ( (count >= 0) && count < nummess)
{
prevmess = curmess;
curmess = count;
insamemsg = 0;
}
break;
case 's' :
case 'w' :
savemess (m, c);
break;
case 'd' :
debug_printmess (m);
lastpage = redrawscreen (m, print_flag);
break;
case 'r' :
case 'R' :
case 'f' :
case 'F' :
mailmess (m, c, title);
lastpage = redrawscreen (m, print_flag);
break;
case '|' :
pipemess (m);
lastpage = redrawscreen (m, print_flag);
break;
case '?' :
printhelp ();
break;
/* fall through */
case '\014' :
lastpage = redrawscreen (m, print_flag);
#if 0
main_redraw :
m->eos = m->bos;
move (0, 0);
clear ();
refresh ();
lastpage = printmoremess (m, print_flag);
#endif
break;
case '\005' : /* ^E */
case '\016' : /* ^N */
case '\004' : /* ^D */
case '\006' : /* ^F */
if (count == 0)
count = 1;
if (c == '\004')
count = count * ( (scrheight - 4) / 2);
else if (c == '\006')
count = count * (scrheight - 4);
scrolldown (m, count);
print_flag = 0;
lastpage = printmoremess (m, print_flag);
if (lastpage)
strcpy (prompt, "more? ");
else
sprintf (prompt, "more(%d%%)? ", percent (m) );
break;
case '\031' : /* ^Y */
case '\020' : /* ^P */
case '\025' : /* ^U */
case '\002' : /* ^B */
if (count == 0)
count = 1;
if (c == '\025')
count = count * ( (scrheight - 4) / 2);
else if (c == '\002')
count = count * (scrheight - 4);
scrollup (m, count);
print_flag = 0;
lastpage = printmoremess (m, print_flag);
if (lastpage)
strcpy (prompt, "more? ");
else
sprintf (prompt, "more(%d%%)? ", percent (m) );
break;
case 'n' :
case '+' :
if (count == 0)
count = 1;
if ( (curmess + count) < nummess)
{
prevmess = curmess;
curmess = curmess + count;
insamemsg = 0;
}
break;
case 'b' :
if (count == 0)
count = 1;
if ( (curmess - count) >= 0)
{
prevmess = curmess;
curmess = curmess - count;
insamemsg = 0;
}
break;
case '-' :
if (prevmess != curmess)
{
int swapmess;
swapmess = prevmess;
prevmess = curmess;
curmess = swapmess;
insamemsg = 0;
}
break;
case 'q' :
case 'x' :
insamemsg = 0;
notdone = 0;
break;
}
}
}
#if 0
refresh ();
echo ();
nocbreak ();
move (scrheight - 1, 0);
addch ('\n');
refresh ();
endwin ();
#endif
screenoff ();
/* putchar ('\n'); */
if (debug_fp)
fclose (debug_fp);
}
redrawscreen (m, print_flag)
struct mess *m;
int print_flag;
{
int lastpage;
m->eos = m->bos;
move (0, 0);
clear ();
refresh ();
lastpage = printmoremess (m, print_flag);
return (lastpage);
}
char *
getsecondcmd (prompt)
char *prompt;
{
static char cmline [128];
int col;
int basecol;
char c;
move (scrheight - 2, 0);
clrtoeol ();
addstr (prompt);
basecol = strlen (prompt);
col = 0;
refresh ();
caught = 0;
c = getch ();
while ( (c != '\r') && (c != '\n') )
{
if (caught)
return (NULL);
if ( (c == '\010') || (c == '\377') )
{
if (col >0)
{
addch ('\010');
--col;
}
}
else if (c < ' ')
{
}
else
{
addch (c);
cmline [col] = c;
++col;
}
refresh ();
c = getch ();
}
cmline [col] = '\0';
return (cmline);
}
mailmess (m, savetype, title)
struct mess *m;
char savetype;
char *title;
{
FILE *fp;
char filename [256];
char tmps [1024];
int lastnl;
char *p;
struct stat buf;
struct stat buf2;
int k;
int append;
sprintf (filename, "/tmp/vd%05d", getpid () );
fp = fopen (filename, "w");
if (fp == NULL)
{
char tmps [1204];
sprintf (tmps, "Cannot open %s", filename);
seconderror (tmps);
return (1);
}
fprintf (fp, "To: %s\n", m->from);
fprintf (fp, "Subject: Re: %s\n", m->subject);
fprintf (fp, "-----\n");
fprintf (fp, "\n");
if ( (savetype == 'R') || (savetype == 'F') )
{
if (*title)
fprintf (fp, "In %s, ", title);
if (savetype == 'R')
fprintf (fp, "you write:\n");
else
fprintf (fp, "%s writes:\n", m->from);
lastnl = 1;
p = m->text;
while (*p)
{
if (lastnl)
{
fputc ('>', fp);
fputc (' ', fp);
lastnl = 0;
}
fputc (*p, fp);
if (*p == '\n')
lastnl = 1;
++p;
}
}
fclose (fp);
sprintf (tmps, "vi %s", filename);
screenoff ();
system (tmps);
dispose (filename);
screenon (1);
unlink (filename);
return (0);
}
dispose (filename)
char *filename;
{
char tmps [1024];
while (1)
{
fprintf (stderr, "What now, [s]end, [d]elete, [e]dit, [q]uit? ");
fgets (tmps, 1023, stdin);
if (tmps [0] == 'e')
{
sprintf (tmps, "vi %s", filename);
system (tmps);
}
else if (tmps [0] == 'd')
{
break;
}
else if (tmps [0] == 'q')
{
break;
}
else if (tmps [0] == 's')
{
if (dosend (filename) == 0)
break;
}
}
return (0);
}
dosend (filename)
char *filename;
{
FILE *fp;
FILE *fpmail;
char *p;
char *q;
char tmps [MAXLINLEN + 1];
char to [MAXLINLEN + 1];
char cc [MAXLINLEN + 1];
int haveto;
int havecc;
int k;
int rc;
int gotdash;
void (*old_sigpipe)();
void broken_pipe ();
fp = fopen (filename, "r");
if (fp == NULL)
{
perror (filename);
return (-1);
}
haveto = 0;
havecc = 0;
while (p = fgets (tmps, MAXLINLEN, fp) )
{
if (strncmp (tmps, "To: ", 4) == 0)
{
#define BINMAIL 1
#ifdef BINMAIL
if (haveto)
{
fprintf (stderr, "Can not handle multiple To: addresses\n");
fclose (fp);
return (-1);
}
if (parseaddr (tmps + 4, to, "To:") != 0)
{
fclose (fp);
return (-1);
}
#endif
haveto = 1;
}
#ifdef BINMAIL
else if (strncmp (tmps, "Bcc: ", 5) == 0)
{
if (havecc)
{
fprintf (stderr, "Can not handle multiple Cc/Bcc: addresses\n");
fclose (fp);
return (-1);
}
if (parseaddr (tmps + 5, cc, "Bcc:") != 0)
{
fclose (fp);
return (-1);
}
havecc = 1;
}
else if (strncmp (tmps, "Cc: ", 4) == 0)
{
if (havecc)
{
fprintf (stderr, "Can not handle multiple Cc/Bcc: addresses\n");
fclose (fp);
return (-1);
}
if (parseaddr (tmps + 4, cc, "Cc:") != 0)
{
fclose (fp);
return (-1);
}
havecc = 1;
}
#endif
else if (strcmp (tmps, "-----\n") == 0)
break;
}
if (p == NULL)
{
fprintf (stderr, "Missing ----- line, can not send.\n");
return (1);
}
if (haveto == 0)
{
fprintf (stderr, "Missing To: address, can not send.\n");
return (1);
}
#ifdef BINMAIL
if (havecc)
sprintf (tmps, "/bin/mail %s %s", to, cc);
else
sprintf (tmps, "/bin/mail %s", to);
#endif
fprintf (stderr, "would: %s\n", tmps);
fpmail = popen (tmps, "w");
if (fpmail == NULL)
{
perror (tmps);
fclose (fp);
return (-1);
}
fseek (fp, 0, 0);
old_sigpipe = signal (SIGPIPE, broken_pipe);
if (setjmp (pipe_env) == 0)
{
gotdash = 0;
while (p = fgets (tmps, MAXLINLEN, fp) )
{
if (!gotdash && (strcmp (tmps, "-----\n") == 0) )
{
gotdash = 1;
continue;
}
#ifdef BINMAIL
if (!gotdash && (strncmp (tmps, "Bcc: ", 5) == 0) )
continue;
#endif
fputs (tmps, fpmail);
}
rc = 0;
sprintf (status2, "Reply sent to %s", to);
}
else
{
rc = 1;
}
signal (SIGPIPE, old_sigpipe);
pclose (fpmail);
fclose (fp);
return (rc);
}
parseaddr (src, addr, addrname)
char *src;
char *addr;
char *addrname;
{
int k;
char *p;
char *q;
char close;
k = 0;
p = src;
q = addr;
while ( (*p != '\n') && (*p != '\0') )
{
if (*p == '<')
break;
++p;
}
if (*p == '<')
{
++p;
while ( (*p != '>') && (*p != '\0') && (k < MAXLINLEN) )
{
*q++ = *p++;
++k;
}
if (*p != '>')
{
fprintf (stderr, "Missing > in %s address\n", addrname);
return (-1);
}
*q++ = '\0';
return (0);
}
p = src;
while (*p == ' ')
++p;
if ( (*p == '"') || (*p == '(') )
{
if (*p == '"')
close = '"';
else
close = ')';
while ( (*p != close) && (*p != '\0') )
++p;
if (*p != close)
{
fprintf (stderr, "Missing closing %s in %s address\n",
close, addrname);
return (-1);
}
while (*p == ' ')
++p;
}
while ( (*p != '\n') && (*p != '\0') && (*p != '"') &&
(*p != '(') && (k < MAXLINLEN) )
{
*q++ = *p++;
++k;
}
*q = '\0';
return (0);
}
savemess (m, savetype)
struct mess *m;
char savetype;
{
FILE *fp;
char *filename;
char *p;
struct stat buf;
int k;
int append;
filename = getsecondcmd ("file: ");
if ( (filename == NULL) || (*filename == '\0') )
{
move (scrheight - 2, 0);
clrtoeol ();
return (1);
}
filename = expandfilename (filename);
k = stat (filename, &buf);
if (k == 0)
append = 1;
else
append = 0;
if (append)
fp = fopen (filename, "a");
else
fp = fopen (filename, "w");
if (fp == NULL)
{
char tmps [1204];
sprintf (tmps, "Cannot open %s", filename);
seconderror (tmps);
return (1);
}
if (savetype == 's')
{
p = m->headers;
while (*p)
{
fputc (*p, fp);
++p;
}
fputc ('\n', fp);
}
p = m->text;
while (*p)
{
fputc (*p, fp);
++p;
}
fclose (fp);
if (append)
addstr (" appended");
else
addstr (" created");
return (0);
}
pipemess (m)
struct mess *m;
{
FILE *fp;
char *filename;
char *p;
int k;
void broken_pipe ();
void (*old_sigpipe)();
filename = getsecondcmd ("|");
if ( (filename == NULL) || (*filename == '\0') )
{
move (scrheight - 2, 0);
clrtoeol ();
return (1);
}
screenoff ();
fp = popen (filename, "w");
if (fp == NULL)
{
char tmps [1204];
sprintf (tmps, "Cannot popen %s\n", filename);
fputs (tmps, stderr);
screenon (1);
return (1);
}
old_sigpipe = signal (SIGPIPE, broken_pipe);
if (setjmp (pipe_env) == 0)
{
p = m->headers;
while (*p)
{
fputc (*p, fp);
++p;
}
fputc ('\n', fp);
p = m->text;
while (*p)
{
fputc (*p, fp);
++p;
}
}
signal (SIGPIPE, old_sigpipe);
pclose (fp);
screenon (1);
return (0);
}
void
broken_pipe (sig)
int sig;
{
longjmp (pipe_env, 1);
}
char *
expandfilename (s)
char *s;
{
extern char *getenv ();
static char filename [1024];
char *home;
if ( (s [0] != '~') || (s [1] != '/') )
return (s);
home = getenv ("HOME");
if (home == NULL)
return (s);
strcpy (filename, home);
strcat (filename, s + 1);
return (filename);
}
printmoremess (m, print_flag)
struct mess *m;
int print_flag;
{
char tmps [128];
int lines;
int width;
int last_was_nl;
char *p;
char *q;
int k;
int start_y;
int more_count;
char **line;
int done;
start_y = 0;
more_count = scrheight - 2;
line = m->eos;
if (print_flag != 1)
m->bos = line;
if (print_flag == -1)
{
move (0, 0);
clrtobot ();
for (k = 0; k < m->headlines; ++k)
{
addstr (*line);
addch ('\n');
++line;
}
done = (*line == NULL);
if (line != m->screen)
--line;
m->eos = line;
return (done);
}
else if (print_flag == 1)
{
start_y = m->headlines - 1;
more_count = (scrheight - 2) - (m->headlines - 1);
}
else
{
start_y = 0;
more_count = scrheight - 2;
}
move (start_y, 0);
clrtobot ();
for (k = 0; k < more_count; ++k)
{
if (*line == NULL)
break;
if (**line)
addstr (*line);
addch ('\n');
++line;
}
done = (*line == NULL);
if (line != m->screen)
--line;
m->eos = line;
return (done);
}
readallmess (fp)
FILE *fp;
{
struct mess *m;
int maxmess;
maxmess = 50;
nummess = 0;
messlist = (struct mess **) Malloc (maxmess * sizeof (struct mess *) );
while (m = readmess (fp) )
{
if ( (nummess + 1) >= maxmess)
{
maxmess += 50;
messlist = (struct mess **) Realloc (maxmess *
sizeof (struct mess *) );
}
messlist [nummess] = m;
++nummess;
formatmess (m);
}
}
formatmess (m)
struct mess *m;
{
/* ++curlines; */
#define GROWSCREEN() {\
if (curlines >= (maxlines - 1) )\
{\
maxlines += 20;\
screen = (char **) Realloc (screen, maxlines * sizeof (char *) );\
}\
}
char **screen;
int maxlines;
int curlines;
int headlines;
char *p;
char *q;
char *s;
char tmps [MAXLINLEN + 16];
int n;
maxlines = 20;
curlines = 0;
screen = (char **) Malloc (maxlines * sizeof (char *) );
if (m->subject)
{
sprintf (tmps, "Subject: %s", m->subject);
n = strlen (tmps);
p = tmps;
while (n >= scrwidth)
{
s = Malloc (scrwidth + 1);
strncpy (s, p, scrwidth);
/* s [scrwidth - 1] = '\0'; */
s [scrwidth] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
n = n - (scrwidth);
p = p + (scrwidth);
}
s = Malloc (n + 1);
strcpy (s, p);
screen [curlines] = s;
++curlines;
GROWSCREEN ();
}
else
{
s = screen [curlines];
s = Malloc (17);
strcpy (s, "Subject: [none]");
screen [curlines] = s;
++curlines;
GROWSCREEN ();
}
if (m->from)
{
sprintf (tmps, "From: %s", m->from);
n = strlen (tmps);
p = tmps;
while (n >= scrwidth)
{
s = Malloc (scrwidth + 1);
strncpy (s, p, scrwidth);
s [scrwidth] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
n = n - scrwidth;
p = p + scrwidth;
}
s = Malloc (n + 1);
strcpy (s, p);
screen [curlines] = s;
++curlines;
GROWSCREEN ();
}
else
{
screen [curlines] = Malloc (17);
strcpy (screen [curlines], "From: [unknown]");
++curlines;
GROWSCREEN ();
}
if (m->crosspost)
{
sprintf (tmps, "Crossposted-To: %s", m->crosspost);
n = strlen (tmps);
p = tmps;
while (n >= scrwidth)
{
s = Malloc (scrwidth + 1);
strncpy (s, p, scrwidth);
s [scrwidth] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
n = n - scrwidth;
p = p + scrwidth;
}
s = Malloc (n + 1);
strcpy (s, p);
screen [curlines] = s;
++curlines;
GROWSCREEN ();
}
sprintf (tmps, "(%d lines)", m->lines);
s = Malloc (strlen (tmps) + 1);
strcpy (s, tmps);
screen [curlines] = s;
++curlines;
GROWSCREEN ();
s = Malloc (2);
s [0] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
headlines = curlines;
if (m->text)
{
p = m->text;
while (*p)
{
n = linlen (p);
while (n >= scrwidth)
{
s = Malloc (scrwidth + 1);
strncpy (s, p, scrwidth);
s [scrwidth] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
n = n - scrwidth;
p = p + scrwidth;
}
s = Malloc (n + 2);
if (n > 0)
{
strncpy (s, p, n);
}
s [n] = '\0';
screen [curlines] = s;
++curlines;
GROWSCREEN ();
p = p + n;
if (*p)
++p;
}
}
screen [curlines] = NULL;
m->screen = screen;
m->screenlines = curlines;
m->headlines = headlines;
#undef GROWSCREEN
}
linlen (p)
char *p;
{
int n;
n = 0;
while ( (*p != '\n') && (*p != '\r') && (*p != '\0') )
{
++p;
++n;
}
return (n);
}
getcmdchar (prompt, count)
char *prompt;
int *count;
{
char c;
int n;
n = 0;
if (status2 [0] != '\0')
{
move (scrheight - 2, 0);
clrtoeol ();
addstr (status2);
status2 [0] = '\0';
}
move (scrheight - 1, 0);
clrtoeol ();
if (status1 [0] != '\0')
{
move (scrheight - 1, 10);
addstr (status1);
move (scrheight - 1, 0);
}
addstr (prompt);
refresh ();
c = getch ();
while ( ('0' <= c) && (c <= '9') )
{
n = 10 * n + c - '0';
c = getch ();
}
if (count)
*count = n;
return (c);
}
printmesshead (m)
struct mess *m;
{
char tmps [256];
move (0, 0);
clear ();
addstr ("Subject: ");
if (m->subject)
addstr (m->subject);
addch ('\n');
addstr ("From: ");
if (m->from)
addstr (m->from);
addch ('\n');
sprintf (tmps, "(%d lines)", m->lines);
addstr (tmps);
addch ('\n');
}
struct mess *
readmess (fp)
FILE *fp;
{
struct mess *m;
char tmps [1024];
int curlen;
int maxlen;
char *grow;
char *p;
int n;
int line_count;
int got_header;
do
{
if (fgets (tmps, 1023, fp) == NULL)
{
return (NULL);
}
} while (blank (tmps) );
m = (struct mess *) Malloc (sizeof (struct mess) );
m->from = NULL;
m->subject = NULL;
m->crosspost = NULL;
m->text = NULL;
m->headers = NULL;
m->lines = 0;
m->screen = NULL;
m->screenlines = 0;
m->len = 0;
grow = (char *) Malloc (GROWTH);
maxlen = GROWTH;
curlen = 0;
*grow = '\0';
line_count = 0;
got_header = 0;
while (!blank (tmps) )
{
n = strlen (tmps);
while ( (curlen + n) >= maxlen)
{
grow = (char *) Realloc (grow, maxlen + GROWTH);
maxlen += GROWTH;
}
strcpy (grow + curlen, tmps);
curlen += n;
++line_count;
if (debug_fp)
{
fprintf (debug_fp, "read 1: \"%s\"\n", tmps);
}
if (strncmp (tmps, "From: ", 6) == 0)
{
n = strlen (tmps + 6);
m->from = (char *) Malloc (n);
strncpy (m->from, tmps + 6, n - 1);
m->from [n - 1] = '\0';
got_header = 1;
}
else if (strncmp (tmps, "Subject: ", 9) == 0)
{
n = strlen (tmps + 9);
m->subject = (char *) Malloc (n);
strncpy (m->subject, tmps + 9, n - 1);
m->subject [n - 1] = '\0';
got_header = 1;
}
else if (strncmp (tmps, "Crossposted-To: ", 16) == 0)
{
n = strlen (tmps + 16);
m->crosspost = (char *) Malloc (n);
strncpy (m->crosspost, tmps + 16, n - 1);
m->crosspost [n - 1] = '\0';
got_header = 1;
}
if (fgets (tmps, 1023, fp) == NULL)
{
m->text = grow;
m->lines = line_count;
m->len = curlen;
return (m);
}
}
m->headers = grow;
grow = (char *) Malloc (GROWTH);
maxlen = GROWTH;
curlen = 0;
*grow = '\0';
line_count = 0;
while (fgets (tmps, 1023, fp) != NULL)
{
if (debug_fp)
{
fprintf (debug_fp, "read 2: \"%s\"\n", tmps);
}
/* if ( (tmps [0] == '-') && (tmps [1] != ' ') ) */
if (strncmp (tmps, "------------------------------", 20) == 0)
break;
n = strlen (tmps);
while ( (curlen + n) >= maxlen)
{
grow = (char *) Realloc (grow, maxlen + GROWTH);
maxlen += GROWTH;
}
strcpy (grow + curlen, tmps);
curlen += n;
++line_count;
}
m->text = grow;
m->lines = line_count;
m->len = curlen;
if (debug_fp)
{
fprintf (debug_fp, "read 3: m->lines = %d, m->len = %d\n", m->lines,
m->len);
}
return (m);
}
blank (p)
char *p;
{
while ( (*p == ' ') || (*p == '\t') || (*p == '\n') )
++p;
return (*p == '\0');
}
debug_printmess (m)
struct mess *m;
{
int k;
char *s;
char **line;
move (2, 0);
clrtobot ();
if (m->subject)
printw ("subject = \"%s\"\n", m->subject);
else
printw ("subject = NULL\n");
if (m->from)
printw ("from = \"%s\"\n", m->from);
else
printw ("from = NULL\n");
printw ("bos = %d = 0x%x\n", m->bos, m->bos);
printw ("eos = %d = 0x%x\n", m->eos, m->bos);
refresh ();
if (m->screen)
{
line = m->screen;
k = 0;
while ( (*line) && (k < 9) )
{
/* printw ("X%sX\n", *line); */
printw ("X 0x%x 0x%x %sX\n", line, *line);
refresh ();
++line;
++k;
}
/* printw ("text = \"%s\"\n", m->text); */
}
else
printw ("screen = NULL\n");
refresh ();
getcmdchar ("continue", NULL);
}
scrolldown (m, count)
struct mess *m;
int count;
{
int j;
int k;
char **line;
line = m->eos = m->bos;
for (j = 0; (j < count) && (*line != NULL); ++j)
++line;
m->eos = line;
}
scrollup (m, count)
struct mess *m;
int count;
{
int j;
int k;
char **line;
line = m->eos = m->bos;
for (j = 0; (j < count) && (line > m->screen); ++j)
--line;
m->eos = line;
}
percent (m)
struct mess *m;
{
int percent;
percent = (100 * (m->eos - m->screen) ) / m->screenlines;
if (percent >= 100)
percent = 99;
return (percent);
}
seconderror (s)
char *s;
{
move (scrheight - 2, 0);
clrtoeol ();
addstr (s);
}
void
catch (sig)
int sig;
{
caught = sig;
}
void
catch2 (sig)
int sig;
{
char tmps [1204];
sprintf (tmps, "\ncaught sig %d\n", sig);
err2 (tmps);
}
screenon (needreturn)
int needreturn;
{
char c;
int x;
int y;
fflush (stdin);
fflush (stdout);
fflush (stderr);
if (needreturn)
{
fputs ("[Hit return to continue]\n", stderr);
c = getchar ();
while ( (c != '\n') && (c != '\r') )
{
fputs ("hit return...\n", stderr);
c = getchar ();
}
}
initscr ();
#if 0 /* this doesn't really work quite right anyways, so just
* assume 24x80 for now... */
#ifdef SYSV
getmaxyx (stdscr, y, x);
#else
#ifdef BSD
{
struct winsize ws;
if (ioctl (fileno (stdin), TIOCGWINSZ, &ws) == 0)
{
y = ws.ws_row;
x = ws.ws_col;
}
else
{
y = 0;
x = 0;
}
}
#endif
#endif
if (y > 0)
scrheight = y;
if (x > 0)
scrwidth = x - 1;
#endif
cbreak ();
noecho ();
refresh ();
}
screenoff ()
{
refresh ();
echo ();
nocbreak ();
move (scrheight - 1, 0);
addch ('\n');
refresh ();
endwin ();
fflush (stdin);
fflush (stdout);
fflush (stderr);
}
err2 (s)
char *s;
{
write (2, s, strlen (s) );
}
char *
Malloc (n)
int n;
{
void *p;
p = (void *) malloc (n);
if (p == NULL)
{
fprintf (stderr, "\nMalloc (%d), out of memory\n", n);
}
return (p);
}
char *
Realloc (p, n)
void *p;
int n;
{
void *q;
q = (void *) realloc (p, n);
if (q == NULL)
{
fprintf (stderr, "\nRealloc (%d), out of memory\n", n);
}
return (q);
}
setstatus1 (title, curmess, nummess)
char *title;
int curmess;
int nummess;
{
int j;
int k;
int pad_blanks;
char *p;
char *q;
char tmps [128];
sprintf (tmps, "%d/%d", curmess, nummess);
j = strlen (title) + 4;
k = strlen (tmps);
if (j + 20 < scrwidth)
{
pad_blanks = ( ( (scrwidth - 20) - j) / 2) + 2;
q = status1;
for (j = 0; j < pad_blanks; ++j)
*q++ = ' ';
p = title;
while (*p)
*q++ = *p++;
pad_blanks = pad_blanks + (9 - k);
for (j = 0; j < pad_blanks; ++j)
*q++ = ' ';
strcpy (q, tmps);
}
else if (k + 10 < scrwidth)
{
pad_blanks = (scrwidth - 10 - strlen (tmps) );
q = status1;
for (j = 0; j < pad_blanks; ++j)
*q++ = ' ';
strcpy (q, tmps);
}
else
{
status1 [0] = '\0';
}
}
/*
Vnews commands: ( may be preceded by a non-negative count) V 2.2 1/17/89
CR Next page or article D Decrypt a rot 13 joke
n Go to next article A Go to article numbered count
e Mark current article as unread < Go to article with given ID
+ or = Go forwards count articles p Go to parent article
- Go to previous article ug Unsubscribe to this group
^B Go backwards count pages ^L Redraw screen
^N Go forward count lines v Print netnews version
^P Go backwards count lines q Quit
^D Go forward half a page x Quit without updating .newsrc
^U Go backwards half a page c Cancel the current article
h Display article header H Display all article headers
! Escape to shell ? Display this message
r Reply to article using editor K Mark rest of newsgroup read
R Reply--put current article in reply b Go back 1 article in same group
ESC-r Reply directly using mailer m Move on to next item in a digest
f Post a followup article s Save article in file
N Go to newsgroup (next is default) w Save without header
l List unread articles in group L List all articles in group
[Press CR to see article, h to see header... (any command will work)]
*/
/*
' '
A
s
w
r
R
f
F
|
^L
^E ^D
^Y ^U
n
b
q
x
Vdig commands: ( may be preceded by a non-negative count)
CR Next page or article D
n Go to next article A Go to article numbered count
e <
[ + or = Go forwards count articles ] p
[ - Go to previous article ] ug
^B Go backwards count pages ^L Redraw screen
^N Go forward count lines [ v Print netnews version ]
^P Go backwards count lines q Quit
^D Go forward half a page x
^U Go backwards half a page c
h H
! Escape to shell ? Display this message
r Reply to article using editor K
R Reply--put current article in reply b Go back 1 article in same group
[ ESC-r Reply directly using mailer ] m
f Post a followup article s Save article in file
N w Save without header
l L
[Press CR to see article, h to see header... (any command will work)]
*/
printhelp ()
{
char *s = "\n\
\n\
vdig commands: ( may be preceded by a non-negative count) V 1.1 9/10/92\n\
CR Next page or article A Go to article numbered count\n\
n Go to next article b Go back count articles\n\
+ Go forwards count articles - Go to previous article\n\
^B Go backwards count pages ^F Go forwards count pages\n\
^D Go forward half a page ^U Go backwards half a page\n\
^N Go forward count lines ^P Go backwards count lines\n\
r Reply to article using editor R Reply--put current article in reply\n\
f Post a followup article ? Display this message\n\
s Save article in file w Save without header\n\
^L Redraw screen q Quit\n\
\n\
[Press CR to see article, h to see header... (any command will work)]\n\
";
move (0, 0);
clear ();
refresh ();
addstr (s);
refresh ();
}