home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
lan
/
snuz.arj
/
SNUZ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-23
|
33KB
|
1,437 lines
/* Snuz -- an NNTP News Reader for the IBM-PC */
/*
* This program is a vastly enlarged and improved version of the program
* "red" from the pcip distribution. The new parts are written by J.D.
* McDonald and are public domain. The older parts are also freely
* distributable. See the pcip distribution for more details. The version of
* pcip this compiles with was obtained from husc6.harvard.edu. It probably
* will not work with other versions. To compile this, use Microsoft C 5.1
* and the include files provided with pcip - not Microsoft's ones. It is
* small model and probably needs the /Gs switch. The picp libraries needed
* are tcp, domain, udp, packet, ip, net, task, and pc. Also needed is the
* file proto.c.
*/
/*
* Further note: I don't really understand how the Internet works, or the
* internals of pcip, at least not completely. NNTP itself is fairly easy to
* understand. Basically, this was cooked up using by expanding on code
* somebody else had written.
*/
#include <stdio.h>
#include <ctype.h>
#include <process.h>
#include <string.h>
long time(long *);
char *malloc(unsigned);
int kbhit(void);
int rename(char *, char *);
int remove(char *);
void perror(char *);
int atoi(char *);
extern int errno;
#define NGROUPS 600
#define STRING 512
char serverhost[128];
char newsrc[128] = "snuz.rc";
char fromline[128];
char editorpath[128];
char smtppath[128];
char tmpdir[128] = "c:";
char *version = "\nSnuz ver. 1.00\n\n";
char tmpfil[128];
struct servent *ser;
struct hostent *hp;
FILE *server;
int serverfd;
int reply;
unsigned long reparticle;
char cur_gname[STRING];
int cur_group;
unsigned long cur_numa, cur_first, cur_last;
unsigned long cur_article;
unsigned long follow_up_article;
char cur_articleid[STRING];
char cur_path[STRING], cur_from[STRING], cur_subject[STRING], cur_replyto[STRING];
char cur_newsgroups[STRING], cur_message_ID[STRING], cur_references[STRING];
char cur_date[STRING];
char *groups[NGROUPS];
unsigned long firsts[NGROUPS];
int ngroups;
int bogus = 0;
char *servp;
int servf;
char servb[2048];
void startup(int, char **);
void compactgroups(void);
void qexit(int);
int cstat(unsigned long);
void docommand(void);
void dumpnewsrc(void);
int postnews(void);
void sendmail(void);
int extract(char *, char *, char *);
void pcip_exit(void);
int netsocket(void);
void getserv(char *, int);
int saveactive(char *);
void getnewsrc(void);
int cgroup(char *);
int cnext(void);
int chead(void);
int checkx(void);
int ngetc(void);
int showbody(void);
int savebody(int);
int getgroup(char *);
void putserv(char *);
int tcpwrite(int, char *, int);
void usleep(void);
void xabort(void);
void clearscreen(void);
int showindex(int);
void listgroups(void);
int getpost(int);
void reversevideo(char *);
void normalvideo(void);
void backline(void);
int tcpread(int, char *, int);
int tcpopen(char *, int);
int valid_header(char *);
char *getenv(char *);
int
main(int argc, char **argv)
{
startup(argc, argv);
docommand();
dumpnewsrc();
postnews();
qexit(0);
pcip_exit(); /* this routine does all the 'onexit' processing which has
* been called for when initializing the pcip package */
sendmail(); /* this routine never returns */
return 0;
}
void
startup(int argc, char **argv)
{
char buf[STRING];
FILE *cfgfile;
char *ptr;
int i;
if (argc == 2 || argc > 3 || (argc == 3 && (!argv[2] ||
argv[1][0] != '-' || argv[1][1] != 'S'))) {
printf("Useage: snuz [-S filename] (-S makes list of newsgroups)\n");
exit(1);
}
ptr = argv[0];
while (*ptr)
*ptr++;
while (*ptr != ':' && *ptr != '\\' && *ptr != '/' && ptr != argv[0])
*(ptr--) = 0;
if((ptr = getenv("SNUZCFG")) == NULL)
strcpy(buf, argv[0]);
else {
strcpy(buf, ptr);
strcat(buf, "\\");
}
strcat(buf, "snuz.cfg");
if ((cfgfile = fopen(buf, "r")) == NULL) {
printf("can't open snuz.cfg file %s\n", buf);
exit(1);
}
while (1) {
if (fgets(buf, 126, cfgfile) == NULL)
break;
extract(newsrc, "SNUZRC=", buf);
extract(serverhost, "NNTPHOST=", buf);
extract(fromline, "NNTPFROM=", buf);
extract(editorpath, "EDITOR=", buf);
extract(tmpdir, "TMP=", buf);
extract(smtppath, "SMTPPATH=", buf);
}
fclose(cfgfile);
for (i = 0; i < 128; i++) {
if (newsrc[i] == '\n')
newsrc[i] = 0;
if (serverhost[i] == '\n')
serverhost[i] = 0;
if (fromline[i] == '\n')
fromline[i] = 0;
if (editorpath[i] == '\n')
editorpath[i] = 0;
if (tmpdir[i] == '\n')
tmpdir[i] = 0;
if (smtppath[i] == '\n')
smtppath[i] = 0;
}
if (!(*serverhost) || !(*fromline) || !(*editorpath) || !(*smtppath)) {
printf("incomplete snuz.cfg file\n");
exit(1);
}
strcat(tmpdir, "\\");
printf(version);
if (argc == 3) {
serverfd = netsocket();
servf = 0;
getserv(buf, sizeof buf);
saveactive(argv[2]);
qexit(1);
}
getnewsrc();
if (ngroups < 2) {
printf("You need at least two newsgroups\n");
exit(1);
}
serverfd = netsocket(); /* Note: this call does a lot, including
* setting up some important onexit routines. */
servf = 0;
getserv(buf, sizeof buf);
buf[77] = '\0';
printf("[%s]\n", buf);
}
void
docommand()
{
char buf[128];
char *ptr;
int cug, nug;
int ch, i, qhead;
int skipgroup = 0;
int noquery = 0;
int oldquery = 0;
int noxpost = 1;
int skipalready = 0;
FILE *qfile, *ifile;
long xtime;
unsigned long ltemp;
long save_article;
cug = 0;
cur_article = firsts[0];
cur_group = -1;
nug = 1;
while (1) {
if (nug) {
nug = 0;
follow_up_article = 0xffffffff;
if (cug < 0) {
printf("▒▒▒▒▒▒ trying to read before first group ▒▒▒▒▒▒ *\n");
cug = 0;
cur_article = firsts[cug];
cur_group = -1;
}
if (cug >= ngroups) {
printf("▒▒▒▒▒▒ trying to read after last group ▒▒▒▒▒▒ \n");
cug = ngroups - 1;
cur_article = firsts[cug];
cur_group = -1;
}
if (cug != cur_group) {
printf("\n▒▒▒▒▒▒ %s ▒▒▒▒▒▒\n", groups[cug]);
if (cgroup(groups[cug])) {
printf("[invalid or deleted group]\n");
if (++bogus >= 30) {
qexit(10);
}
groups[cug] = NULL;
firsts[cug] = 0;
compactgroups();
cug++;
cur_group = -1;
if (cug >= ngroups)
cug = 0;
nug++;
continue;
}
printf("First: %U Last: %U Current: %U\n\n",
cur_first, cur_last, firsts[cug] > cur_last ? cur_last :
firsts[cug]);
}
cur_group = cug;
if (firsts[cug] < cur_first)
firsts[cug] = cur_first;
if (firsts[cug] > cur_last + 1)
firsts[cug] = cur_last + 1;
if (cur_numa == 0) {
if (!skipalready || cug >= ngroups - 1 || kbhit()) {
printf("▒▒▒▒▒▒ no articles in this group ▒▒▒▒▒▒\n");
skipgroup = 2;
} else {
cug++;
nug++;
continue;
}
} else if (cstat(firsts[cug]) && cstat(cur_last)) {
if (!skipalready || cug >= ngroups - 1 || kbhit()) {
printf("▒▒▒▒▒▒ group inaccessible ▒▒▒▒▒▒\n");
skipgroup = 2;
} else {
cug++;
nug++;
continue;
}
} else if (firsts[cug] > cur_last) {
if (!skipalready || cug >= ngroups - 1 || kbhit()) {
printf(
"▒▒▒▒▒▒ already read last article - <RETURN> will skip group ▒▒▒▒▒▒\n");
skipgroup = 1;
} else {
cug++;
nug++;
continue;
}
}
} else {
if (cnext()) {
printf("▒▒▒▒▒▒ End of group %s ▒▒▒▒▒▒\n", groups[cug]);
skipgroup = 2;
firsts[cug] = cur_last + 1;
}
}
qhead = chead();
if (!skipgroup) {
if (qhead) {
printf("[article %U: bad header]\n", cur_article);
firsts[cug] = cur_article + 1;
continue;
}
if (noxpost && checkx()) {
firsts[cug] = cur_article + 1;
continue;
}
}
query:
{
if (noquery)
ch = 'y';
else if (oldquery)
ch = oldquery;
else {
printf(">");
ch = ngetc();
}
oldquery = 0;
noquery = 0;
if ((skipgroup && ch == '\r') || (skipgroup == 2 && ch == 'y'))
ch = 'N';
skipgroup = 0;
switch (ch) {
case '?':
case 'H':
case 'h':
printf("\n<RETURN> or y - read next article\n");
printf("= - reread current article\n");
printf("- - read previous article\n");
printf("g - go to article #\n");
printf("q - quit\n");
printf("e - exit without changing .rc file\n");
printf("s - save article in file\n");
printf("a - append article to file\n");
printf("c - mark all articles in group as read\n");
printf("P - go to previous newsgroup\n");
printf("N - go to next newsgroup\n");
printf("G - go to specified new group \n");
printf("L - list news groups subscribed to \n");
printf("i - list index \n");
printf("I - list index with keyword\n");
printf("X - toggle reading cross posts\n");
printf("Z - toggle reading already read groups\n");
printf("F or f - followup, [F includes text] \n");
printf("M or m - send mail, [M includes text] \n");
printf("S - Subscribe to new group\n");
printf("U - unsubscribe current group\n");
break;
case 'q':
return;
case 'X':
noxpost ^= 1;
if (noxpost)
printf("No cross posts\n");
else
printf("Read cross posts\n");
break;
case 'Z':
skipalready ^= 1;
if (skipalready)
printf("Skip already read groups\n");
else
printf("Don't skip already read groups\n");
nug++;
continue;
case 'e':
qexit(1);
case 'y':
case '\r':
strncpy(buf, cur_subject, 80);
buf[80] = 0;
do {
clearscreen();
printf("****** (%U/%U) [%s]******\n%s\n(%s) %s\n\n",
cur_article, cur_last, groups[cur_group], buf, cur_from,
cur_date);
follow_up_article = cur_article;
} while ((oldquery = showbody()) == 'a');
if (oldquery == 'q' || oldquery < 0 ||
(oldquery == '\r' && cur_article == cur_last))
oldquery = 0;
firsts[cug] = cur_article + 1;
continue;
case 's':
case 'a':
if (follow_up_article == 0xffffffff) {
printf("Not on an article\n");
} else {
save_article = cur_article;
cstat(follow_up_article);
chead();
(void) savebody(ch == 'a' ? 1 : 0);
cur_article = save_article;
cstat(cur_article);
chead();
if(firsts[cug] == cur_last + 1)skipgroup = 2;
}
break;
case 'c':
firsts[cug] = cur_last + 1;
cug++;
nug++;
continue;
case 'P':
cug--;
nug++;
continue;
case 'N':
cug++;
nug++;
continue;
case '-':
case '=':
if (follow_up_article != 0xffffffff) {
if (ch == '-') {
if (cur_first != follow_up_article)
noquery = 1;
if (follow_up_article > cur_first)
firsts[cug]
= follow_up_article - 1;
} else {
noquery = 1;
firsts[cug] = follow_up_article;
}
nug++;
continue;
}
printf("Not on an article\n");
break;
case 'g':
fflush(stdin);
fflush(stdout);
printf("Article number >");
fgets(buf, 20, stdin);
sscanf(buf, "%U", <emp);
if ((ltemp <= cur_last)) {
firsts[cug] = ltemp;
nug++;
noquery = 1;
continue;
}
printf("[article out of range]\n");
break;
case 'S':
i = getgroup(buf);
if (i == -2)
break;
if (i != -1) {
printf("Already subscribed!!\n");
} else if ((ptr = malloc(strlen(buf) + 1)) == NULL ||
ngroups >= NGROUPS - 2) {
printf("Out of memory\n");
} else {
groups[ngroups] = ptr;
ptr = buf;
while (*ptr == ' ')
ptr++;
strcpy(groups[ngroups], ptr);
firsts[ngroups] = 1;
cug = ngroups++;
cur_group = -1;
groups[ngroups] = NULL;
nug++;
continue;
}
break;
case 'U':
if (ngroups <= 2) {
printf("too few groups to delete one\n");
break;
}
groups[cur_group] = NULL;
firsts[cur_group] = 0;
compactgroups();
cug++;
nug++;
cur_group = -1;
if (cug >= ngroups)
cug = ngroups - 1;
continue;
case 'G':
i = getgroup(buf);
if (i == -2)
break;
if (i != -1) {
cug = i;
nug++;
continue;
}
printf("group not found");
break;
case 'i':
case 'I':
showindex((ch == 'I') ? 1 : 0);
if (chead())
continue;
break;
case 'L':
listgroups();
break;
case 'F':
case 'f':
case 'M':
case 'm':
if (follow_up_article == 0xffffffff) {
printf("Not on an article\n");
} else {
save_article = cur_article;
cstat(follow_up_article);
chead();
if (!getpost(ch)) {
errno = 0;
i = spawnl(P_WAIT, editorpath,
editorpath, tmpfil,
NULL);
if (i)
printf("error number from spawn = %d\n",
errno);
printf("Type y to actually %s article\n",
(ch == 'M' || ch == 'm') ? "mail" : "post");
if ((i = ngetc()) == 'y' || i == 'Y') {
/* postnews(); */
strcpy(buf, tmpdir);
if (ch == 'M' || ch == 'm')
strcat(buf, "sendmail.lst");
else
strcat(buf, "postnews.lst");
qfile = fopen(buf, "a");
if (!qfile) {
printf("failed\n");
} else {
ifile = NULL;
strcpy(buf, tmpfil);
xtime = time(NULL) & 4194303l;
do {
xtime++;
if (ifile)
fclose(ifile);
sprintf(tmpfil, "%sx%ld.nuz", tmpdir, xtime);
} while (ifile = fopen(tmpfil, "r"));
rename(buf, tmpfil);
fprintf(qfile, "%s\n", tmpfil);
fclose(qfile);
}
} else
remove(tmpfil);
}
cur_article = save_article;
cstat(cur_article);
chead();
if(firsts[cug] == cur_last + 1)skipgroup = 2;
}
break;
default:
printf("[illegal command, try ?]\n");
break;
}
}
goto query;
}
}
void
getserv(char *b, int sb)
{
char *p = b;
sb--;
while (sb > 0) {
while (!servf) {
servp = servb;
servf = tcpread(serverfd, servb, sizeof servb);
}
if (*servp == '\n') {
*b++ = 0;
servp++, servf--;
break;
} else if (*servp == '\r')
servp++, servf--;
else
*b++ = *servp++, servf--;
}
}
void
putserv(char *b)
{
tcpwrite(serverfd, b, strlen(b));
}
void
compactgroups()
{
int i;
for (i = 0; i < ngroups; i++)
if (groups[i] == NULL)
break;
if (i != ngroups - 1) {
for (i++; i < ngroups; i++) {
groups[i - 1] = groups[i];
firsts[i - 1] = firsts[i];
}
}
ngroups--;
}
void
getnewsrc(void)
{
char group[STRING];
unsigned long first;
int i;
char *ptr, *ptr2;
FILE *rec;
rec = fopen(newsrc, "r");
if (!rec) {
perror(newsrc);
exit(1);
}
i = 0;
while ((i < NGROUPS) && (fscanf(rec, "%s %U", group, &first) == 2)) {
ptr2 = group;
while (*ptr2 == ' ')
ptr2++;
ptr = malloc(strlen(ptr2) + 1);
if (!ptr) {
printf("Out of memory for groups\n");
break;
}
groups[i] = strcpy(ptr, ptr2);
firsts[i] = first;
i++;
}
ngroups = i;
}
void
dumpnewsrc(void)
{
int i;
FILE *rec;
rec = fopen(newsrc, "w");
for (i = 0; i < ngroups; i++)
if (groups[i])
fprintf(rec, "%s %U\n", groups[i], firsts[i]);
fclose(rec);
}
int
cgroup(char *s)
{
char buf[STRING];
sprintf(buf, "GROUP %s\n", s);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 411)
return -1;
else if (reply == 211) {
sscanf(buf, "%d %U %U %U %s",
&reply, &cur_numa, &cur_first, &cur_last, cur_gname);
return 0;
} else
printf("cgroup: %s\n", buf);
return -1;
}
cstat(i)
unsigned long i;
{
char buf[STRING], *p, *q;
sprintf(buf, "STAT %U\n", i);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 423)
return -1;
else if (reply == 223) {
cur_article = reparticle;
p = buf;
q = cur_articleid;
while ((p < buf + STRING - 2) && (*p != '<'))
p++;
while ((p < buf + STRING - 2) && (*p != '>'))
*q++ = *p++;
*q++ = '>';
*q++ = '\0';
return 0;
} else
printf("cstat: %s\n", buf);
return -1;
}
#if 0
int
current(void)
{
char buf[STRING], *p, *q;
sprintf(buf, "STAT\n");
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 423)
return -1;
else if (reply == 412)
return -1;
else if (reply == 223) {
cur_article = reparticle;
p = buf;
q = cur_articleid;
while ((p < buf + STRING - 2) && (*p != '<'))
p++;
while ((p < buf + STRING - 2) && (*p != '>'))
*q++ = *p++;
*q++ = '>';
*q++ = '\0';
return 0;
} else
printf("current: %s\n", buf);
return -1;
}
#endif
int
cnext(void)
{
char buf[STRING], *p, *q;
sprintf(buf, "NEXT\n");
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 421)
return -1;
else if (reply == 223) {
cur_article = reparticle;
p = buf;
q = cur_articleid;
while ((p < buf + STRING - 2) && (*p != '<'))
p++;
while ((p < buf + STRING - 2) && (*p != '>'))
*q++ = *p++;
*q++ = '>';
*q++ = '\0';
return 0;
} else
printf("cnext: %s\n", buf);
return -1;
}
int
extract(char *to, char *key, char *from)
{
if (!strncmp(from, key, strlen(key))) {
from += strlen(key);
while (*from == ' ')
from++;
strcpy(to, from);
return 1;
} else
return 0;
}
chead()
{
char buf[STRING];
*cur_path = 0;
*cur_from = 0;
*cur_replyto = 0;
*cur_subject = 0;
*cur_newsgroups = 0;
*cur_message_ID = 0;
*cur_references = 0;
*cur_date = 0;
sprintf(buf, "HEAD %U\n", cur_article);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 423)
return -1;
else if (reply == 221)
while (1) {
getserv(buf, sizeof buf);
if (!strcmp(buf, ".")) {
if (!*cur_replyto)
strcpy(cur_replyto, cur_from);
return 0;
}
extract(cur_path, "Path:", buf) ||
extract(cur_from, "From:", buf) ||
extract(cur_subject, "Subject:", buf) ||
extract(cur_replyto, "Reply-To:", buf) ||
extract(cur_newsgroups, "Newsgroups:", buf) ||
extract(cur_message_ID, "Message-ID:", buf) ||
extract(cur_references, "References:", buf) ||
extract(cur_date, "Date:", buf);
} else
printf("chead: %s\n", buf);
return -1;
}
int
showbody(void)
{
char buf[STRING];
int line = 0;
int ch;
sprintf(buf, "BODY %U\n", cur_article);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 423)
return -1;
else if (reply == 222)
while (1) {
if (line == 18) {
reversevideo("more(<SPACE> to continue)?");
fflush(stdout);
ch = ngetc();
if (ch != ' ') {
while (getserv(buf, sizeof buf), strcmp(buf, "."));
normalvideo();
return ch;
}
backline();
line = 0;
}
getserv(buf, sizeof buf);
if (strcmp(buf, ".")) {
/* printf("%s", buf); */
fputs(buf,stdout);
if (strlen(buf) != 80)
printf("\n");
} else {
reversevideo(" End of article ");
printf("\n");
normalvideo();
return 0;
}
line++;
} else
printf("showbody: %d %s\n", reply, buf);
return -1;
}
int
savebody(int type)
{
char buf[STRING];
FILE *f;
char sss[72];
char *s, *ss;
s = &sss[0];
fflush(stdin);
fflush(stdout);
printf("Filename >");
fgets(s, 70, stdin);
sss[71] = '\n';
while (*s == ' ')
s++;
ss = s;
while (*ss != '\n')
ss++;
*ss = 0;
if (!(f = fopen(s, type ? "a" : "w"))) {
perror(s);
return -1;
}
sprintf(buf, "BODY %U\n", cur_article);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 423)
goto badsave;
else if (reply == 222) {
fprintf(f, "Subject: %s\n", cur_subject);
fprintf(f, "From: %s\n", cur_from);
fprintf(f, "Path: %s\n", cur_path);
fprintf(f, "Reply-To: %s\n", cur_replyto);
fprintf(f, "Newsgroups: %s\n", cur_newsgroups);
fprintf(f, "Message-ID: %s\n", cur_message_ID);
fprintf(f, "References: %s\n", cur_references);
fprintf(f, "Date: %s\n", cur_date);
fprintf(f, "\n");
while (1) {
getserv(buf, sizeof buf);
if (strcmp(buf, "."))
fprintf(f, "%s\n", buf);
else
break;
}
fclose(f);
return 0;
} else
printf("savebody: %d %s\n", reply, buf);
badsave:
fclose(f);
return -1;
}
int
saveactive(char *s)
{
char buf[256];
FILE *f;
if (!(f = fopen(s, "w"))) {
perror(s);
return -1;
}
sprintf(buf, "LIST\n");
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 215) {
while (1) {
char group[256];
unsigned long to, from;
char act;
getserv(buf, sizeof buf);
if (!strcmp(buf, "."))
break;
sscanf(buf, "%s %U %U %c", group, &to, &from, &act);
fprintf(f, "%s %U\n", group, to);
}
fclose(f);
return 0;
} else
printf("saveactive: %d %s\n", reply, buf);
fclose(f);
return -1;
}
int
netsocket(void)
{
int fd;
if ((fd = tcpopen(serverhost, 119)) < 0) {
fprintf(stderr, "tcpopen failed\n");
exit(9);
}
return (fd);
}
int
getgroup(char *buf)
{
char *s, *ss;
int i;
fflush(stdin);
fflush(stdout);
printf("New group >");
fgets(buf, 70, stdin);
if (*buf == 0 || *buf == '\n')
return -2;
s = &buf[0];
buf[71] = '\n';
while (*s == ' ')
s++;
ss = s;
while (*ss != '\n')
ss++;
*ss = 0;
for (i = 0; i < ngroups; i++) {
if (!strcmp(s, groups[i]))
return i;
}
return -1;
}
void
listgroups(void)
{
int line = 0;
int ch, i;
printf("\n\n");
for (i = 0; i < ngroups; i++) {
if (line == 18) {
reversevideo("more(<RETURN> or <SPACE> to continue, q or . to quit)?");
fflush(stdout);
ch = ngetc();
if (ch == 'q' || ch == '.') {
normalvideo();
return;
}
backline();
line = 0;
}
printf(" %s %U\n", groups[i], firsts[i]);
line++;
}
}
int
showindex(int flag)
{
char buf[80], test_string[80], test_string2[150];
int line = 0;
int ch, i, j;
unsigned long save_article;
if (flag) {
printf("Enter matching string: ");
fgets(test_string, 78, stdin);
for (i = 0; test_string[i] != 0; i++) {
if (test_string[i] == '\n')
test_string[i] = 0;
if (test_string[i] >= 'a' && test_string[i] <= 'z')
test_string[i] -= 'a' - 'A';
}
}
save_article = cur_article;
if (cur_article < cur_first)
cur_article = cur_first;
printf("\n\n");
for (; cur_article <= cur_last; cur_article++) {
if (line == 18) {
reversevideo("more(<RETURN> or <SPACE> to continue, q or . to quit)?");
fflush(stdout);
ch = ngetc();
if (ch == 'q' || ch == '.') {
cur_article = save_article;
normalvideo();
return 0;
}
backline();
line = 0;
}
if (chead())
continue;
strncpy(buf, cur_subject, 70);
buf[70] = 0;
if (flag) {
strcpy(test_string2, buf);
strncat(test_string2, cur_from, 70);
for (j = 0; j < 145 && test_string2[j] != 0; j++) {
if (test_string2[j] >= 'a' && test_string2[j] <= 'z')
test_string2[j] -= 'a' - 'A';
}
}
test_string2[j] = 0;
if (!flag || strstr(test_string2, test_string)) {
printf("%U%c %s\n",
cur_article, checkx() ? '*' : ' ', buf);
fflush(stdout);
line++;
}
}
cur_article = save_article;
return 0;
}
int
getpost(int f)
{
char buf[STRING];
FILE *ifile = NULL;
sprintf(tmpfil, "%stmp.nuz", tmpdir);
ifile = fopen(tmpfil, "w");
if (!ifile) {
printf("Can't open temporary file \n");
return 1;
}
fprintf(ifile, "From: %s\n", fromline);
if (f == 'm' || f == 'M') {
fprintf(ifile, "To: %s\n", (cur_replyto != NULL) ?
cur_replyto : cur_from);
}
if (!strncmp(cur_subject, "Re:", 3))
fprintf(ifile, "Subject: %s\n", cur_subject);
else
fprintf(ifile, "Subject: Re: %s\n", cur_subject);
if (f == 'f' || f == 'F') {
fprintf(ifile, "Newsgroups: %s\n", cur_newsgroups);
fprintf(ifile, "Summary: \nFollowup-To: \nDistribution: \n");
/* fprintf(ifile, "Date: %s\n", cur_date); */
fprintf(ifile, "References: %s", cur_message_ID);
if (cur_references)
fprintf(ifile, " %s", cur_references);
fprintf(ifile, "\n");
}
fprintf(ifile, "\n\n");
if (f == 'F' || f == 'M') {
fprintf(ifile, "In article %s %s writes:\n", cur_message_ID, cur_from);
sprintf(buf, "BODY %U\n", cur_article);
putserv(buf);
getserv(buf, sizeof buf);
sscanf(buf, "%d %U", &reply, &reparticle);
if (reply == 222) {
while (1) {
getserv(buf, sizeof buf);
if (strcmp(buf, ".")) {
fprintf(ifile, ">%s\n", buf);
} else
break;
}
} else {
printf("savebody error: %d %s\n", reply, buf);
fclose(ifile);
return 1;
}
}
fclose(ifile);
return 0;
}
int
postnews(void)
{
char buf[STRING], s[STRING], fbuf[128];
int seen_fromline, in_header, seen_header;
FILE *ifile, *pfile;
char *cp, *bp;
int count, i;
strcpy(fbuf, tmpdir);
strcat(fbuf, "postnews.lst");
pfile = fopen(fbuf, "r");
if (!pfile) {
printf("No News to post\n");
return 1;
} else
printf("Now trying to post your News\n");
while (1) {
if (fgets(fbuf, 126, pfile) == NULL)
break;
for (i = 0; fbuf[i]; i++)
if (fbuf[i] == '\n')
fbuf[i] = 0;
ifile = fopen(fbuf, "r");
if (!ifile) {
printf("Can't open temporary file %s\n", fbuf);
continue;
}
putserv("POST\n");
getserv(buf, sizeof buf);
if (*buf != '3') {
if (atoi(buf) == 440) {
printf("No posting!\n");
} else {
printf("Remote error: %s\n", buf);
}
fclose(pfile);
fclose(ifile);
return 0;
}
printf("Sending file\n");
in_header = 1;
seen_header = 0;
seen_fromline = 0;
count = 0;
bp = buf;
while (fgets(s, 510, ifile) != NULL) {
s[511] = '\n';
cp = s;
while (*cp != '\n')
cp++;
*cp = 0;
if (s[0] == '.') { /* Single . is eof, so put in extra one */
*bp++ = '.';
if (++count == 512) {
tcpwrite(serverfd, buf, 512);
usleep();
/*
* Note on all these 'usleep' calls: Without them this
* program crashes our Proteon fiber-optic network
* gateway. It is known that this gateway has software
* problems. They promise to fix it 'real soon now'. But
* on the other hand no other computer crashes is, nor
* does NCSA Telnet or NCSA FTP used on my very own PC.
* So this appears to be a terrible kludge.
*/
count = 0;
bp = buf;
}
}
if (in_header && !strnicmp(s, "From:", sizeof("From:") - 1)) {
seen_header = 1;
seen_fromline = 1;
}
if (in_header && s[0] == '\0') {
if (seen_header) {
in_header = 0;
if (!seen_fromline) {
strcpy(s, "From: ");
strcpy(s, fromline);
strcat(s, "\r\n");
}
} else {
continue;
}
} else if (in_header) {
if (valid_header(s))
seen_header = 1;
else
continue;
}
cp = s;
while (*cp) {
*bp++ = *cp++;
if (++count == 512) {
tcpwrite(serverfd, buf, 512);
usleep();
count = 0;
bp = buf;
}
}
cp = "\r\n";
while (*cp) {
*bp++ = *cp++;
if (++count == 512) {
tcpwrite(serverfd, buf, 512);
usleep();
count = 0;
bp = buf;
}
}
}
fclose(ifile);
cp = ".\r\n";
while (*cp) {
*bp++ = *cp++;
if (++count == 512) {
tcpwrite(serverfd, buf, 512);
usleep();
count = 0;
bp = buf;
}
}
if (count) {
tcpwrite(serverfd, buf, count);
usleep();
}
printf("waiting for reply\n");
(void) getserv(buf, sizeof(buf));
printf("got reply\n");
if (*buf != '2') {
if (atoi(buf) == 441) {
printf("Article not accepted by server; not post*ed.\n");
for (cp = buf + 4; *cp && *cp != '\r'; cp++)
if (*cp == '\\')
putchar('\n');
else
putchar(*cp);
fclose(pfile);
return 0;
} else {
printf("Remote error: %s\n", buf);
fclose(pfile);
return 0;
}
}
remove(fbuf);
}
strcpy(fbuf, tmpdir);
strcat(fbuf, "postnews.lst");
remove(fbuf);
return 0;
}
int
valid_header(char *h)
{
char *colon, *space;
/*
* blank or tab in first position implies this is a continuation header
*/
if (h[0] == ' ' || h[0] == '\t')
return (1);
/*
* just check for initial letter, colon, and space to make sure we
* discard only invalid headers
*/
colon = strchr(h, ':');
space = strchr(h, ' ');
if (isalpha(h[0]) && colon && space == colon + 1)
return (1);
/*
* anything else is a bad header -- it should be ignored
*/
return (0);
}
void
qexit(int n)
{
char buf[512];
if (n >= 10)
printf("Horrible error: read manual \n");
fflush(stdout);
putserv("QUIT\n");
getserv(buf, sizeof buf);
if (*buf != '2')
printf("Tried to quit, but failed\n");
if (n)
exit(n);
}
int
checkx(void)
{
char buf[256];
int i, k;
char *ptr, *ptr2, *ptr3;
if (cur_group == 0)
return 0;
ptr = cur_newsgroups;
while (*ptr == ' ')
ptr++;
k = 0;
while (1) {
if (*ptr == 0)
break;
if (*ptr == ',')
ptr++;
while (*ptr == ' ')
ptr++;
ptr2 = ptr;
ptr3 = buf;
while (*ptr2 != 0 && *ptr2 != ',')
*ptr3++ = *ptr2++;
*ptr3 = 0;
while (*(--ptr3) == ' ')
*ptr3 = 0;
ptr = ptr2;
for (i = 0; i < cur_group; i++) {
if (strcmp(buf, groups[i]) == 0)
return 1;
}
}
return 0;
}
void
sendmail()
{
char buf[128];
FILE *mfile;
int i;
strcpy(buf, tmpdir);
strcat(buf, "sendmail.lst");
mfile = fopen(buf, "r");
fclose(mfile);
if (mfile != NULL) {
printf("Sending mail\n");
for (i = 0; i < 10; i++)
usleep();
spawnl(P_OVERLAY, smtppath, smtppath, buf, serverhost, NULL);
/* this does not normally return, but might if some spawn error */
} else {
printf("No mail to process\n");
for (i = 0; i < 4; i++)
usleep();
}
xabort(); /* don't do onexit processing, we already did it */
}