home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Beijing Paradise BBS Backup
/
PARADISE.ISO
/
software
/
BBSDOORW
/
SNWS191S.ZIP
/
ARTICLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-07
|
32KB
|
1,157 lines
/*
SNEWS 1.91
article - routines to read and display an article
Copyright (C) 1991 John McCombs, Christchurch, NEW ZEALAND
john@ahuriri.gen.nz
PO Box 2708, Christchurch, NEW ZEALAND
Modifications copyright (C) 1993 Daniel Fandrich
<dan@fch.wimsey.bc.ca> or CompuServe 72365,306
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 1, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the file COPYING, which contains a copy of the GNU General
Public License.
Source is formatted with a tab size of 4.
*/
#include "defs.h"
#include "snews.h"
#include "pccharst.h"
#include <alloc.h>
#include <dir.h>
#include <io.h>
#include <ctype.h>
enum char_sets current_char_set = DEFAULT_CHAR_SET;
int active_code_page;
static char *empty_line = "\n"; /* static empty line structure */
void ReplyAddress(TEXT *tx, char *subject);
/*-------------------- set up the global code page vars --------------------*/
void select_code_page(void)
{
code_page_table = select_cp_table(active_code_page = get_code_page());
}
/*------------------------- read in an article -----------------------------*/
TEXT *load_article(char *fnx, long offset)
{
/*
* Open the file and read it. Save the author and organisation
* fill in the structures
*/
FILE *tmp_file;
char buf[256], lnbuf[256], *p, *s, *token;
TEXT *tx;
LINE *ln, *lz;
int ct, i;
tx = NULL;
ct = 0;
current_char_set = DEFAULT_CHAR_SET;
if ((tmp_file = flockopen(fnx, "rb")) != NULL) {
fseek(tmp_file, offset, SEEK_SET);
tx = xmalloc(sizeof(TEXT));
tx->top = NULL;
tx->start = NULL;
strcpy(tx->follow_up, "");
strcpy(tx->author, " ** none ** ");
strcpy(tx->organisation, " ** none ** ");
while (fgets(buf, sizeof(buf)-1, tmp_file) != NULL) {
if (strncmp(buf, "@@@@END", 7) == 0) break;
expand_tabs(buf, sizeof(buf)-1);
/*
* We now have a line of input. If the line is too long
* it is wrapped at spaces or '!'. The lines of text are
* stored in LINE structures
*/
p = &buf[0];
while (strlen(p) > 0) {
strcpy(lnbuf, p);
if (strlen(p) <= 80) {
strcpy(lnbuf, p);
*p = '\x00'; /* signal we're ready for a new line */
} else {
/* can we split the line at a nice spot (space , !) ? */
p += 79;
for (i = 79; i > 50; i--) {
if ((lnbuf[i] == ' ') || (lnbuf[i] == '!') ||
(lnbuf[i] == ','))
break;
p--;
}
/* can't split nicely -- split at the end of the line */
if (i <= 50) {
p += (79-i);
i = 79;
}
lnbuf[i] = '\x00';
}
/* is it the first line - if so int the TEXT structure */
if (ct == 0) {
ln = xmalloc(sizeof(LINE));
ln->last = NULL;
tx->top = ln;
} else {
lz = ln;
ln->next = xmalloc(sizeof(LINE));
ln = ln->next;
ln->last = lz;
}
ln->index = ct;
if (lnbuf[0] == '\n') /* is the line empty? */
ln->data = empty_line; /* yes, save malloc() overhead */
else {
ln->data = xmalloc(strlen(lnbuf)+1);
strcpy(ln->data, lnbuf);
}
/* Find first line of body */
if ((strlen(lnbuf) == 1) && (tx->start == NULL))
tx->start = ln;
ct++;
/* save the header info */
if ((tx->start == NULL) && (strnicmp("From:", lnbuf, 5) == 0)) {
s = lnbuf + 5;
while (*s && isspace(*s)) s++;
*(s + WHO_LENGTH - 1) = '\0';
strtok(strcpy(tx->author, s), "\n");
}
if ((tx->start == NULL) && ((strnicmp("Organisation:", lnbuf, 13) == 0) || (strncmp("Organization:", lnbuf, 13) == 0))) {
s = lnbuf + 13;
while (*s && isspace(*s)) s++;
*(s + ORG_LENGTH - 1) = '\0';
strtok(strcpy(tx->organisation, s), "\n");
}
if ((tx->start == NULL) && (strnicmp("Followup-To:", lnbuf, 12) == 0)) {
s = lnbuf + 12;
while (*s && isspace(*s)) s++;
*(s + sizeof(tx->follow_up) - 1) = '\0';
strtok(strcpy(tx->follow_up, s), "\n");
}
if ((tx->start == NULL) && (strnicmp("Content-Type:", lnbuf, 13) == 0)) {
s = lnbuf + 13;
while (*s && isspace(*s)) s++; /* kill leading spaces */
token = strtok(s, " ;\n");
while (token != NULL) {
if (strnicmp("charset=", token, 8) == 0) {
current_char_set = select_char_set(token+8);
break;
}
token = strtok(NULL, " ;\n");
}
}
}
}
ln->next = NULL;
tx->lines = ct;
fclose(tmp_file);
}
return(tx);
}
/*---------------------- deallocate article memory ------------------------*/
void free_article(TEXT *t)
{
LINE *l, *k;
l = t->top;
while (l != NULL) {
k = l;
l = l->next;
if (k->data != empty_line) /* don't free empty line pointer */
free(k->data);
free(k);
}
free(t);
}
/*---------------------------- read an article ----------------------------*/
enum exit_codes read_article(ACTIVE *gp, TEXT *tx, char *subject, int a_ct, int of_ct)
{
/*
* This routine allows the user to read an article
*/
LINE *this, *tmp; /* current thread */
enum exit_codes exit_code; /* why we are exiting the loop */
char sub_tmp[80]; /* new subject line */
int i, maxx;
this = tx->start;
if (this->next != NULL)
this = this->next; /* skip over blank line */
show_article(gp, tx, subject, this, a_ct, of_ct);
exit_code = EX_CONT;
while ((exit_code == EX_CONT) || (exit_code == EX_DUMMY)) {
exit_code = EX_CONT;
gotoxy(1,25);
switch (get_any_key()) {
case Fn1 :
case '?' :
case 'h' :
show_help(HELP_ARTICLES);
break;
case Fn2 :
show_values();
break;
case Fn3 :
if (current_char_set++ == US_ASCII)
current_char_set = 0;
break;
case Fn4 :
pipe_article(tx, my_stuff.hotpipe);
message("-- Done --");
break;
case UP_ARR :
if (this->last != NULL) {
this = this->last;
gotoxy(1,TEXT_LINE+PAGE_LENGTH-1);
delline();
gotoxy(1,TEXT_LINE);
insline();
clreol();
cputs(translate_line(this->data, current_char_set));
show_percent((int) ((100L * (this==NULL ? tx->lines+1 : min((this->index) + PAGE_LENGTH, tx->lines+1))) / ((tx->lines) + 1)));
}
exit_code = EX_DUMMY;
break;
case DN_ARR :
if (this->next != NULL &&
(this->index + PAGE_LENGTH < tx->lines ||
this->index <= tx->start->index)) {
this = this->next;
gotoxy(1,TEXT_LINE);
delline();
gotoxy(1,TEXT_LINE+PAGE_LENGTH-1);
insline();
tmp = this;
for (i = 0; i < PAGE_LENGTH-1; i++) {
tmp = tmp->next;
if (tmp == NULL) break;
}
if (tmp)
cputs(translate_line(tmp->data, current_char_set));
show_percent((int) ((100L * (tmp==NULL ? tx->lines+1 : tmp->index)) / ((tx->lines) + 1)));
}
exit_code = EX_DUMMY;
break;
case 'b' :
case PGUP :
for (i = 0; i < PAGE_LENGTH-1; i++) {
if (this->last == NULL) break;
this = this->last;
}
break;
case ' ' :
case PGDN :
if ( this->next == NULL )
exit_code = EX_DUMMY;
else {
#ifndef ALTPAGING /* maintain reading place paging method */
maxx = 0;
if ((tx->lines - (this->index + PAGE_LENGTH)) > 0)
maxx = PAGE_LENGTH - 1;
#else /* don't show past end of article paging method */
maxx = tx->lines - (this->index + PAGE_LENGTH);
maxx = min(maxx, PAGE_LENGTH - 1);
maxx = max(maxx, tx->start->index + 1 - this->index);
#endif
if ( maxx <= 0 )
exit_code = EX_DUMMY;
else
for (i = 0; i < maxx; i++) {
if (this->next == NULL) break;
this = this->next;
}
}
break;
case 'R'-0x40 :
case HOME :
tmp = this;
this = tx->start;
if (this->next != NULL)
this = this->next; /* skip over blank line */
if (this == tmp)
exit_code = EX_DUMMY;
break;
case END :
tmp = this;
this = tx->start;
while (this->next != NULL)
this = this->next;
for (i = 0; i < PAGE_LENGTH-1; i++) {
if (this->last == NULL) break;
if (tx->start->next && this == tx->start->next)
break;
this = this->last;
}
if (this == tmp)
exit_code = EX_DUMMY;
break;
case '[' :
case '-' :
case LEFT :
exit_code = EX_PREVIOUS;
break;
case ']' :
case RIGHT :
exit_code = EX_NEXT;
break;
case cLEFT :
exit_code = EX_PREVIOUS10;
break;
case cRIGHT :
exit_code = EX_NEXT10;
break;
case 'v' :
tmp = this;
this = tx->top;
if (this == tmp)
exit_code = EX_DUMMY;
break;
case '/' :
this = search_text(this);
break;
case 'p' :
strcpy(sub_tmp, "");
post(NULL, gp->group, sub_tmp);
break;
case 'f' :
if (strnicmp(subject, "Re:", 3) != 0) {
strcpy(sub_tmp, "Re: ");
strcat(sub_tmp, subject);
} else
strcpy(sub_tmp, subject);
if (strlen(tx->follow_up) == 0) {
post(tx, gp->group, sub_tmp);
} else if (stricmp(tx->follow_up, "poster") == 0) {
reply_to_article(tx, sub_tmp);
} else
post(tx, tx->follow_up, sub_tmp);
break;
case 'r' :
if (strnicmp(subject, "Re:", 3) != 0) {
strcpy(sub_tmp, "Re: ");
strcat(sub_tmp, subject);
} else
strcpy(sub_tmp, subject);
reply_to_article(tx, sub_tmp);
break;
case 'R' :
if (strnicmp(subject, "Re:", 3) != 0) {
strcpy(sub_tmp, "Re: ");
strcat(sub_tmp, subject);
} else
strcpy(sub_tmp, subject);
ReplyAddress(tx, sub_tmp);
break;
case 'm' :
mail_to_someone(tx);
break;
case 's' :
save_to_disk(tx, NULL, FALSE);
message("-- Done --");
break;
case 'w' :
save_to_disk(tx, my_stuff.extract_file, TRUE);
message("-- Done --");
break;
case '|' :
pipe_article(tx, NULL);
message("-- Done --");
break;
case 'x' :
case 'X' :
rot13(tx);
break;
case 'X'-0x40 :
this = tx->start;
if (this->next != NULL)
this = this->next; /* skip over blank line */
rot13(tx);
break;
case '!' :
textbackground(BLACK); textcolor(LIGHTGRAY);
cprintf("\r\n");
spawnl(P_WAIT, getenv("COMSPEC"), getenv("COMSPEC"), NULL);
break;
case TAB :
exit_code = EX_NEXT_UNREAD;
break;
case ENTER :
exit_code = EX_NEXT;
break;
case '=' :
case ESCAPE :
exit_code = EX_QUIT;
break;
default :
exit_code = EX_DUMMY;
break;
}
if (exit_code == EX_CONT)
show_article(gp, tx, subject, this, a_ct, of_ct);
}
return(exit_code);
}
/*--------------------- display a page of an article ------------------------*/
void show_article(ACTIVE *gp, TEXT *tx, char *subject, LINE *this, int a_ct,
int of_ct)
{
/*
* This routine show a page of an article
*/
int i;
char buf[63];
strcpy(buf, subject);
buf[59] = '\x00';
textbackground(textb); textcolor(textf);
clrscr();
textbackground(headb); textcolor(headf);
clreol();
cprintf("Group: %-53s Article:%3d of %3d\r\n",
gp->group, a_ct, of_ct);
clreol();
cprintf("Subject: %-59s %4d lines\r\n",
translate_header(buf, current_char_set), tx->lines);
clreol();
/* cprintf("From: %s; %s", translate_header(tx->author, current_char_set),
translate_header(tx->organisation, current_char_set));*/
cprintf("From: %s", translate_header(tx->author, current_char_set));
command("ESC=select thread TAB=next unread ENTER=next F1=help");
textbackground(textb); textcolor(textf);
gotoxy(1, TEXT_LINE);
for (i = 0; i < PAGE_LENGTH; i++) {
gotoxy(1, i+TEXT_LINE);
cputs(translate_line(this->data, current_char_set));
this = this->next;
if (this == NULL) break;
}
show_percent((int) ((100L * (this==NULL ? tx->lines+1 : this->index)) / ((tx->lines) + 1)));
}
/*-------------------- search for text in article body -------------------*/
LINE *search_text(LINE *this)
{
char search_text[80];
static char last_text[80] = {'\0'};
message("Search for? ");
if (*gets(search_text))
strcpy(last_text, search_text);
else
strcpy(search_text, last_text);
#ifdef AMATCH
strlwr(search_text); /* lower case string for case insensitive search */
#endif
if (search_text[0])
while (this->next) {
this = this->next;
#ifdef AMATCH
if (amatch(search_text, strlwr(translate_line(this->data, current_char_set))))
#else
if (stristr(translate_line(this->data, current_char_set), search_text))
#endif
break;
}
message("");
return this;
}
/*-------------------- show percentage through article -------------------*/
void show_percent(int percent)
{
/*
* This routine displays how far through an article we are
*/
gotoxy(2,25);
textbackground(msgb); textcolor(msgf);
cprintf("%d%% ", percent);
textbackground(textb); textcolor(textf);
}
/*-------------------------- save article --------------------------------*/
int save_to_disk(TEXT *tx, char *save_name, int mailbox)
{
/*
* This routine saves an article to disk, appending if necessary
* If save_name is NULL, user is asked for a name
* If save_name is not NULL, article is saved to the save_name file
* If mailbox is nonzero, article is saved in mailbox format
* Returns 0 if no error, 1 if error
* (one anomaly -- if user elects not to append, 1 is returned)
*/
FILE *tmp = NULL;
LINE *ln;
char fn[80];
int ch;
if (save_name == NULL) { /* save function */
lmessage("Filename? ");
gets(fn);
} else /* extract function */
strcpy(fn, save_name);
if (!*fn) /* abort if no file name given */
return 0;
expand_filename(fn); /* expand ~/ in file name */
if (access(fn, 0) == 0) { /* file exists -- should we append? */
if (save_name) {
if ((tmp = fopen(fn, "at")) == NULL) {
message("*** Cannot open file for appending - "
"press any key to continue ***");
get_any_key();
}
} else {
message("File exists - append (y/n)? ");
while (((ch = tolower(getch())) != 'y') && (ch != 'n'));
if (ch == 'y') {
if ((tmp = fopen(fn, "at")) == NULL) {
message("*** Cannot open file for appending - "
"press any key to continue ***");
get_any_key();
}
}
}
} else { /* file doesn't exist -- try to create it */
/* make sure the file name given doesn't have bad characters */
if ((strcspn(fn, " \"*+,;<=>?[]|\x7f\xe5") != strlen(fn)) ||
((tmp = fopen(fn, "wt")) == NULL)) {
message("*** Cannot open file for output - press any key to continue ***");
get_any_key();
}
}
if (tmp != NULL) {
if (mailbox) {
fputs("\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\n",tmp);
}
/* save article contents to disk */
/* \n are stored in the ln->data structures so we don't need to
write any others out */
ln = tx->top;
while (ln != NULL) {
fputs(ln->data, tmp);
ln = ln->next;
}
fclose(tmp);
}
return (tmp == NULL);
}
/*------------------- pipe article through a program ---------------------*/
void pipe_article(TEXT *tx, char *prog_name)
{
/*
* This routine saves an article to a temporary file.
* If prog_name is NULL, user is asked for a program name and the article
* is piped through that program.
* If prog_name is not NULL, article is piped through that program.
*/
char prog[129], cmd[129], temp[81];
char *pipe;
if (prog_name == NULL) { /* save function */
lmessage("Pipe article through which program? ");
gets(prog);
} else /* extract function */
strcpy(prog, prog_name);
if (!*prog) /* abort if no program given */
return;
if (strchr(prog, '<')) {
message("*** Cannot redirect input - press any key to continue ***");
get_any_key();
} else {
sprintf(temp, "%spipe%04x.tmp", my_stuff.temp_str, getpid());
strcpy(cmd, prog);
/* if command contains %s, put file name there */
if (strstr(cmd, "%s") != NULL) {
sprintf(cmd, prog, temp);
/* look for a second pipe in command and put the redirect in the right spot */
} else if ((pipe = strchr(cmd, '|')) != NULL) {
strcat(strcat(strcat(strcpy(pipe, " <"), temp), " "), strchr(prog, '|'));
/* append file redirect to end of command */
} else
strcat(strcat(cmd, " <"), temp);
if (!save_to_disk(tx, temp, FALSE)) { /* save article to temporary file */
clrscr();
system(cmd);
unlink(temp);
printf("\n\n");
message("-- Press any key to continue --");
get_any_key();
}
}
}
/*------------------- expand an alias to the email address ------------------*/
char *expand_alias(char *author)
{
char buf[256];
FILE *aliasfile;
char *s;
/*
* Given a possible alias in author, search the alias file for a match
* and return the full email address back in author.
*/
if (*my_stuff.alias_file && (aliasfile = fopen(my_stuff.alias_file,"rt")) != NULL) {
while (fgets(buf, sizeof(buf)-1, aliasfile) != NULL) {
/* ignore comment line */
if (buf[0] == ';' || buf[0] == '#' || isspace(buf[0]))
continue;
/* find matching alias */
if (strnicmp(author, buf, strlen(author)) == 0) {
/* skip over alias */
s = strpbrk(buf," \t");
while (*++s && isspace(*s))
;
/* skip over name in quotes, if any */
if (*s == '\"') {
++s;
while (*s && (*s != '\"')) ++s;
++s;
while (*s && (isspace(*s) || (*s == '<'))) ++s;
}
/* copy full name into the pointer given for the alias */
if ((s = strtok(s, " >;\t\r\n")) != NULL)
strcpy(author,s);
break;
}
} /* while */
fclose(aliasfile);
} /* if */
return author;
}
/*-------------------------- reply to article ---------------------------*/
void reply_to_article(TEXT *tx, char *subject)
{
/*
* Mail reply to article
*/
#ifdef INCLUDE_SIG
FILE *sig;
char sig_fn[80];
#endif
FILE *tmp;
LINE *ln;
int ch;
char fn[81];
char buf[256];
char author[WHO_LENGTH], msg_id[MSG_ID_LENGTH];
sprintf(fn, "%srply%04x.tmp", my_stuff.temp_str, getpid());
if ((tmp= fopen(fn, "wt")) != NULL) {
strcpy(author, " ");
get_his_stuff(tx, author, msg_id);
/* add the quoted message */
message("Quote article (y/n)? ");
while (((ch = tolower(getch())) != 'y') && (ch != 'n'));
if (ch == 'y') {
fprintf(tmp, "In article %s you write:\n", msg_id);
ln = tx->start;
while (ln != NULL) {
fprintf(tmp, ">%s", ln->data);
ln = ln->next;
}
}
#ifdef INCLUDE_SIG
/* append the signature if there is one */
strcpy(sig_fn, my_stuff.home);
strcat(sig_fn, my_stuff.signature);
if ((sig= fopen(sig_fn, "rt")) != NULL) {
fprintf(tmp, "\n--\n");
while (fgets(buf, 79, sig) != NULL)
fputs(buf, tmp);
fclose(sig);
}
#endif
fclose(tmp);
ch = 'e';
/* NEW BIT includes send/abort/edit */
while ((ch != 's') && (ch != 'a')) {
if (ch == 'e') {
sprintf(buf, my_stuff.editor, fn);
system(buf);
}
clrscr();
gotoxy(1,23);
cprintf(" Mail reply addressed to: %s",author);
sprintf(buf,"Mail reply: (S)end, (A)bort, or (E)dit again? (S/A/E):");
message(buf);
while (((ch = tolower(getch())) != 's') && (ch != 'a') && (ch != 'e'));
gotoxy(1,24);
}
if (ch == 's') {
sprintf(buf, "mail -s \"%s\" %s <%s", subject, author, fn);
system(buf);
}
unlink(fn);
message("-- Press any key to continue --");
get_any_key();
} else {
message("*** Cannot open temp file - press any key to continue ***");
get_any_key();
}
}
/* ---------- (R)eply allowing specified address or alias ---------------- */
void ReplyAddress(TEXT *tx, char *subject)
{
#ifdef INCLUDE_SIG
FILE *sig;
char sig_fn[80];
#endif
FILE *tmp;
LINE *ln;
int ch;
char fn[81];
char buf[256];
char author[WHO_LENGTH], msg_id[MSG_ID_LENGTH];
sprintf(fn, "%srply%04x.tmp", my_stuff.temp_str, getpid());
if ((tmp= fopen(fn, "wt")) != NULL) {
get_his_stuff(tx, author, msg_id);
/* add the quoted message */
message("Quote article (y/n)? ");
while (((ch = tolower(getch())) != 'y') && (ch != 'n'));
if (ch == 'y') {
fprintf(tmp, "In article %s you write:\n", msg_id);
ln = tx->start;
while (ln != NULL) {
fprintf(tmp, ">%s", ln->data);
ln = ln->next;
}
}
#ifdef INCLUDE_SIG
/* append the signature if there is one */
strcpy(sig_fn, my_stuff.home);
strcat(sig_fn, my_stuff.signature);
if ((sig= fopen(sig_fn, "rt")) != NULL) {
fprintf(tmp, "\n--\n");
while (fgets(buf, 79, sig) != NULL)
fputs(buf, tmp);
fclose(sig);
}
#endif
fclose(tmp);
lmessage("Send reply to whom (aliases allowed)? ");
gets(author);
if (*author) {
expand_alias(author);
ch = 'e';
while ((ch != 's') && (ch != 'a')) {
if (ch == 'e') {
sprintf(buf, my_stuff.editor, fn);
system(buf);
}
sprintf(buf,"Mail article: (S)end, (A)bort, or (E)dit again? (S/A/E):");
message(buf);
while (((ch = tolower(getch())) != 's') && (ch != 'a') && (ch != 'e'));
gotoxy(1,24);
}
if (ch == 's') {
sprintf(buf, "mail -s \"%s\" %s <%s", subject, author, fn);
system(buf);
}
unlink(fn);
message("-- Press any key to continue --");
get_any_key();
} else {
unlink(fn);
}
} else {
message("*** Cannot open temp file - press any key to continue ***");
get_any_key();
}
}
/*-------------------------- reply to article ---------------------------*/
void mail_to_someone(TEXT *tx)
{
/*
* Mail this article to someone
*/
FILE *tmp;
LINE *ln;
int ch;
char fn[MAXPATH+1];
char buf[256], who[80];
lmessage("Mail this article to (aliases allowed)? ");
gets(who);
if (*who) {
sprintf(fn, "%srply%04x.tmp", my_stuff.temp_str, getpid());
if ((tmp= fopen(fn, "wt")) != NULL) {
expand_alias(who);
fprintf(tmp, "Resent-From: %s@%s (%s)\n",
my_stuff.user, my_stuff.my_domain, my_stuff.my_name);
fprintf(tmp, "Resent-To: %s\n", who);
ln = tx->top;
while (ln != NULL) {
fputs(ln->data, tmp);
ln = ln->next;
}
fclose(tmp);
message("Edit outgoing message (y/n)? ");
while (((ch = tolower(getch())) != 'y') && (ch != 'n'));
if (ch == 'y') {
sprintf(buf, my_stuff.editor, fn);
system(buf);
}
sprintf(buf, "Mail article to %s (y/n)? ", who);
message(buf);
while (((ch = tolower(getch())) != 'y') && (ch != 'n'));
if (ch == 'y') {
sprintf(buf, "rmail -t <%s", fn);
system(buf);
}
unlink(fn);
} else {
message("*** cannot open temp file - press any key ***");
get_any_key();
}
}
}
/*----------------------- find email address in line --------------------*/
/*---------------------------------------------------------*/
/* char *get_address() */
/* */
/* searches for the '@' char in internet addresses and */
/* then extracts the word the '@' is in. The terminat- */
/* ating characters are : ':' '<' '>' '(' ')' '"' '\t' */
/* '\r' and '\n'; at which point it stops looking. */
/* */
/*---------------------------------------------------------*/
char *get_address(char *buf, char *addr)
{
char *p , *c;
/* search for the '@' or "at" that is in every Internet address */
if ((p = strchr(buf,'@')) != NULL) {
c = p;
while (*p && (*p != ' ' &&
*p != '\t' &&
*p != ':' &&
*p != '<' &&
*p != '\"' &&
*p != '(' )) {
/* quite a few cases to check for */
p--;
}
while (*c && (*c != ' ' &&
*c != '\t' &&
*c != ':' &&
*c != '>' &&
*c != '\"' &&
*c != '\n' &&
*c != '\r' &&
*c != ')' )) {
/* quite a few cases to check for */
c++;
}
*c = '\0';
strcpy(addr, ++p);
return addr;
}
return NULL;
}
/*----------------------- get stuff off article header --------------------*/
/*---------------------------------------------------------*/
/* void get_his_stuff() */
/* */
/* obtains the address of the person in the passed arti- */
/* cle, as well as the msgid. */
/* */
/*---------------------------------------------------------*/
void get_his_stuff(TEXT *tx, char *author, char *msg_id)
{
/*
* Retrieve the author and msg_id from the article
*/
LINE *ln;
char *p;
char buf[256];
char *null_name = " < no name > ";
strcpy(author, null_name);
strcpy(msg_id, " <none> ");
ln = tx->top;
while (ln != NULL) {
strcpy(buf, ln->data);
strtok(buf, " :\n\r"); /* skip over <header>: */
p = strtok(NULL, " :\n\r"); /* skip over space */
if (p != NULL) {
if (strnicmp(ln->data, "Message-ID:", 11) == 0) {
p = ln->data + 11; /* is this necessary? [df] */
while (*p && isspace(*p))
++p;
p = strtok(p, " :\n\r");
if (p)
strncpy(msg_id, p, MSG_ID_LENGTH-1);
else
strncpy(msg_id, ln->data + 11, MSG_ID_LENGTH-1);
msg_id[MSG_ID_LENGTH-1] = '\0';
}
if ((strnicmp(ln->data, "From:", 5) == 0) && (strcmp(author, null_name) == 0)) {
if (get_address(ln->data, author) == NULL) {
strncpy(author, p, WHO_LENGTH-1);
author[WHO_LENGTH-1] = '\0';
}
}
if (strnicmp(ln->data, "Reply-To:", 5) == 0) {
if (get_address(ln->data, author) == NULL) {
strncpy(author, p, WHO_LENGTH-1);
author[WHO_LENGTH-1] = '\0';
}
}
} /* if */
if (strlen(ln->data) < 2)
break; /* we've found the start of the body */
ln = ln->next;
}
}
/*--------------------------- rot 13 the article ------------------------*/
void rot13(TEXT *tx)
{
LINE *ln;
int i, c;
ln = tx->start;
while (ln != NULL) {
for (i = 0; i < strlen(ln->data); i++) {
c = *((ln->data)+i);
if ((c >= 'A') && (c <= 'Z')) {
*((ln->data)+i) = (((c-'A') + 13) % 26) + 'A';
} else {
if ((c >= 'a') && (c <= 'z')) {
*((ln->data)+i) = (((c-'a') + 13) % 26) + 'a';
}
}
}
ln = ln->next;
}
}
/*--------------------------- expand the tabs ----------------------------*/
void expand_tabs(char *buf, int max_len)
{
int l, k;
char tmp[256], *p, *t;
p = buf;
t = &tmp[0];
l = 0;
while ((*p != '\x00') && (l < max_len)) {
if (*p != '\x09') {
*t = *p;
t++;
p++;
l++;
} else {
p++;
k = ((l / 8) + 1) * 8;
for ( ; l < k ; l++) {
*t = ' ';
t++;
if (l >= max_len) break;
}
}
}
*t = '\x00';
strcpy(buf, tmp);
}