home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
APPS
/
elm.lzh
/
ELM
/
SRC
/
ELM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-11
|
23KB
|
833 lines
static char rcsid[] = "@(#)$Id: elm.c,v 4.1 90/04/28 22:42:54 syd Exp $";
/*******************************************************************************
* The Elm Mail System - $Revision: 4.1 $ $State: Exp $
*
* This file and all associated files and documentation:
* Copyright (c) 1986, 1987 Dave Taylor
* Copyright (c) 1988, 1989, 1990 USENET Community Trust
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Syd Weinstein, Elm Coordinator
* elm@DSI.COM dsinc!elm
*
*******************************************************************************
* $Log: elm.c,v $
* Revision 4.1 90/04/28 22:42:54 syd
* checkin of Elm 2.3 as of Release PL0
*
*
******************************************************************************/
/* Main program of the ELM mail system!
*/
#include "elm.h"
#ifdef BSD
#undef toupper
#undef tolower
#endif
long bytes();
char *format_long(), *parse_arguments();
main(argc, argv)
int argc;
char *argv[];
{
int ch;
char address[SLEN], to_whom[SLEN], *req_mfile;
int key_offset; /** Position offset within keyboard string **/
int redraw, /** do we need to rewrite the entire screen? **/
nucurr, /** change message list or just the current message pointer... **/
nufoot; /** clear lines 16 thru bottom and new menu **/
int i,j; /** Random counting variables (etc) **/
int pageon, /** for when we receive new mail... **/
last_in_folder; /** for when we receive new mail too... **/
long num; /** another variable for fun.. **/
extern char version_buff[];
extern int errno;
req_mfile = parse_arguments(argc, argv, to_whom);
initialize(req_mfile);
if (mail_only) {
dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n",
format_long(to_whom, 3)));
if(!batch_only) {
sprintf(address, "Send only mode [ELM %s]", version_buff);
Centerline(1, address);
}
(void) sendmsg(to_whom, "", batch_subject, TRUE,
(batch_only ? NO : allow_forms), FALSE);
leave(0);
} else if (check_only) {
do_check_only(to_whom);
leave(0);
}
ScreenSize(&LINES, &COLUMNS);
showscreen();
while (1) {
redraw = 0;
nufoot = 0;
nucurr = 0;
if ((num = bytes(cur_folder)) != mailfile_size) {
dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n",
num - mailfile_size));
error("New mail has arrived! Hang on...");
fflush(stdin); /* just to be sure... */
last_in_folder = message_count;
pageon = header_page;
if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
dprint(1, (debugfile,
"Error: given file %s as folder - unreadable (%s)!\n",
cur_folder, error_name(errno)));
fprintf(stderr,"Can't open folder '%s' for reading!\n", cur_folder);
leave();
}
newmbox(cur_folder, TRUE); /* last won't be touched! */
clear_error();
header_page = pageon;
if (on_page(current)) /* do we REALLY have to rewrite? */
showscreen();
else {
update_title();
ClearLine(LINES-1); /* remove reading message... */
error2("%d new message%s received.",
message_count - last_in_folder,
plural(message_count - last_in_folder));
}
/* mailfile_size = num; */
if (cursor_control)
transmit_functions(ON); /* insurance */
}
prompt("Command: ");
CleartoEOLN();
ch = GetPrompt();
CleartoEOS();
#ifdef DEBUG
if (! movement_command(ch))
dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
#endif
set_error(""); /* clear error buffer */
MoveCursor(LINES-3,strlen("Command: "));
switch (ch) {
case '?' : if (help(FALSE))
redraw++;
else
nufoot++;
break;
case '$' : PutLine0(LINES-3, strlen("Command: "),
"Resynchronize folder");
redraw = resync();
break;
next_page:
case '+' : /* move to next page if we're not on the last */
if((selected &&
((header_page+1)*headers_per_page < selected))
||(!selected &&
((header_page+1)*headers_per_page<message_count))){
header_page++;
nucurr = NEW_PAGE;
if(move_when_paged) {
/* move to first message of new page */
if(selected)
current = visible_to_index(
header_page * headers_per_page + 1) + 1;
else
current = header_page * headers_per_page + 1;
}
} else error("Already on last page.");
break;
prev_page:
case '-' : /* move to prev page if we're not on the first */
if(header_page > 0) {
header_page--;
nucurr = NEW_PAGE;
if(move_when_paged) {
/* move to first message of new page */
if(selected)
current = visible_to_index(
header_page * headers_per_page + 1) + 1;
else
current = header_page * headers_per_page + 1;
}
} else error("Already on first page.");
break;
first_msg:
case '=' : if (selected)
current = visible_to_index(1)+1;
else
current = 1;
nucurr = get_page(current);
break;
last_msg:
case '*' : if (selected)
current = (visible_to_index(selected)+1);
else
current = message_count;
nucurr = get_page(current);
break;
case '|' : Writechar('|');
if (message_count < 1) {
error("No mail to pipe!");
fflush(stdin);
} else {
softkeys_off();
redraw = do_pipe();
softkeys_on();
}
break;
#ifdef ALLOW_SUBSHELL
case '!' : Writechar('!');
redraw = subshell();
break;
#endif
case '%' : if (current > 0) {
get_return(address, current-1);
clear_error();
PutLine1(LINES,(COLUMNS-strlen(address))/2,
"%.78s", address);
} else {
error("No mail to get return address of!");
fflush(stdin);
}
break;
case '/' : if (pattern_match())
nucurr = get_page(current);
else {
error("pattern not found!");
fflush(stdin);
}
break;
case '<' : /* scan current message for calendar information */
#ifdef ENABLE_CALENDAR
if (message_count < 1) {
error("No mail to scan!");
fflush(stdin);
}
else {
PutLine0(LINES-3, strlen("Command: "),
"Scan message for calendar entries...");
scan_calendar();
}
#else
error("Sorry. Calendar function disabled.");
fflush(stdin);
#endif
break;
case 'a' : if(alias()) redraw++;
else nufoot++;
define_softkeys(MAIN); break;
case 'b' : PutLine0(LINES-3, strlen("Command: "),
"Bounce message");
fflush(stdout);
if (message_count < 1) {
error("No mail to bounce!");
fflush(stdin);
}
else
nufoot = remail();
break;
case 'c' : PutLine0(LINES-3, strlen("Command: "),
"Change folder");
define_softkeys(CHANGE);
redraw = change_file();
define_softkeys(MAIN);
break;
case ctrl('D') :
case '^' :
case 'd' : if (message_count < 1) {
error("No mail to delete!");
fflush(stdin);
}
else {
if(ch == ctrl('D')) {
/* if current message did not become deleted,
* don't to move to the next undeleted msg. */
if(!meta_match(DELETED)) break;
} else
delete_msg((ch == 'd'), TRUE);
if (resolve_mode) /* move after mail resolved */
if((i=next_message(current-1, TRUE)) != -1) {
current = i+1;
nucurr = get_page(current);
}
}
break;
#ifdef ALLOW_MAILBOX_EDITING
case 'e' : PutLine0(LINES-3,strlen("Command: "),"Edit folder");
if (current > 0) {
edit_mailbox();
if (cursor_control)
transmit_functions(ON); /* insurance */
}
else {
error("Folder is empty!");
fflush(stdin);
}
break;
#else
case 'e' : error(
"Folder editing isn't configured in this version of ELM.");
fflush(stdin);
break;
#endif
case 'f' : PutLine0(LINES-3, strlen("Command: "), "Forward");
define_softkeys(YESNO);
if (current > 0) {
if(forward()) redraw++;
else nufoot++;
} else {
error("No mail to forward!");
fflush(stdin);
}
define_softkeys(MAIN);
break;
case 'g' : PutLine0(LINES-3,strlen("Command: "), "Group reply");
fflush(stdout);
if (current > 0) {
if (headers[current-1]->status & FORM_LETTER) {
error("Can't group reply to a Form!!");
fflush(stdin);
}
else {
define_softkeys(YESNO);
redraw = reply_to_everyone();
define_softkeys(MAIN);
}
}
else {
error("No mail to reply to!");
fflush(stdin);
}
break;
case 'h' : if (filter)
PutLine0(LINES-3, strlen("Command: "),
"Message with headers...");
else
PutLine0(LINES-3, strlen("Command: "),"Display message");
if(current > 0) {
fflush(stdout);
j = filter;
filter = FALSE;
i = show_msg(current);
while (i)
i = process_showmsg_cmd(i);
filter = j;
redraw++;
(void)get_page(current);
} else error("No mail to read!");
break;
case 'J' : if(current > 0) {
if((i=next_message(current-1, FALSE)) != -1) {
current = i+1;
nucurr = get_page(current);
} else error("No more messages below.");
} else error("No mail in folder!");
break;
next_undel_msg:
case 'j' : if(current > 0) {
if((i=next_message(current-1, TRUE)) != -1) {
current = i+1;
nucurr = get_page(current);
} else error("No more undeleted messages below.");
} else error("No mail in folder!");
break;
case 'K' : if(current > 0) {
if((i=prev_message(current-1, FALSE)) != -1) {
current = i+1;
nucurr = get_page(current);
} else error("No more messages above.");
} else error("No mail in folder!");
break;
prev_undel_msg:
case 'k' : if(current > 0) {
if((i=prev_message(current-1, TRUE)) != -1) {
current = i+1;
nucurr = get_page(current);
} else error("No more undeleted messages above.");
} else error("No mail in folder!");
break;
case 'l' : PutLine0(LINES-3, strlen("Command: "),
"Limit displayed messages by...");
clear_error();
if (limit() != 0) {
get_page(current);
redraw++;
} else {
nufoot++;
}
break;
case 'm' : PutLine0(LINES-3, strlen("Command: "), "Mail");
redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE);
break;
case ' ' :
case ctrl('J'):
case ctrl('M'):PutLine0(LINES-3, strlen("Command: "),
"Display message");
fflush(stdout);
if(current > 0 ) {
define_softkeys(READ);
i = show_msg(current);
while (i)
i = process_showmsg_cmd(i);
redraw++;
(void)get_page(current);
}else error ("No mail to read!");
break;
case 'n' : PutLine0(LINES-3,strlen("Command: "),"Next Message");
fflush(stdout);
define_softkeys(READ);
if(current > 0 ) {
define_softkeys(READ);
i = show_msg(current);
while (i)
i = process_showmsg_cmd(i);
redraw++;
if (++current > message_count)
current = message_count;
(void)get_page(current);
}else error ("No mail to read!");
break;
case 'o' : PutLine0(LINES-3, strlen("Command: "), "Options");
if((i=options()) > 0)
get_page(current);
else if(i < 0)
leave();
redraw++; /* always fix da screen... */
break;
case 'p' : PutLine0(LINES-3, strlen("Command: "), "Print mail");
fflush(stdout);
if (message_count < 1) {
error("No mail to print!");
fflush(stdin);
}
else
print_msg();
break;
case 'q' : PutLine0(LINES-3, strlen("Command: "), "Quit");
if (mailfile_size != bytes(cur_folder)) {
error("New Mail! Quit cancelled...");
fflush(stdin);
if (folder_type == SPOOL) unlock();
}
else
quit(TRUE);
break;
case 'Q' : PutLine0(LINES-3, strlen("Command: "), "Quick quit");
if (mailfile_size != bytes(cur_folder)) {
error("New Mail! Quick Quit cancelled...");
if (folder_type == SPOOL) unlock();
}
else
quit(FALSE);
break;
case 'r' : PutLine0(LINES-3, strlen("Command: "),
"Reply to message");
if (current > 0)
redraw = reply();
else {
error("No mail to reply to!");
fflush(stdin);
}
softkeys_on();
break;
case '>' : /** backwards compatibility **/
case 'C' :
case 's' : if (message_count < 1) {
error1("No mail to %s!",
ch != 'C' ? "save" : "copy");
fflush(stdin);
}
else {
PutLine1(LINES-3, strlen("Command: "),
"%s to folder",
ch != 'C' ? "Save" : "Copy");
PutLine0(LINES-3,COLUMNS-40,
"(Use '?' to list your folders)");
if (save(&redraw, FALSE, (ch != 'C'))
&& resolve_mode && ch != 'C') {
if((i=next_message(current-1, TRUE)) != -1) {
current = i+1;
nucurr = get_page(current);
}
}
}
ClearLine(LINES-2);
break;
case ctrl('T') :
case 't' : if (message_count < 1) {
error("No mail to tag!");
fflush(stdin);
}
else if (ch == 't')
tag_message(TRUE);
else
meta_match(TAGGED);
break;
case 'u' : if (message_count < 1) {
error("No mail to mark as undeleted!");
fflush(stdin);
}
else {
undelete_msg(TRUE);
if (resolve_mode) /* move after mail resolved */
if((i=next_message(current-1, FALSE)) != -1) {
current = i+1;
nucurr = get_page(current);
}
/*************************************************************************
** What we've done here is to special case the "U)ndelete" command to
** ignore whether the next message is marked for deletion or not. The
** reason is obvious upon usage - it's a real pain to undelete a series
** of messages without this quirk. Thanks to Jim Davis @ HPLabs for
** suggesting this more intuitive behaviour.
**
** The old way, for those people that might want to see what the previous
** behaviour was to call next_message with TRUE, not FALSE.
**************************************************************************/
}
break;
case ctrl('U') : if (message_count < 1) {
error("No mail to undelete!");
fflush(stdin);
}
else
meta_match(UNDELETE);
break;
case 'X' : PutLine0(LINES-3, strlen("Command: "), "Quick Exit");
fflush(stdout);
leave();
break;
case ctrl('Q') :
case 'x' : PutLine0(LINES-3, strlen("Command: "), "Exit");
fflush(stdout);
exit_prog();
break;
case ctrl('L') : redraw++; break;
case EOF : leave(); /* Read failed, control tty died? */
break;
case '@' : debug_screen(); redraw++; break;
case '#' : if (message_count) {
debug_message();
redraw++;
}
else {
error("No mail to check.");
fflush(stdin);
}
break;
case NO_OP_COMMAND : break; /* noop for timeout loop */
case ESCAPE : if (cursor_control) {
key_offset = 1;
ch = ReadCh();
if ( ch == '[' || ch == 'O')
{
ch = ReadCh();
key_offset++;
}
if(ch == up[key_offset]) goto prev_undel_msg;
else if(ch == down[key_offset]) goto next_undel_msg;
else if(ch == right[key_offset]) goto next_page;
else if(ch == left[key_offset]) goto prev_page;
else if (hp_terminal) {
switch (ch) {
case 'U': goto next_page;
case 'V': goto prev_page;
case 'h':
case 'H': goto first_msg;
case 'F': goto last_msg;
case 'A':
case 'D':
case 'i': goto next_undel_msg;
case 'B':
case 'I':
case 'C': goto prev_undel_msg;
default: PutLine2(LINES-3, strlen("Command: "),
"%c%c", ESCAPE, ch);
}
} else /* false hit - output */
PutLine2(LINES-3, strlen("Command: "),
"%c%c", ESCAPE, ch);
}
/* else fall into the default error message! */
default : if (ch > '0' && ch <= '9') {
PutLine0(LINES-3, strlen("Command: "),
"New Current Message");
i = read_number(ch);
if( i > message_count)
error("Not that many messages.");
else if(selected
&& isoff(headers[i-1]->status, VISIBLE))
error("Message not in limited display.");
else {
current = i;
nucurr = get_page(current);
}
}
else {
error("Unknown command. Use '?' for help.");
fflush(stdin);
}
}
if (redraw)
showscreen();
if ((current < 1) || (selected && compute_visible(current) < 1)) {
if (message_count > 0) {
/* We are out of range! Get to first message! */
if (selected)
current = compute_visible(1);
else
current = 1;
}
else
current = 0;
}
else if ((current > message_count)
|| (selected && compute_visible(current) > selected)) {
if (message_count > 0) {
/* We are out of range! Get to last (visible) message! */
if (selected)
current = visible_to_index(selected)+1;
else
current = message_count;
}
else
current = 0;
}
if (nucurr == NEW_PAGE)
show_headers();
else if (nucurr == SAME_PAGE)
show_current();
else if (nufoot) {
if (mini_menu) {
MoveCursor(LINES-7, 0);
CleartoEOS();
show_menu();
}
else {
MoveCursor(LINES-4, 0);
CleartoEOS();
}
show_last_error(); /* for those operations that have to
* clear the footer except for a message.
*/
}
} /* the BIG while loop! */
}
debug_screen()
{
/**** spit out all the current variable settings and the table
entries for the current 'n' items displayed. ****/
register int i, j;
char buffer[SLEN];
ClearScreen();
Raw(OFF);
PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
current, message_count);
PutLine2(2,0,"Header_page = %d \t\t%d possible page(s)\n",
header_page, (int) (message_count / headers_per_page) + 1);
PutLine1(4,0,"\nCurrent mailfile is %s.\n\n", cur_folder);
i = header_page*headers_per_page; /* starting header */
if ((j = i + (headers_per_page-1)) >= message_count)
j = message_count-1;
Write_to_screen(
"Num From Subject Lines Offset\l\r\l\r",0);
while (i <= j) {
sprintf(buffer,
"%3d %-16.16s %-40.40s %4d %d\l\r",
i+1,
headers[i]->from,
headers[i]->subject,
headers[i]->lines,
headers[i]->offset);
Write_to_screen(buffer, 0);
i++;
}
Raw(ON);
PutLine0(LINES,0,"Press any key to return.");
(void) ReadCh();
}
debug_message()
{
/**** Spit out the current message record. Include EVERYTHING
in the record structure. **/
char buffer[SLEN];
register struct header_rec *current_header = headers[current-1];
ClearScreen();
Raw(OFF);
Write_to_screen("\t\t\t----- Message %d -----\l\r\l\r\l\r\l\r", 1,
current);
Write_to_screen("Lines : %-5d\t\t\tStatus: A C D E F N O P T U V\l\r", 1,
current_header->lines);
Write_to_screen(" \t\t\t c o e x o e l r a r i\l\r", 0);
Write_to_screen(" \t\t\t t n l p r w d i g g s\l\r", 0);
Write_to_screen(" \t\t\t n f d d m v d n i\l\r", 0);
sprintf(buffer,
"\l\rOffset: %ld\t\t\t %d %d %d %d %d",
current_header->offset,
(current_header->status & ACTION) != 0,
(current_header->status & CONFIDENTIAL) != 0,
(current_header->status & DELETED) != 0,
(current_header->status & EXPIRED) != 0,
(current_header->status & FORM_LETTER) != 0);
sprintf(buffer + strlen(buffer),
" %d %d %d %d %d %d\n",
(current_header->status & NEW) != 0,
(current_header->status & UNREAD) != 0,
(current_header->status & PRIVATE) != 0,
(current_header->status & TAGGED) != 0,
(current_header->status & URGENT) != 0,
(current_header->status & VISIBLE) != 0);
Write_to_screen(buffer, 0);
sprintf(buffer, "\l\rReceived on: %d/%d/%d at %d:%02d\l\r",
current_header->received.month+1,
current_header->received.day,
current_header->received.year,
current_header->received.hour,
current_header->received.minute);
Write_to_screen(buffer, 0);
sprintf(buffer, "Message sent on: %s, %s %s, %s at %s\l\r",
current_header->dayname,
current_header->month,
current_header->day,
current_header->year,
current_header->time);
Write_to_screen(buffer, 0);
Write_to_screen("From: %s\l\rSubject: %s", 2,
current_header->from,
current_header->subject);
Write_to_screen("\l\rPrimary Recipient: %s\nInternal Index Reference Number = %d\l\r", 2,
current_header->to,
current_header->index_number);
Write_to_screen("Message-ID: %s\l\r", 1,
strlen(current_header->messageid) > 0 ?
current_header->messageid : "<none>");
Write_to_screen("Status: %s\l\r", 1, current_header->mailx_status);
Raw(ON);
PutLine0(LINES,0,"Please Press any key to return.");
(void) ReadCh();
}
do_check_only(to_whom)
char *to_whom;
{
char buffer[VERY_LONG_STRING];
dprint(3, (debugfile, "Check-only: checking \n-> \"%s\"\n",
format_long(to_whom, 3)));
(void) build_address(strip_commas(to_whom), buffer);
printf("Expands to: %s", format_long(buffer, strlen("Expands to: ")));
}