|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T e
Length: 22788 (0x5904) Types: TextFile Names: »elm.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦4fd8323b9⟧ »EurOpenD3/mail/elm2.3.tar.Z« └─⟦698c4f91f⟧ └─⟦this⟧ »src/elm.c«
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\n\r\n\r",0); while (i <= j) { sprintf(buffer, "%3d %-16.16s %-40.40s %4d %d\n\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 -----\n\r\n\r\n\r\n\r", 1, current); Write_to_screen("Lines : %-5d\t\t\tStatus: A C D E F N O P T U V\n\r", 1, current_header->lines); Write_to_screen(" \t\t\t c o e x o e l r a r i\n\r", 0); Write_to_screen(" \t\t\t t n l p r w d i g g s\n\r", 0); Write_to_screen(" \t\t\t n f d d m v d n i\n\r", 0); sprintf(buffer, "\n\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, "\n\rReceived on: %d/%d/%d at %d:%02d\n\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\n\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\n\rSubject: %s", 2, current_header->from, current_header->subject); Write_to_screen("\n\rPrimary Recipient: %s\nInternal Index Reference Number = %d\n\r", 2, current_header->to, current_header->index_number); Write_to_screen("Message-ID: %s\n\r", 1, strlen(current_header->messageid) > 0 ? current_header->messageid : "<none>"); Write_to_screen("Status: %s\n\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: "))); }