rsalz@bbn.com (Rich Salz) (05/31/90)
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com> Posting-number: Volume 22, Issue 73 Archive-name: elm2.3/part14 ---- Cut Here and unpack ---- #!/bin/sh # this is part 14 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/editmsg.c continued # CurArch=14 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file src/editmsg.c" sed 's/^X//' << 'SHAR_EOF' >> src/editmsg.c X strcpy(editor, emacs_editor); X fclose(edit_fd); X (void) edit_the_message(filename,0); X strcpy(editor, buffer); X edit_fd = fopen(filename, "a"); X Write_to_screen(post_ed_continue, 0); X goto more_input; X } X else X Write_to_screen( X "\n\r(Can't find Emacs on this system! Continue.)\n\r", X 0); X else X Write_to_screen( X "\n\r(Don't know where Emacs would be. Continue.)\n\r", X 0); X goto more_input; X X case 'v' : NewLine(); X strcpy(buffer, editor); X strcpy(editor, default_editor); X fclose(edit_fd); X (void) edit_the_message(filename,0); X strcpy(editor, buffer); X edit_fd = fopen(filename, "a"); X Write_to_screen(post_ed_continue, 0); X goto more_input; X X case 'o' : Write_to_screen( X "\n\rPlease enter the name of the editor: ", 0); X editor_name[0] = '\0'; X optionally_enter(editor_name,-1,-1, FALSE, FALSE); X NewLine(); X if (strlen(editor_name) > 0) { X strcpy(buffer, editor); X strcpy(editor, editor_name); X fclose(edit_fd); X (void) edit_the_message(filename,0); X strcpy(editor, buffer); X edit_fd = fopen(filename, "a"); X Write_to_screen(post_ed_continue, 0); X goto more_input; X } X Write_to_screen(simple_continue, 0); X goto more_input; X X case '<' : NewLine(); X if (strlen(buffer) < 3) X Write_to_screen( X "(You need to use a specific command here. Continue.)\n\r"); X else { X sprintf(buf, " > %s%s.%d 2>&1", temp_dir, temp_edit, getpid()); X strcat(buffer, buf); X if (( old_raw = RawState()) == ON) X Raw(OFF); X (void) system_call((char *) buffer+2, SH, TRUE, TRUE); X if (old_raw == ON) X Raw(ON); X sprintf(buffer, "~r %s%s.%d", temp_dir, temp_edit, getpid()); X read_in_file(edit_fd, (char *) buffer + 3, 0); X (void) unlink((char *) buffer+3); X } X goto more_input; X X case '!' : NewLine(); X if (( old_raw = RawState()) == ON) X Raw(OFF); X if (strlen(buffer) < 3) X (void) system_call(shell, USER_SHELL, TRUE, TRUE); X else X (void) system_call((char *) buffer+2, USER_SHELL, TRUE, TRUE); X if (old_raw == ON) X Raw(ON); X Write_to_screen(simple_continue, 0); X goto more_input; X X case 'm' : /* same as 'f' but with leading prefix added */ X X case 'f' : /* this can be directly translated into a X 'readmsg' call with the same params! */ X NewLine(); X read_in_messages(edit_fd, (char *) buffer + 1); X goto more_input; X X case 'p' : /* print out message so far. Soooo simple! */ X print_message_so_far(edit_fd, filename); X goto more_input; X X default : sprintf(buf, X "\n\r(Don't know what %c%c is. Try %c? for help.)\n\r", X escape_char, buffer[1], escape_char); X Write_to_screen(buf, 0); X } X } X else { Xtilde_input: X fprintf(edit_fd, "%s\n", buffer); X NewLine(); X } X buffer[0] = '\0'; X } X X X Write_to_screen("\n\r<end-of-message>\n\r\n\r\n\r\n\r", 0); X X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X X if (edit_fd != NULL) /* insurance... */ X fclose(edit_fd); X X return(0); X} X Xtilde_help() X{ X /* a simple routine to print out what is available at this level */ X X char buf[SLEN]; X X Write_to_screen("\n\r(Available options at this point are:\n\r\n\r", 0); X sprintf(buf, "\t%c?\tPrint this help menu.\n\r", escape_char); X Write_to_screen(buf, 0); X if (escape_char == TILDE_ESCAPE) /* doesn't make sense otherwise... */ X Write_to_screen( X "\t~~\tAdd line prefixed by a single '~' character.\n\r", 0); X X sprintf(buf, X "\t%cb\tChange the addresses in the Blind-carbon-copy list.\n\r", X escape_char); X Write_to_screen(buf, 0); X X sprintf(buf, X "\t%cc\tChange the addresses in the Carbon-copy list.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%ce\tInvoke the Emacs editor on the message, if possible.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cf\tAdd the specified message or current.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%ch\tChange all available headers (to, cc, bcc, subject).\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cm\tSame as '%cf', but with the current 'prefix'.\n\r", X escape_char, escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%co\tInvoke a user specified editor on the message.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cp\tPrint out message as typed in so far.\n\r", escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cr\tRead in the specified file.\n\r", escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cs\tChange the subject of the message.\n\r", escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%ct\tChange the addresses in the To list.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%cv\tInvoke the Vi visual editor on the message.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%c!\tExecute a unix command (or give a shell if no command).\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t%c<\tExecute a unix command adding the output to the message.\n\r", X escape_char); X Write_to_screen(buf, 0); X sprintf(buf, X "\t. \tby itself on a line (or a control-D) ends the message.\n\r"); X Write_to_screen(buf, 0); X Write_to_screen("Continue.)\n\r", 0); X} X Xread_in_file(fd, filename, show_user_filename) XFILE *fd; Xchar *filename; Xint show_user_filename; X{ X /** Open the specified file and stream it in to the already opened X file descriptor given to us. When we're done output the number X of lines and characters we added, if any... **/ X X FILE *myfd; X char myfname[SLEN], buffer[SLEN]; X register int n; X register int lines = 0, nchars = 0; X X for ( n = 0 ; whitespace(filename[n]) ; n++ ); X X /** expand any shell variables, '~' or other notation... **/ X /* temp copy of filename to buffer since expand_env is destructive */ X strcpy(buffer, &filename[n]); X expand_env(myfname, buffer); X X if (strlen(myfname) == 0) { X Write_to_screen( X "\n\r(No filename specified for file read! Continue.)\n\r", 0); X return; X } X X if ((myfd = fopen(myfname,"r")) == NULL) { X Write_to_screen("\n\r(Couldn't read file '%s'! Continue.)\n\r", 1, X myfname); X return; X } X X while (fgets(buffer, SLEN, myfd) != NULL) { X n = strlen(buffer); X if(buffer[n-1] == '\n') lines++; X nchars += n; X fputs(buffer, fd); X fflush(stdout); X } X X fclose(myfd); X X if (show_user_filename) X sprintf(buffer, X "\n\r(Added %d line%s [%d char%s] from file %s. Continue.)\n\r", X lines, plural(lines), nchars, plural(nchars), myfname); X else X sprintf(buffer, X "\n\r(Added %d line%s [%d char%s] to message. Continue.)\n\r", X lines, plural(lines), nchars, plural(nchars)); X Write_to_screen(buffer, 0); X X return; X} X Xprint_message_so_far(edit_fd, filename) XFILE *edit_fd; Xchar *filename; X{ X /** This prints out the message typed in so far. We accomplish X this in a cheap manner - close the file, reopen it for reading, X stream it to the screen, then close the file, and reopen it X for appending. Simple, but effective! X X A nice enhancement would be for this to -> page <- the message X if it's sufficiently long. Too much work for now, though. X **/ X X char buffer[SLEN]; X X fclose(edit_fd); X X if ((edit_fd = fopen(filename, "r")) == NULL) { X Write_to_screen("\n\rMayday! Mayday! Mayday!\n\r", 0); X Write_to_screen("\n\rPanic: Can't open file for reading! Bail!\n\r", X 0); X emergency_exit(); X } X X Write_to_screen("\n\rTo: %s\n\r", 1, format_long(to, 4)); X Write_to_screen("Cc: %s\n\r", 1, format_long(cc, 4)); X Write_to_screen("Bcc: %s\n\r", 1, format_long(bcc, 5)); X Write_to_screen("Subject: %s\n\r\n\r", 1, subject); X X while (fgets(buffer, SLEN, edit_fd) != NULL) { X Write_to_screen(buffer, 0); X CarriageReturn(); X } X X fclose(edit_fd); X X if ((edit_fd = fopen(filename, "a")) == NULL) { X Write_to_screen("Mayday! Mayday! Abandon Ship! Aiiieeeeee\n\r", 0); X Write_to_screen("\n\rPanic: Can't reopen file for appending!\n\r", 0); X emergency_exit(); X } X X Write_to_screen("\n\r(Continue entering message.)\n\r", 0); X} X Xread_in_messages(fd, buffer) XFILE *fd; Xchar *buffer; X{ X /** Read the specified messages into the open file. If the X first character of "buffer" is 'm' then prefix it, other- X wise just stream it in straight...Since we're using the X pipe to 'readmsg' we can also allow the user to specify X patterns and such too... X **/ X X FILE *myfd, *popen(); X char local_buffer[SLEN], *arg; X register int add_prefix=0, mindex; X register int n; X int lines = 0, nchars = 0; X X add_prefix = tolower(buffer[0]) == 'm'; X X /* strip whitespace to get argument */ X for(arg = &buffer[1]; whitespace(*arg); arg++) X ; X X /* if no argument or begins with a digit, then retrieve the X * appropriate message from the current folder, else X * just take the arguments as a pattern for readmsg to match in X * the current folder. X */ X if(isdigit(*arg) || *arg == '\0') { X if(message_count < 1) { X Write_to_screen("(No messages to read in! Continue.)\n\r", 0); X return; X } X if((mindex = atoi(arg)) == 0) /* no argument - read in current msg */ X mindex = current; X else if(mindex < 1 || mindex > message_count) { X sprintf(local_buffer, X "(Valid messsage numbers are between 1 and %d. Continue.)\n\r", X message_count); X Write_to_screen(local_buffer, 0); X return; X } X X sprintf(local_buffer, "%s -f %s %d", readmsg, cur_folder, X headers[mindex-1]->index_number); X X } else X sprintf(local_buffer, "%s -f %s %s", readmsg, cur_folder, arg); X X X /* now get output of readmsg */ X if ((myfd = popen(local_buffer, "r")) == NULL) { X Write_to_screen("(Can't find 'readmsg' command! Continue.)\n\r", X 0); X return; X } X X dprint(5, (debugfile, "** readmsg call: \"%s\" **\n", local_buffer)); X X while (fgets(local_buffer, SLEN, myfd) != NULL) { X n = strlen(local_buffer); X nchars += n; X if (local_buffer[n-1] == '\n') lines++; X if (add_prefix) X fprintf(fd, "%s%s", prefixchars, local_buffer); X else X fputs(local_buffer, fd); X } X X pclose(myfd); X X if (lines == 0) X sprintf(local_buffer, X "(Couldn't add the requested message. Continue.)\n\r"); X else X sprintf(local_buffer, X "(Added %d line%s [%d char%s] to message. Continue.)\n\r", X lines, plural(lines), nchars, plural(nchars)); X Write_to_screen(local_buffer, 0); X X return; X} X Xget_with_expansion(prompt, buffer, expanded_buffer, sourcebuf) Xchar *prompt, *buffer, *expanded_buffer, *sourcebuf; X{ X /** This is used to prompt for a new value of the specified field. X If expanded_buffer == NULL then we won't bother trying to expand X this puppy out! (sourcebuf could be an initial addition) X **/ X X Write_to_screen(prompt, 0); fflush(stdout); /* output! */ X X if (sourcebuf != NULL) { X while (!whitespace(*sourcebuf) && *sourcebuf != '\0') X sourcebuf++; X if (*sourcebuf != '\0') { X while (whitespace(*sourcebuf)) X sourcebuf++; X if (strlen(sourcebuf) > 0) { X strcat(buffer, " "); X strcat(buffer, sourcebuf); X } X } X } X X optionally_enter(buffer, -1, -1, TRUE, FALSE); /* already data! */ X X if(expanded_buffer != NULL) { X build_address(strip_commas(buffer), expanded_buffer); X if(*expanded_buffer != '\0') { X if (*prompt == '\n') X Write_to_screen("%s%s", 2, prompt, expanded_buffer); X else X Write_to_screen("\n\r%s%s", 2, prompt, expanded_buffer); X } X } X NewLine(); X X return; X} X Xedit_interrupt() X{ X /** This routine is called when the user hits an interrupt key X while in the builtin editor...it increments the number of X times an interrupt is hit and returns it. X **/ X X signal(SIGINT, edit_interrupt); X signal(SIGQUIT, edit_interrupt); X X if (interrupts_while_editing++ == 0) X Write_to_screen("(Interrupt. One more to cancel this letter.)\n\r", X 0); X else X Write_to_screen("(Interrupt. Letter cancelled.)\n\r", 0); X X longjmp(edit_location, 1); /* get back */ X} SHAR_EOF echo "File src/editmsg.c is complete" chmod 0444 src/editmsg.c || echo "restore of src/editmsg.c fails" echo "x - extracting src/elm.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/elm.c && X Xstatic char rcsid[] = "@(#)$Id: elm.c,v 4.1 90/04/28 22:42:54 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * This file and all associated files and documentation: X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: elm.c,v $ X * Revision 4.1 90/04/28 22:42:54 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/* Main program of the ELM mail system! X*/ X X#include "elm.h" X X#ifdef BSD X#undef toupper X#undef tolower X#endif X Xlong bytes(); Xchar *format_long(), *parse_arguments(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X { X int ch; X char address[SLEN], to_whom[SLEN], *req_mfile; X int key_offset; /** Position offset within keyboard string **/ X int redraw, /** do we need to rewrite the entire screen? **/ X nucurr, /** change message list or just the current message pointer... **/ X nufoot; /** clear lines 16 thru bottom and new menu **/ X int i,j; /** Random counting variables (etc) **/ X int pageon, /** for when we receive new mail... **/ X last_in_folder; /** for when we receive new mail too... **/ X long num; /** another variable for fun.. **/ X extern char version_buff[]; X extern int errno; X X req_mfile = parse_arguments(argc, argv, to_whom); X X initialize(req_mfile); X X if (mail_only) { X dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", X format_long(to_whom, 3))); X if(!batch_only) { X sprintf(address, "Send only mode [ELM %s]", version_buff); X Centerline(1, address); X } X (void) sendmsg(to_whom, "", batch_subject, TRUE, X (batch_only ? NO : allow_forms), FALSE); X leave(0); X } else if (check_only) { X do_check_only(to_whom); X leave(0); X } X X ScreenSize(&LINES, &COLUMNS); X X showscreen(); X X while (1) { X redraw = 0; X nufoot = 0; X nucurr = 0; X if ((num = bytes(cur_folder)) != mailfile_size) { X dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", X num - mailfile_size)); X error("New mail has arrived! Hang on..."); X fflush(stdin); /* just to be sure... */ X last_in_folder = message_count; X pageon = header_page; X X if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) { X dprint(1, (debugfile, X "Error: given file %s as folder - unreadable (%s)!\n", X cur_folder, error_name(errno))); X fprintf(stderr,"Can't open folder '%s' for reading!\n", cur_folder); X leave(); X } X X newmbox(cur_folder, TRUE); /* last won't be touched! */ X clear_error(); X header_page = pageon; X X if (on_page(current)) /* do we REALLY have to rewrite? */ X showscreen(); X else { X update_title(); X ClearLine(LINES-1); /* remove reading message... */ X error2("%d new message%s received.", X message_count - last_in_folder, X plural(message_count - last_in_folder)); X } X /* mailfile_size = num; */ X if (cursor_control) X transmit_functions(ON); /* insurance */ X } X X prompt("Command: "); X X CleartoEOLN(); X ch = GetPrompt(); X CleartoEOS(); X#ifdef DEBUG X if (! movement_command(ch)) X dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch)); X#endif X X set_error(""); /* clear error buffer */ X X MoveCursor(LINES-3,strlen("Command: ")); X X switch (ch) { X X case '?' : if (help(FALSE)) X redraw++; X else X nufoot++; X break; X X case '$' : PutLine0(LINES-3, strlen("Command: "), X "Resynchronize folder"); X redraw = resync(); X break; X Xnext_page: X case '+' : /* move to next page if we're not on the last */ X if((selected && X ((header_page+1)*headers_per_page < selected)) X ||(!selected && X ((header_page+1)*headers_per_page<message_count))){ X X header_page++; X nucurr = NEW_PAGE; X X if(move_when_paged) { X /* move to first message of new page */ X if(selected) X current = visible_to_index( X header_page * headers_per_page + 1) + 1; X else X current = header_page * headers_per_page + 1; X } X } else error("Already on last page."); X break; X Xprev_page: X case '-' : /* move to prev page if we're not on the first */ X if(header_page > 0) { X header_page--; X nucurr = NEW_PAGE; X X if(move_when_paged) { X /* move to first message of new page */ X if(selected) X current = visible_to_index( X header_page * headers_per_page + 1) + 1; X else X current = header_page * headers_per_page + 1; X } X } else error("Already on first page."); X break; X Xfirst_msg: X case '=' : if (selected) X current = visible_to_index(1)+1; X else X current = 1; X nucurr = get_page(current); X break; X Xlast_msg: X case '*' : if (selected) X current = (visible_to_index(selected)+1); X else X current = message_count; X nucurr = get_page(current); X break; X X case '|' : Writechar('|'); X if (message_count < 1) { X error("No mail to pipe!"); X fflush(stdin); X } else { X softkeys_off(); X redraw = do_pipe(); X softkeys_on(); X } X break; X X#ifdef ALLOW_SUBSHELL X case '!' : Writechar('!'); X redraw = subshell(); X break; X#endif X X case '%' : if (current > 0) { X get_return(address, current-1); X clear_error(); X PutLine1(LINES,(COLUMNS-strlen(address))/2, X "%.78s", address); X } else { X error("No mail to get return address of!"); X fflush(stdin); X } X break; X X case '/' : if (pattern_match()) X nucurr = get_page(current); X else { X error("pattern not found!"); X fflush(stdin); X } X break; X X case '<' : /* scan current message for calendar information */ X#ifdef ENABLE_CALENDAR X if (message_count < 1) { X error("No mail to scan!"); X fflush(stdin); X } X else { X PutLine0(LINES-3, strlen("Command: "), X "Scan message for calendar entries..."); X scan_calendar(); X } X#else X error("Sorry. Calendar function disabled."); X fflush(stdin); X#endif X break; X X case 'a' : if(alias()) redraw++; X else nufoot++; X define_softkeys(MAIN); break; X X case 'b' : PutLine0(LINES-3, strlen("Command: "), X "Bounce message"); X fflush(stdout); X if (message_count < 1) { X error("No mail to bounce!"); X fflush(stdin); X } X else X nufoot = remail(); X break; X X case 'c' : PutLine0(LINES-3, strlen("Command: "), X "Change folder"); X define_softkeys(CHANGE); X redraw = change_file(); X define_softkeys(MAIN); X break; X X case ctrl('D') : X case '^' : X case 'd' : if (message_count < 1) { X error("No mail to delete!"); X fflush(stdin); X } X else { X if(ch == ctrl('D')) { X X /* if current message did not become deleted, X * don't to move to the next undeleted msg. */ X if(!meta_match(DELETED)) break; X X } else X delete_msg((ch == 'd'), TRUE); X X if (resolve_mode) /* move after mail resolved */ X if((i=next_message(current-1, TRUE)) != -1) { X current = i+1; X nucurr = get_page(current); X } X } X break; X X X#ifdef ALLOW_MAILBOX_EDITING X case 'e' : PutLine0(LINES-3,strlen("Command: "),"Edit folder"); X if (current > 0) { X edit_mailbox(); X if (cursor_control) X transmit_functions(ON); /* insurance */ X } X else { X error("Folder is empty!"); X fflush(stdin); X } X break; X#else X case 'e' : error( X "Folder editing isn't configured in this version of ELM."); X fflush(stdin); X break; X#endif X X case 'f' : PutLine0(LINES-3, strlen("Command: "), "Forward"); X define_softkeys(YESNO); X if (current > 0) { X if(forward()) redraw++; X else nufoot++; X } else { X error("No mail to forward!"); X fflush(stdin); X } X define_softkeys(MAIN); X break; X X case 'g' : PutLine0(LINES-3,strlen("Command: "), "Group reply"); X fflush(stdout); X if (current > 0) { X if (headers[current-1]->status & FORM_LETTER) { X error("Can't group reply to a Form!!"); X fflush(stdin); X } X else { X define_softkeys(YESNO); X redraw = reply_to_everyone(); X define_softkeys(MAIN); X } X } X else { X error("No mail to reply to!"); X fflush(stdin); X } X break; X X case 'h' : if (filter) X PutLine0(LINES-3, strlen("Command: "), X "Message with headers..."); X else X PutLine0(LINES-3, strlen("Command: "),"Display message"); X if(current > 0) { X fflush(stdout); X j = filter; X filter = FALSE; X i = show_msg(current); X while (i) X i = process_showmsg_cmd(i); X filter = j; X redraw++; X (void)get_page(current); X } else error("No mail to read!"); X break; X X case 'J' : if(current > 0) { X if((i=next_message(current-1, FALSE)) != -1) { X current = i+1; X nucurr = get_page(current); X } else error("No more messages below."); X } else error("No mail in folder!"); X break; X Xnext_undel_msg: X case 'j' : if(current > 0) { X if((i=next_message(current-1, TRUE)) != -1) { X current = i+1; X nucurr = get_page(current); X } else error("No more undeleted messages below."); X } else error("No mail in folder!"); X break; X X case 'K' : if(current > 0) { X if((i=prev_message(current-1, FALSE)) != -1) { X current = i+1; X nucurr = get_page(current); X } else error("No more messages above."); X } else error("No mail in folder!"); X break; X Xprev_undel_msg: X case 'k' : if(current > 0) { X if((i=prev_message(current-1, TRUE)) != -1) { X current = i+1; X nucurr = get_page(current); X } else error("No more undeleted messages above."); X } else error("No mail in folder!"); X break; X X case 'l' : PutLine0(LINES-3, strlen("Command: "), X "Limit displayed messages by..."); X clear_error(); X if (limit() != 0) { X get_page(current); X redraw++; X } else { X nufoot++; X } X break; X X case 'm' : PutLine0(LINES-3, strlen("Command: "), "Mail"); X redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE); X break; X X case ' ' : X case ctrl('J'): X case ctrl('M'):PutLine0(LINES-3, strlen("Command: "), X "Display message"); X fflush(stdout); X if(current > 0 ) { X define_softkeys(READ); X X i = show_msg(current); X while (i) X i = process_showmsg_cmd(i); X redraw++; X (void)get_page(current); X }else error ("No mail to read!"); X break; X X case 'n' : PutLine0(LINES-3,strlen("Command: "),"Next Message"); X fflush(stdout); X define_softkeys(READ); X X if(current > 0 ) { X define_softkeys(READ); X X i = show_msg(current); X while (i) X i = process_showmsg_cmd(i); X redraw++; X if (++current > message_count) X current = message_count; X (void)get_page(current); X }else error ("No mail to read!"); X break; X X case 'o' : PutLine0(LINES-3, strlen("Command: "), "Options"); X if((i=options()) > 0) X get_page(current); X else if(i < 0) X leave(); X redraw++; /* always fix da screen... */ X break; X X case 'p' : PutLine0(LINES-3, strlen("Command: "), "Print mail"); X fflush(stdout); X if (message_count < 1) { X error("No mail to print!"); X fflush(stdin); X } X else X print_msg(); X break; X X case 'q' : PutLine0(LINES-3, strlen("Command: "), "Quit"); X X if (mailfile_size != bytes(cur_folder)) { X error("New Mail! Quit cancelled..."); X fflush(stdin); X if (folder_type == SPOOL) unlock(); X } X else X quit(TRUE); X X break; X X case 'Q' : PutLine0(LINES-3, strlen("Command: "), "Quick quit"); X X if (mailfile_size != bytes(cur_folder)) { X error("New Mail! Quick Quit cancelled..."); X if (folder_type == SPOOL) unlock(); X } X else X quit(FALSE); X X break; X X case 'r' : PutLine0(LINES-3, strlen("Command: "), X "Reply to message"); X if (current > 0) X redraw = reply(); X else { X error("No mail to reply to!"); X fflush(stdin); X } X softkeys_on(); X break; X X case '>' : /** backwards compatibility **/ X X case 'C' : X case 's' : if (message_count < 1) { X error1("No mail to %s!", X ch != 'C' ? "save" : "copy"); X fflush(stdin); X } X else { X PutLine1(LINES-3, strlen("Command: "), X "%s to folder", X ch != 'C' ? "Save" : "Copy"); X PutLine0(LINES-3,COLUMNS-40, X "(Use '?' to list your folders)"); X if (save(&redraw, FALSE, (ch != 'C')) X && resolve_mode && ch != 'C') { X if((i=next_message(current-1, TRUE)) != -1) { X current = i+1; X nucurr = get_page(current); X } X } X } X ClearLine(LINES-2); X break; X X case ctrl('T') : X case 't' : if (message_count < 1) { X error("No mail to tag!"); X fflush(stdin); X } X else if (ch == 't') X tag_message(TRUE); X else X meta_match(TAGGED); X break; X X case 'u' : if (message_count < 1) { X error("No mail to mark as undeleted!"); X fflush(stdin); X } X else { X undelete_msg(TRUE); X if (resolve_mode) /* move after mail resolved */ X if((i=next_message(current-1, FALSE)) != -1) { X current = i+1; X nucurr = get_page(current); X } X/************************************************************************* X ** What we've done here is to special case the "U)ndelete" command to X ** ignore whether the next message is marked for deletion or not. The X ** reason is obvious upon usage - it's a real pain to undelete a series X ** of messages without this quirk. Thanks to Jim Davis @ HPLabs for X ** suggesting this more intuitive behaviour. X ** X ** The old way, for those people that might want to see what the previous X ** behaviour was to call next_message with TRUE, not FALSE. X**************************************************************************/ X } X break; X X case ctrl('U') : if (message_count < 1) { X error("No mail to undelete!"); X fflush(stdin); X } X else X meta_match(UNDELETE); X break; X X case 'X' : PutLine0(LINES-3, strlen("Command: "), "Quick Exit"); X fflush(stdout); X leave(); X break; X X case ctrl('Q') : X case 'x' : PutLine0(LINES-3, strlen("Command: "), "Exit"); X fflush(stdout); X exit_prog(); X break; X X case ctrl('L') : redraw++; break; X X case EOF : leave(); /* Read failed, control tty died? */ X break; X X case '@' : debug_screen(); redraw++; break; X X case '#' : if (message_count) { X debug_message(); X redraw++; X } X else { X error("No mail to check."); X fflush(stdin); X } X break; X X case NO_OP_COMMAND : break; /* noop for timeout loop */ X X case ESCAPE : if (cursor_control) { X key_offset = 1; X ch = ReadCh(); X X if ( ch == '[' || ch == 'O') X { X ch = ReadCh(); X key_offset++; X } X X if(ch == up[key_offset]) goto prev_undel_msg; X else if(ch == down[key_offset]) goto next_undel_msg; X else if(ch == right[key_offset]) goto next_page; X else if(ch == left[key_offset]) goto prev_page; X else if (hp_terminal) { X switch (ch) { X case 'U': goto next_page; X case 'V': goto prev_page; X case 'h': X case 'H': goto first_msg; X case 'F': goto last_msg; X case 'A': X case 'D': X case 'i': goto next_undel_msg; X case 'B': X case 'I': X case 'C': goto prev_undel_msg; X default: PutLine2(LINES-3, strlen("Command: "), X "%c%c", ESCAPE, ch); X } X } else /* false hit - output */ X PutLine2(LINES-3, strlen("Command: "), X "%c%c", ESCAPE, ch); X } X X /* else fall into the default error message! */ X X default : if (ch > '0' && ch <= '9') { X PutLine0(LINES-3, strlen("Command: "), X "New Current Message"); X i = read_number(ch); X X if( i > message_count) X error("Not that many messages."); X else if(selected X && isoff(headers[i-1]->status, VISIBLE)) X error("Message not in limited display."); X else { X current = i; X nucurr = get_page(current); X } X } X else { X error("Unknown command. Use '?' for help."); X fflush(stdin); X } X } X X if (redraw) X showscreen(); X X if ((current < 1) || (selected && compute_visible(current) < 1)) { X if (message_count > 0) { X /* We are out of range! Get to first message! */ X if (selected) X current = compute_visible(1); X else X current = 1; X } X else X current = 0; X } X else if ((current > message_count) X || (selected && compute_visible(current) > selected)) { X if (message_count > 0) { X /* We are out of range! Get to last (visible) message! */ X if (selected) X current = visible_to_index(selected)+1; X else X current = message_count; X } X else X current = 0; X } X X if (nucurr == NEW_PAGE) X show_headers(); X else if (nucurr == SAME_PAGE) X show_current(); X else if (nufoot) { X if (mini_menu) { X MoveCursor(LINES-7, 0); X CleartoEOS(); X show_menu(); X } X else { X MoveCursor(LINES-4, 0); X CleartoEOS(); X } X show_last_error(); /* for those operations that have to X * clear the footer except for a message. X */ X } X X } /* the BIG while loop! */ X} X Xdebug_screen() X{ X /**** spit out all the current variable settings and the table X entries for the current 'n' items displayed. ****/ X X register int i, j; X char buffer[SLEN]; X X ClearScreen(); X Raw(OFF); X X PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n", X current, message_count); X PutLine2(2,0,"Header_page = %d \t\t%d possible page(s)\n", X header_page, (int) (message_count / headers_per_page) + 1); X X PutLine1(4,0,"\nCurrent mailfile is %s.\n\n", cur_folder); X X i = header_page*headers_per_page; /* starting header */ X X if ((j = i + (headers_per_page-1)) >= message_count) X j = message_count-1; X X Write_to_screen( X"Num From Subject Lines Offset\n\r\n\r",0); X X while (i <= j) { X sprintf(buffer, X "%3d %-16.16s %-40.40s %4d %d\n\r", X i+1, X headers[i]->from, X headers[i]->subject, X headers[i]->lines, X headers[i]->offset); X Write_to_screen(buffer, 0); X i++; X } X X Raw(ON); X X PutLine0(LINES,0,"Press any key to return."); X (void) ReadCh(); X} X X Xdebug_message() X{ X /**** Spit out the current message record. Include EVERYTHING X in the record structure. **/ X X char buffer[SLEN]; X register struct header_rec *current_header = headers[current-1]; X X ClearScreen(); X Raw(OFF); X X Write_to_screen("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r", 1, X current); X X Write_to_screen("Lines : %-5d\t\t\tStatus: A C D E F N O P T U V\n\r", 1, X current_header->lines); X Write_to_screen(" \t\t\t c o e x o e l r a r i\n\r", 0); X Write_to_screen(" \t\t\t t n l p r w d i g g s\n\r", 0); X Write_to_screen(" \t\t\t n f d d m v d n i\n\r", 0); X X sprintf(buffer, X "\n\rOffset: %ld\t\t\t %d %d %d %d %d", X current_header->offset, X (current_header->status & ACTION) != 0, X (current_header->status & CONFIDENTIAL) != 0, X (current_header->status & DELETED) != 0, X (current_header->status & EXPIRED) != 0, X (current_header->status & FORM_LETTER) != 0); X sprintf(buffer + strlen(buffer), X " %d %d %d %d %d %d\n", X (current_header->status & NEW) != 0, X (current_header->status & UNREAD) != 0, X (current_header->status & PRIVATE) != 0, X (current_header->status & TAGGED) != 0, X (current_header->status & URGENT) != 0, X (current_header->status & VISIBLE) != 0); X X Write_to_screen(buffer, 0); X X sprintf(buffer, "\n\rReceived on: %d/%d/%d at %d:%02d\n\r", X current_header->received.month+1, X current_header->received.day, X current_header->received.year, X current_header->received.hour, X current_header->received.minute); X Write_to_screen(buffer, 0); X X sprintf(buffer, "Message sent on: %s, %s %s, %s at %s\n\r", X current_header->dayname, X current_header->month, X current_header->day, X current_header->year, X current_header->time); X Write_to_screen(buffer, 0); X X Write_to_screen("From: %s\n\rSubject: %s", 2, X current_header->from, X current_header->subject); X X Write_to_screen("\n\rPrimary Recipient: %s\nInternal Index Reference Number = %d\n\r", 2, X current_header->to, X current_header->index_number); X X Write_to_screen("Message-ID: %s\n\r", 1, X strlen(current_header->messageid) > 0 ? X current_header->messageid : "<none>"); X X Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status); X X Raw(ON); X X PutLine0(LINES,0,"Please Press any key to return."); X (void) ReadCh(); X} X Xdo_check_only(to_whom) Xchar *to_whom; X { X char buffer[VERY_LONG_STRING]; X X dprint(3, (debugfile, "Check-only: checking \n-> \"%s\"\n", X format_long(to_whom, 3))); X (void) build_address(strip_commas(to_whom), buffer); X printf("Expands to: %s", format_long(buffer, strlen("Expands to: "))); X } SHAR_EOF chmod 0444 src/elm.c || echo "restore of src/elm.c fails" echo "x - extracting src/encode.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/encode.c && X Xstatic char rcsid[] = "@(#)$Id: encode.c,v 4.1 90/04/28 22:42:57 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: encode.c,v $ X * Revision 4.1 90/04/28 22:42:57 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This is a heavily mangled version of the 'cypher' program written by X person or persons unknown. X X**/ X X#include "headers.h" X X#define RS 94 X#define RN 4 X#define RMASK 0x7fff /* use only 15 bits */ X Xstatic char r[RS][RN]; /* rotors */ Xstatic char ir[RS][RN]; /* inverse rotors */ Xstatic char h[RS]; /* half rotor */ Xstatic char s[RS]; /* shuffle vector */ Xstatic int p[RN]; /* rotor indices */ X Xstatic char the_key[SLEN]; /* unencrypted key */ Xstatic char *encrypted_key; /* encrypted key */ X Xchar *strncpy(), *strcpy(); Xunsigned long sleep(); X X#define DECRYPT_PROMPT "Enter decryption key: " X#define FIRST_ENC_PROMPT "Enter encryption key: " X#define SECOND_ENC_PROMPT "Please enter it again: " X#define PROMPT_LINE LINES-1 X Xgetkey(send) Xint send; X{ X /** this routine prompts for and returns an encode/decode X key for use in the rest of the program. **/ X X char buffer[2][NLEN]; X X while (1) { X PutLine0(PROMPT_LINE, 0, (send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT)); X CleartoEOLN(); X optionally_enter(buffer[0], PROMPT_LINE, X strlen(send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT), FALSE, TRUE); X if (send) { X PutLine0(PROMPT_LINE, 0, SECOND_ENC_PROMPT); X CleartoEOLN(); X optionally_enter(buffer[1], PROMPT_LINE, strlen(SECOND_ENC_PROMPT), X FALSE, TRUE); X if(strcmp(buffer[0], buffer[1]) != 0) { X error("Your keys were not the same!"); X sleep(1); X clear_error(); X continue; X } X } X break; X } X strcpy(the_key, buffer[0]); /* save unencrypted key */ X makekey(buffer[0]); X X setup(); /** initialize the rotors etc. **/ X X ClearLine(PROMPT_LINE); X clear_error(); X} X Xget_key_no_prompt() X{ X /** This performs the same action as get_key, but assumes that X the current value of 'the_key' is acceptable. This is used X when a message is encrypted twice... **/ X X char buffer[SLEN]; X X strcpy(buffer, the_key); X X makekey( buffer ); X X setup(); X} X Xencode(line) Xchar *line; X{ X /** encrypt or decrypt the specified line. Uses the previously X entered key... **/ X X register int i, j, ph = 0; X X for (; *line; line++) { X i = (int) *line; X X if ( (i >= ' ') && (i < '~') ) { X i -= ' '; X X for ( j = 0; j < RN; j++ ) /* rotor forwards */ X i = r[(i+p[j])%RS][j]; X X i = ((h[(i+ph)%RS])-ph+RS)%RS; /* half rotor */ X X for ( j-- ; j >= 0; j-- ) /* rotor backwards */ X i = (ir[i][j]+RS-p[j])%RS; X X j = 0; /* rotate rotors */ X p[0]++; X while ( p[j] == RS ) { X p[j] = 0; X j++; X if ( j == RN ) break; X p[j]++; X } X X if ( ++ph == RS ) X ph = 0; X X i += ' '; X } X X *line = (char) i; /* replace with altered one */ X } X} X X Xmakekey( rkey) Xchar *rkey; X{ X /** encrypt the key using the system routine 'crypt' **/ X X char key[9], salt[2], *crypt(); X X strncpy( key, rkey, 8); X key[8] = '\0'; X salt[0] = key[0]; X salt[1] = key[1]; X#ifdef CRYPT X encrypted_key = crypt( key, salt); X#else X encrypted_key = key; X#endif X} X X/* X * shuffle rotors. X * shuffle each of the rotors indiscriminately. shuffle the half-rotor X * using a special obvious and not very tricky algorithm which is not as X * sophisticated as the one in crypt(1) and Oh God, I'm so depressed. X * After all this is done build the inverses of the rotors. X */ X Xsetup() X{ X register long i, j, k, temp; X long seed; X X for ( j = 0; j < RN; j++ ) { X p[j] = 0; X for ( i = 0; i < RS; i++ ) X r[i][j] = i; X } X X seed = 123; X for ( i = 0; i < 13; i++) /* now personalize the seed */ X seed = (seed*encrypted_key[i] + i) & RMASK; X X for ( i = 0; i < RS; i++ ) /* initialize shuffle vector */ X h[i] = s[i] = i; X X for ( i = 0; i < RS; i++) { /* shuffle the vector */ X seed = (5 * seed + encrypted_key[i%13]) & RMASK;; X k = ((seed % 65521) & RMASK) % RS; X temp = s[k]; X s[k] = s[i]; X s[i] = temp; X } X X for ( i = 0; i < RS; i += 2 ) { /* scramble the half-rotor */ X temp = h[s[i]]; /* swap rotor elements ONCE */ X h[s[i]] = h[s[i+1]]; X h[s[i+1]] = temp; X } X X for ( j = 0; j < RN; j++) { /* select a rotor */ X X for ( i = 0; i < RS; i++) { /* shuffle the vector */ X seed = (5 * seed + encrypted_key[i%13]) & RMASK;; X k = ((seed % 65521) & RMASK) % RS; X temp = r[i][j]; X r[i][j] = r[k][j]; X r[k][j] = temp; X } X X for ( i = 0; i < RS; i++) /* create inverse rotors */ X ir[r[i][j]][j] = i; X } X} SHAR_EOF chmod 0444 src/encode.c || echo "restore of src/encode.c fails" echo "x - extracting src/errno.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/errno.c && X Xstatic char rcsid[] = "@(#)$Id: errno.c,v 4.1 90/04/28 22:42:58 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: errno.c,v $ X * Revision 4.1 90/04/28 22:42:58 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This routine maps error numbers to error names and error messages. X These are all directly ripped out of the include file errno.h, and X are HOPEFULLY standardized across the different breeds of Unix!! X X If (alas) yours are different, you should be able to use awk to X mangle your errno.h file quite simply... X X**/ X X#include "headers.h" X Xchar *err_name[] = { X/* 0 */ "NOERROR", "No error status currently", X/* 1 */ "EPERM", "Not super-user", X/* 2 */ "ENOENT", "No such file or directory", X/* 3 */ "ESRCH", "No such process", X/* 4 */ "EINTR", "Interrupted system call", X/* 5 */ "EIO", "I/O error", X/* 6 */ "ENXIO", "No such device or address", X/* 7 */ "E2BIG", "Arg list too long", X/* 8 */ "ENOEXEC", "Exec format error", X/* 9 */ "EBADF", "Bad file number", X/* 10 */ "ECHILD", "No children", X/* 11 */ "EAGAIN", "No more processes", X/* 12 */ "ENOMEM", "Not enough core", X/* 13 */ "EACCES", "Permission denied", X/* 14 */ "EFAULT", "Bad address", X/* 15 */ "ENOTBLK", "Block device required", X/* 16 */ "EBUSY", "Mount device busy", X/* 17 */ "EEXIST", "File exists", X/* 18 */ "EXDEV", "Cross-device link", X/* 19 */ "ENODEV", "No such device", X/* 20 */ "ENOTDIR", "Not a directory", X/* 21 */ "EISDIR", "Is a directory", X/* 22 */ "EINVAL", "Invalid argument", X/* 23 */ "ENFILE", "File table overflow", X/* 24 */ "EMFILE", "Too many open files", X/* 25 */ "ENOTTY", "Not a typewriter", X/* 26 */ "ETXTBSY", "Text file busy", X/* 27 */ "EFBIG", "File too large", X/* 28 */ "ENOSPC", "No space left on device", X/* 29 */ "ESPIPE", "Illegal seek", X/* 30 */ "EROFS", "Read only file system", X/* 31 */ "EMLINK", "Too many links", X/* 32 */ "EPIPE", "Broken pipe", X/* 33 */ "EDOM", "Math arg out of domain of func", X/* 34 */ "ERANGE", "Math result not representable", X/* 35 */ "ENOMSG", "No message of desired type", X/* 36 */ "EIDRM", "Identifier removed" X }; X Xchar *strcpy(); X Xchar *error_name(errnumber) Xint errnumber; X{ X static char buffer[50]; X X if (errnumber < 0 || errnumber > 36) X sprintf(buffer,"ERR-UNKNOWN (%d)", errnumber); X else X strcpy(buffer, err_name[2*errnumber]); X X return( (char *) buffer); X} X Xchar *error_description(errnumber) Xint errnumber; X{ X static char buffer[50]; X X if (errnumber < 0 || errnumber > 36) X sprintf(buffer,"Unknown error - %d - No description", errnumber); X else X strcpy(buffer, err_name[2*errnumber + 1]); X X return ( (char *) buffer); X} SHAR_EOF chmod 0444 src/errno.c || echo "restore of src/errno.c fails" echo "x - extracting src/exitprog.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/exitprog.c && X Xstatic char rcsid[] = "@(#)$Id: exitprog.c,v 4.1 90/04/28 22:43:00 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: exitprog.c,v $ X * Revision 4.1 90/04/28 22:43:00 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X#include "headers.h" X Xint Xexit_prog() X{ X /** Exit, abandoning all changes to the mailbox (if there were X any, and if the user say's it's ok) X **/ X X char buffer[SLEN], answer; X register int i, changes; X X dprint(1, (debugfile, "\n\n-- exiting --\n\n")); X X /* Determine if any messages are scheduled for deletion, or if X * any message has changed status X */ X for (changes = 0, i = 0; i < message_count; i++) X if (ison(headers[i]->status, DELETED) || headers[i]->status_chgd) X changes++; X X if (changes) { X /* YES or NO on softkeys */ X if (hp_softkeys) { X define_softkeys(YESNO); X softkeys_on(); X } X sprintf(buffer,"Abandon change%s to mailbox? (y/n) ",plural(changes)); X answer = want_to(buffer, 'n'); X X if(answer != 'y') return -1; X } X X fflush(stdout); X return leave(0); X} SHAR_EOF chmod 0444 src/exitprog.c || echo "restore of src/exitprog.c fails" echo "x - extracting src/expires.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/expires.c && X Xstatic char rcsid[] = "@(#)$Id: expires.c,v 4.1 90/04/28 22:43:01 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: expires.c,v $ X * Revision 4.1 90/04/28 22:43:01 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This routine is written to deal with the Expires: header on the X individual mail coming in. What it does is to look at the date, X compare it to todays date, then set the EXPIRED flag on the X current message if it is true... X**/ X X#include "headers.h" X X#ifdef I_TIME X# include <time.h> X#endif X#ifdef I_SYSTIME X# include <sys/time.h> X#endif X X#include <ctype.h> X X#ifdef BSD X#undef toupper X#undef tolower X#endif X Xprocess_expiration_date(date, message_status) Xchar *date; Xint *message_status; X{ X struct tm *timestruct; X long thetime; X char word1[WLEN], word2[WLEN], word3[WLEN], word4[WLEN], word5[WLEN]; X int month = 0, day = 0, year = 0, hour = 0, minute = 0; X#ifndef _POSIX_SOURCE X struct tm *localtime(); X long time(); X#endif X X /** first step is to break down the date given into MM DD YY HH MM X format: The possible formats for this field are, by example: X X (1) Mon, Jun 11, 87 X (2) Mon, 11 Jun 87 X (3) Jun 11, 87 X (4) 11 Jun 87 X (5) 11/06/87 <- ambiguous - will be ignored!! X (6) 8711061248GMT X (7) Mon, Jun 11, 87 12:48:35 GMT X X The reason #5 is considered ambiguous will be made clear SHAR_EOF echo "End of part 14" echo "File src/expires.c is continued in part 15" echo "15" > s2_seq_.tmp exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.