syd@dsinc.UUCP (Syd Weinstein) (12/12/88)
---- Cut Here and unpack ---- #!/bin/sh # this is part 11 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/edit.c continued # CurArch=11 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/edit.c" sed 's/^X//' << 'SHAR_EOF' >> src/edit.c X Raw(ON); X sleep(2); X return(0); X } X X Raw(ON); X X if (mbox_specified == 0) { /* uh oh... now the toughie... */ X X#ifdef NOSU X sprintf(temp_infile, "%s%s.temp", temp_lock_dir, username); X#else X sprintf(temp_infile, "%s%s.temp", mailhome, username); X#endif X unlink(temp_infile); /* remove it if it's there... */ X X if (bytes(infile) != mailfile_size) { X X /* SIGH. We've received mail since we invoked the editor X on the mailbox. We'll have to do some strange stuff to X remedy the problem... */ X X PutLine0(LINES, 0, "Warning: new mail received..."); X CleartoEOLN(); X X if ((temp_mailbox = fopen(filename, "a")) == NULL) { X dprint(1, (debugfile, X "Attempt to open \"%s\" to append failed in %s\n", X filename, "edit_mailbox")); X set_error("Couldn't reopen tempfile. Edit LOST!"); X return(1); X } X /** Now let's lock the mailbox up and stream the new stuff X into the temp file... **/ X X chown( filename, userid, groupid); X X lock(OUTGOING); X if ((real_mailbox = fopen(infile, "r")) == NULL) { X dprint(1, (debugfile, X "Attempt to open \"%s\" for reading new mail failed in %s\n", X infile, "edit_mailbox")); X sprintf(buffer, "Couldn't open %s for reading! Edit LOST!", X infile); X set_error(buffer); X unlock(); X return(1); X } X if (fseek(real_mailbox, mailfile_size, 0) == -1) { X dprint(1, (debugfile, X "Couldn't seek to end of infile (offset %ld) (%s)\n", X mailfile_size, "edit_mailbox")); X set_error("Couldn't seek to end of mailbox. Edit LOST!"); X unlock(); X return(1); X } X X /** Now we can finally stream the new mail into the tempfile **/ X X while (fgets(buffer, LONG_SLEN, real_mailbox) != NULL) X fprintf(temp_mailbox, "%s", buffer); X X fclose(real_mailbox); X fclose(temp_mailbox); X } X else X lock(OUTGOING); /* create a lock file if we're replacing mailbox */ X X /** link to the temporary mailbox in the mailhome directory... **/ X X if (link(filename, temp_infile) != 0) X if (errno == EXDEV || errno == EEXIST) { /* attempt to link across file systems */ X if (copy(filename, temp_infile) != 0) { X error("Couldn't copy temp file to mailbox!"); X unlock(); /* ciao!*/ X emergency_exit(); X } X } X else { X Write_to_screen("\n\rCouldn't link %s to mailfile %s...\n\r",2, X filename, temp_infile); X Write_to_screen("** %s - %s **\n\r", 2, X error_name(errno), error_description(errno)); X emergency_exit(); X } X X /*** G U L P ... let's remove the incoming mail file... ***/ X X if (unlink(infile) != 0) { X if (copy(temp_infile, infile) != 0) { X error("Couldn't copy temp file to mailbox!"); X unlock(); /* ciao!*/ X emergency_exit(); X } X } X else { X /** and quickly now... **/ X X if (link(temp_infile, infile) != 0) { X Write_to_screen( X "\n\rCouldn't internally link %s to mailfile %s...\n\r", X 2, temp_infile, infile); X Write_to_screen( X "\n\rYou'll need to check out %s for your mail...\n\r", X 1, temp_infile); X Write_to_screen("** %s - %s **\n\r", 2, X error_name(errno), error_description(errno)); X emergency_exit(); X } X } X X /** And let's remove the lock file! We're DONE!!! **/ X X unlock(); X unlink(temp_infile); /* remove the temp file too */ X unlink(filename); /* remove the temp file too */ X error("edit changes incorporated into new mail..."); X } X else X error("Resynchronizing with new version of mailbox..."); X X sleep(2); X newmbox(3, TRUE, TRUE); X mailfile_size = bytes(infile); X showscreen(); X X current = 1; /* don't leave the user hanging! */ X X /** finally restore the permissions... **/ X X if (loaded_stat_buffer) { /* if not, it's junk! */ X chown(infile, stat_buffer.st_uid, stat_buffer.st_gid); X chmod(infile, stat_buffer.st_mode); X } X X return(1); X} X X#endif SHAR_EOF echo "File src/edit.c is complete" chmod 0444 src/edit.c || echo "restore of src/edit.c fails" echo "x - extracting src/editmsg.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/editmsg.c && X Xstatic char rcsid[] = "@(#)$Id: editmsg.c,v 2.1 88/09/15 20:28:00 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * Copyright (c) 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Syd Weinstein, Elm Corrdinator X * syd@dsinc.UUCP dsinc!syd X * X ******************************************************************************* X * $Log: editmsg.c,v $ X * Revision 2.1 88/09/15 20:28:00 syd X * checked in with -k by syd at 88.09.15.20.28.00. X * X * 88/08/27 ssw X * add deluth patches X * X * Revision 2.1 88/07/21 09:58:15 edc X * Final hacks and cleanup to the 2.1 alpha test release. X * X * Revision 2.0 88/06/27 17:24:58 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** This contains routines to do with starting up and using an editor (or two) X from within Elm. This stuff used to be in mailmsg2.c... X**/ X X#include "headers.h" X#include <errno.h> X#include <setjmp.h> X#include <signal.h> X#include <ctype.h> X X#ifdef BSD X#undef tolower X#endif X Xextern int errno; X Xchar *error_name(), *error_description(), *strcpy(), *format_long(); Xunsigned long sleep(); X Xint Xedit_the_message(filename, already_has_text) Xchar *filename; Xint already_has_text; X{ X /** Invoke the users editor on the filename. Return when done. X If 'already has text' then we can't use the no-editor option X and must use 'alternative editor' (e.g. $EDITOR or default_editor) X instead... **/ X X char buffer[SLEN]; X register int stat, return_value = 0; X int old_raw; X X buffer[0] = '\0'; X X if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) { X if (already_has_text) X sprintf(buffer, "%s %s", alternative_editor, filename); X else X return(no_editor_edit_the_message(filename)); X } X X PutLine0(LINES, 0, "invoking editor..."); fflush(stdout); X if (strlen(buffer) == 0) X sprintf(buffer,"%s %s", editor, filename); X X if( (old_raw = RawState()) == ON) X Raw(OFF); X X chown(filename, userid, groupid); /* file was owned by root! */ X X if (cursor_control) X transmit_functions(OFF); /* function keys are local */ X X if ((stat = system_call(buffer, SH)) != 0) { X dprint(1,(debugfile, X "System call failed with stat %d (edit_the_message)\n", X stat)); X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), X error_description(errno))); X ClearLine(LINES-1); X error1("Can't invoke editor '%s' for composition", editor); X sleep(2); X return_value = 1; X } X X if (cursor_control) X transmit_functions(ON); /* function keys are local */ X X if ( old_raw == ON) X Raw(ON); X X return(return_value); X} X Xextern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], X expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], X subject[SLEN]; X Xint interrupts_while_editing; /* keep track 'o dis stuff */ Xjmp_buf edit_location; /* for getting back from interrupt */ X X#ifdef ALLOW_BCC Xextern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING]; X#endif X Xchar *strip_commas(); Xlong fsize(); X Xint Xno_editor_edit_the_message(filename) Xchar *filename; X{ X /** If the current editor is set to either "builtin" or "none", then X invoke this program instead. As it turns out, this and the X routine above have a pretty incestuous relationship (!)... X **/ X X FILE *edit_fd; X char buffer[SLEN], editor_name[SLEN], buf[SLEN]; X int edit_interrupt(), (*oldint)(), (*oldquit)(); X int old_raw; X X if (( old_raw = RawState()) == ON) X Raw(OFF); X X if ((edit_fd = fopen(filename, "a")) == NULL) { X error2("Couldn't open %s for appending [%s]", filename, X error_name(errno)); X sleep (2); X dprint(1, (debugfile, X "Error encountered trying to open file %s;\n", filename)); X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), X error_description(errno))); X if ( old_raw == ON) X Raw(ON); X return(1); X } X X /** is there already text in this file? **/ X X if (fsize(edit_fd) > 0L) X printf( X "\nPlease continue message, ^D or '.' to end, %cp to list, %c? for help;\n\n", X escape_char, escape_char); X else X printf( X "\nPlease enter message, ^D or '.' to end, or %c? <RETURN> for help;\n\n", X escape_char); X X oldint = signal(SIGINT, edit_interrupt); X oldquit = signal(SIGQUIT, edit_interrupt); X X interrupts_while_editing = 0; X X if (setjmp(edit_location) != 0) { X if (interrupts_while_editing > 1) { X Raw(ON); X X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X X if (edit_fd != NULL) /* insurance... */ X fclose(edit_fd); X return(1); X } X goto more_input; /* read input again, please! */ X } X Xraw_input : Raw(ON); X Xmore_input: buffer[0] = '\0'; X X while (optionally_enter(buffer, -1,-1, FALSE) == 0) { X X interrupts_while_editing = 0; /* reset to zero... */ X X if (strcmp(buffer, ".") == 0) X break; /* '.' is as good as a ^D to us dumb programs :-) */ X if (buffer[0] == escape_char) { X Raw(OFF); X switch (tolower(buffer[1])) { X case '?' : tilde_help(); X printf("(continue)\n"); goto raw_input; X X case TILDE: move_left(buffer, 1); X Raw(ON); goto tilde_input; /*!!*/ X X case 't' : get_with_expansion("\nTo: ", to, expanded_to, buffer); X goto raw_input; X#ifdef ALLOW_BCC X case 'b' : get_with_expansion("\nBcc: ",bcc,expanded_bcc, buffer); X goto raw_input; X#endif X case 'c' : get_with_expansion("\nCc: ", cc, expanded_cc, buffer); X goto raw_input; X case 's' : get_with_expansion("\nSubject: ", subject,NULL,buffer); X goto raw_input; X X case 'h' : get_with_expansion("\nTo: ", to, expanded_to, NULL); X get_with_expansion("Cc: ", cc, expanded_cc, NULL); X#ifdef ALLOW_BCC X get_with_expansion("Bcc: ", bcc,expanded_bcc, NULL); X#endif X get_with_expansion("Subject: ", subject,NULL, NULL); X goto raw_input; X X case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1); X goto raw_input; X case 'e' : if (strlen(emacs_editor) > 0) X if (access(emacs_editor, ACCESS_EXISTS) == 0) { X strcpy(buffer, editor); 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 printf("(continue entering message, ^D or '.' to end)\n"); X goto raw_input; X } X else X printf( X "\n(Can't find Emacs on this system! continue)\n"); X else X printf( X "\n(Don't know where Emacs would be...continue)\n"); X goto raw_input; X X case 'v' : 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 printf("(continue entering message, ^D or '.' to end)\n"); X goto raw_input; X X case 'o' : printf("\nPlease enter the name of the editor : "); X editor_name[0] = '\0'; X optionally_enter(editor_name,-1,-1, FALSE); 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 printf("(continue entering message, ^D or '.' to end)\n"); X goto raw_input; X } X printf("(continue)\n"); X goto raw_input; X X case '<' : putchar('\n'); X if (strlen(buffer) < 3) X (void) printf( X "(you need to use a specific command here. Continue...)\n"); X else { X sprintf(buf, " > %s.%d 2>&1", temp_edit, getpid()); X strcat(buffer, buf); X (void) system_call((char *) buffer+2, SH); X sprintf(buffer, "~r %s.%d", temp_edit, getpid()); X read_in_file(edit_fd, (char *) buffer + 3, 0); X (void) unlink((char *) buffer+3); X } X goto raw_input; X X case '!' : putchar('\n'); X if (strlen(buffer) < 3) X (void) system_call(shell, USER_SHELL); X else X (void) system_call((char *) buffer+2, USER_SHELL); X printf("(continue)\n"); X goto raw_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 putchar('\n'); X read_in_messages(edit_fd, (char *) buffer + 1); X goto raw_input; X X case 'p' : /* print out message so far. Soooo simple! */ X print_message_so_far(edit_fd, filename); X goto raw_input; X X default : printf( X "\n(don't know what %c%c is. Try %c? for help)\n", X escape_char, buffer[1], escape_char); X } X } X else { Xtilde_input: X fprintf(edit_fd, "%s\n", buffer); X printf("\r\n"); X } X buffer[0] = '\0'; X } X X printf("\n<end-of-message>\n\r\n\r"); X X if ( old_raw == ON) X Raw(ON); 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 int old_raw; X X if ( (old_raw = RawState()) == ON) X Raw(OFF); X X printf("\n(Available options at this point are;\n\n"); X printf("\t%c?\tPrint this help menu\n", escape_char); X if (escape_char == TILDE) X printf("\t~~\tAdd line prefixed by a single '~' character\n"); X /* doesn't make sense otherwise... */ X X#ifdef ALLOW_BCC X printf("\ X\t%cb\tChange the addresses in the Blind-carbon-copy list\n", escape_char); X#endif X X printf("\t%cc\tChange the addresses in the Carbon-copy list\n", X escape_char); X printf("\t%ce\tInvoke the Emacs editor on the message, if possible\n", X escape_char); X printf("\t%cf\tadd the specified list of messages, or current\n", X escape_char); X printf("\t%ch\tchange all available headers (to,cc%s,subject)\n", X escape_char, X#ifdef ALLOW_BCC X ",bcc"); X#else X ""); X#endif X printf("\t%cm\tsame as '%cf', but with the current 'prefix'\n", X escape_char, escape_char); X printf("\t%co\tInvoke a user specified editor on the message\n", X escape_char); X printf("\t%cp\tprint out message as typed in so far\n", escape_char); X printf("\t%cr\tRead in the specified file\n", escape_char); X printf("\t%cs\tChange the subject of the message\n", escape_char); X printf("\t%ct\tChange the addresses in the To list\n", X escape_char); X printf("\t%cv\tInvoke the Vi visual editor on the message\n\n", X escape_char); X printf( X "\t%c!\texecute a unix command (or give a shell if no command)\n", X escape_char); X printf( X "\t%c<\texecute a unix command adding the output to the message\n\n", X escape_char); X printf( X "\t. \tby itself on a line (or a control-D) ends the message\n\n"); X X if ( old_raw == ON) X Raw(ON); 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 we added, if any... **/ X X FILE *myfd; X char myfname[SLEN], buffer[LONG_SLEN]; X register int lines = 0; X X while (whitespace(filename[lines])) lines++; X X /** expand any shell variables, '~' or other notation... **/ X X expand_env(myfname, (char *) filename + lines); X X if (strlen(myfname) == 0) { X printf("\n(no filename specified for file read! Continue...)\n"); X return; X } X X if ((myfd = fopen(myfname,"r")) == NULL) { X printf("\n(Couldn't read file '%s'! Continue...)\n", X myfname); X return; X } X X lines = 0; X X while (fgets(buffer, LONG_SLEN, myfd) != NULL) { X lines++; X fputs(buffer, fd); X fflush(stdout); X } X X fclose(myfd); X X if (show_user_filename) X printf("\n(added %d line%s from file %s. Please continue...)\n", X lines, plural(lines), myfname); X else X printf("\n(added %d line%s to message. Please continue...)\n", X lines, plural(lines)); 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[LONG_SLEN]; X X fclose(edit_fd); X X if ((edit_fd = fopen(filename, "r")) == NULL) { X printf("\nMayday! Mayday! Mayday!\n"); X printf("\nPanic: Can't open file for reading! Bail!\n"); X emergency_exit(); X } X X printf("\nTo: %s\n", format_long(to, 4)); X printf("Cc: %s\n", format_long(cc, 4)); X#ifdef ALLOW_BCC X printf("Bcc: %s\n", format_long(bcc, 5)); X#endif X printf("Subject: %s\n\n", subject); X X while (fgets(buffer, LONG_SLEN, edit_fd) != NULL) X printf("%s", buffer); X X fclose(edit_fd); X X if ((edit_fd = fopen(filename, "a")) == NULL) { X printf("Mayday! Mayday! Abandon Ship! Aiiieeeeee\n"); X printf("\nPanic: Can't reopen file for appending!\n"); X emergency_exit(); X } X X printf("\n(continue entering message, please)\n"); 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[LONG_SLEN]; X register int lines = 0, add_prefix=0, mindex; X X add_prefix = (tolower(buffer[0]) == 'm'); X X if (strlen(++buffer) == 0) { X if (mail_only) { X printf("(you need to specify what message(s) to include)\n"); X return; X } X /** else give us the current message number as a default **/ X } X X if (mail_only || ! isdigit(buffer[0])) X sprintf(local_buffer, "%s %s", readmsg, buffer); X else { X mindex = atoi(buffer); /* map requested # to real # */ X sprintf(local_buffer, "%s %d", readmsg, X header_table[mindex-1].index_number); X } X X if ((myfd = popen(local_buffer, "r")) == NULL) { X printf("(can't get to 'readmsg' command. Sorry...)\n"); X return; X } X X dprint(5, (debugfile, "** readmsg call: \"%s\" **\n", local_buffer)); X X while (fgets(local_buffer, LONG_SLEN, myfd) != NULL) { X 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 printf("(Couldn't add the requested message. Continue)\n"); X else X printf("(added %d line%s to message... Please continue)\n", X lines, plural(lines)); 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 char mybuffer[VERY_LONG_STRING]; X int old_raw; X X if ( (old_raw = RawState()) == OFF) X Raw(ON); X X printf(prompt); 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 strcpy(mybuffer, buffer); X X optionally_enter(buffer, -1, -1, TRUE); /* already data! */ X X if ( old_raw == OFF) X Raw(OFF); X X putchar('\n'); X X /** if it's changed and we're supposed to expand addresses... **/ X X if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL) X if (build_address(strip_commas(buffer), expanded_buffer)) X printf("%s%s\n\r", prompt, expanded_buffer); 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 printf("(Interrupt. One more to cancel this letter...)\n\r"); X X longjmp(edit_location, 1); /* get back */ X} SHAR_EOF 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 2.1.1.2 88/09/23 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * This file and all associated files and documentation: X * (C) Copyright 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Syd Weinstein, Elm Corrdinator X * syd@dsinc.UUCP dsinc!syd X * X ******************************************************************************* X * $Log: elm.c,v $ X * Revision 2.1 88/09/15 20:28:04 syd X * checked in with -k by syd at 88.09.15.20.28.04. X * X * 88/09/01 Rob Bernardo <gatech!pbhyf.PacBell.COM!rob> X * 1. It allows the user to use the -z flags and -f [filename] flag X * 2. Puts elm in raw mode earlier on than before so that any commands X * 3. forward a message without editing it, fix redraw after no edit X * X * 88/08/27 ssw X * add deluth patches X * X * 88/08/27 various X * changes for j,k commands X * X * Revision 2.1 88/07/21 09:58:17 edc X * Final hacks and cleanup to the 2.1 alpha test release. X * X * Revision 2.0 88/06/27 17:24:59 edc X * The original 2.0 gamma sources as leaked from HP X * 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(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X { X int ch; X char address[SLEN], to_whom[LONG_SLEN]; X int key_offset; /** Position offset within keyboard string **/ X int redraw, /** do we need to rewrite the entire screen? **/ X nuhead, /** or perhaps just the headers section... **/ X nucurr, /** or just the current message pointer... **/ X nufoot; /** clear lines 16 thru bottom and new menu **/ X int i; /** Random counting variable (etc) **/ X int pageon, /** for when we receive new mail... **/ X last_in_mailbox; /** for when we receive new mail too... **/ X long num; /** another variable for fun.. **/ X X parse_arguments(argc, argv, to_whom); X X if (mail_only) { X X initialize(FALSE); X X dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", X format_long(to_whom, 3))); X (void) sendmsg(to_whom, "", "", TRUE, NO, FALSE); X leave(0); X } X X initialize(TRUE); X X ScreenSize(&LINES, &COLUMNS); X X showscreen(); X X /* mailfile_size = bytes(infile); */ /* done in newmbox.c now */ X X while (1) { X redraw = 0; X nuhead = 0; X nufoot = 0; X nucurr = 0; X if ((num = bytes(infile)) != 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_mailbox = message_count; X pageon = header_page; X newmbox(2, FALSE, 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_mailbox, X plural(message_count - last_in_mailbox)); 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()) X redraw++; X else X nufoot++; X break; X X case '$' : resync(); break; X X case ' ' : X case '+' : header_page++; nuhead++; X if (move_when_paged && header_page <= X ((message_count-1) / headers_per_page)) { X current = header_page*headers_per_page + 1; X if (selected) X current = visible_to_index(current)+1; X } X break; X X case '-' : header_page--; nuhead++; X if (move_when_paged && header_page >= 0) { X current = header_page*headers_per_page + 1; X if (selected) X current = visible_to_index(current)+1; X } X break; X X case '=' : if (selected) X current = visible_to_index(1)+1; X else X current = 1; X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case '*' : if (selected) X current = (visible_to_index(selected)+1); X else X current = message_count; X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case '|' : Writechar('|'); X softkeys_off(); X redraw = do_pipe(); X softkeys_on(); break; X X case '!' : Writechar('!'); X softkeys_off(); X redraw = subshell(); X softkeys_on(); break; X X case '%' : get_return(address); X clear_error(); X PutLine1(LINES,(COLUMNS-strlen(address))/2, X "%.78s", address); X break; X X case '/' : if (pattern_match()) { X if (get_page(current)) X nuhead++; X else X nucurr++; X } 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 PutLine0(LINES-3, strlen("Command: "), X "Scan message for calendar entries..."); X scan_calendar(); 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 mailbox"); X if ((file_changed = leave_mbox(FALSE)) != -1) { X define_softkeys(CHANGE); X redraw = newmbox(0, TRUE, TRUE); X /* mailfile_size = bytes(infile); */ X } X else { X file_changed = 0; X sort_mailbox(message_count, FALSE); X } X define_softkeys(MAIN); X break; X X case '^' : X case 'd' : if (message_count < 1) { X error("No mail to delete!"); X fflush(stdin); X } X else { X delete_msg((ch == 'd'), TRUE); X if (resolve_mode) /* move after mail resolved */ X if (current < message_count) { X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please **/ ; X if (current > message_count) X current = i; /* reset - overshot! */ X if (get_page(current)) X nuhead++; X else X nucurr++; X } X } X break; X X case ctrl('D') : if (message_count < 1) { X error("No mail to delete!"); X fflush(stdin); X } X else X meta_match(DELETED); X break; X X#ifdef ALLOW_MAILBOX_EDITING X case 'e' : PutLine0(LINES-3,strlen("Command: "),"Edit mailbox"); X if (current > 0) { X edit_mailbox(); X if (cursor_control) X transmit_functions(ON); /* insurance */ X } X else { X error("Mailbox is empty!"); X fflush(stdin); X } X break; X#else X case 'e' : error( X "mailbox 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 (header_table[current-1].status & FORM_LETTER) { X error("Can't group reply to a Form!!"); X fflush(stdin); X } X else { X PutLine0(LINES-3,COLUMNS-40, X "building addresses..."); 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: "),"Read message"); X fflush(stdout); X i = filter; X filter = FALSE; X redraw = show_msg(current); X if (((redraw == ESCAPE) || ( redraw > ' ')) && X redraw < 127) { X while ((redraw == ESCAPE) || (redraw > ' ')) X redraw = process_showmsg_cmd(redraw); X } X redraw = 1; /* always */ X filter = i; X break; X X case 'J' : if (selected) { X if ((current = next_visible(current)) < 0) X current = visible_to_index(selected)+1; X } X else X current++; X X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case 'j' : if (selected) { X if ((current = next_visible(current)) < 0) X current = visible_to_index(selected)+1; X } X else { X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please **/ ; X if (current > message_count) X current = i; /* reset - overshot! */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case 'K' : if (selected) X current = previous_visible(current); X else X current--; X X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case 'k' : if (selected) X current = previous_visible(current); X else { X i = current; X while ( --current > 0 && X header_table[current-1].status & DELETED) X /* continue searching */ ; X if (current <= 0) current = i;/* reset */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; break; X X case 'l' : PutLine0(LINES-3, strlen("Command: "), X "Limit displayed messages by..."); X if (limit() != 0) { X nuhead++; X update_title(); /* poof! */ X } X else X nufoot++; X redraw++; X break; X X case 'm' : PutLine0(LINES-3, strlen("Command: "), "Mail"); X redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE); X break; X X case ctrl('J'): X case ctrl('M'):PutLine0(LINES-3,strlen("Command: "),"Read Message"); X fflush(stdout); X define_softkeys(READ); X X redraw = show_msg(current); X if (((redraw == ESCAPE) || (redraw > ' ')) && X redraw < 127) { X X while ((redraw == ESCAPE) || (redraw > ' ')) X redraw = process_showmsg_cmd(redraw); X } X redraw = 1; /* always.. */ X (void) get_page(current); X break; X X case 'n' : PutLine0(LINES-3,strlen("Command: "),"Next Message"); X fflush(stdout); X define_softkeys(READ); X X redraw = show_msg(current); X if (((redraw == ESCAPE) || (redraw > ' ')) && X redraw < 127) { X X while ((redraw == ESCAPE) || (redraw > ' ')) X redraw = process_showmsg_cmd(redraw); X } X redraw = 1; /* always.. */ X current += redraw; X if (current > message_count) X current = message_count; X (void) get_page(current); /* rewrites ANYway */ X break; X X case 'o' : PutLine0(LINES-3, strlen("Command: "), "Options"); X options(); 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(infile)) { X error("New Mail! Quit cancelled..."); X fflush(stdin); X if (mbox_specified == 0) unlock(); X } X else X quit(); 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 's' : if (message_count < 1) { X error("No mail to save!"); X fflush(stdin); X } X else { X PutLine0(LINES-3, strlen("Command: "), X "Save Message"); X PutLine0(LINES-3,COLUMNS-40, X "(Use '?' to list your folders)"); X if (save(&redraw, FALSE) && resolve_mode) { X X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please **/ ; X if (current > message_count) X current = i; /* reset - overshot! */ X X if (get_page(current)) X nuhead++; X else X nucurr++; 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(); 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 (current < message_count) { X current++; 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 code, for those people that might want to see what the previous X ** behaviour was, is: X X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please ** / ; X if (current > message_count) X current = i; /* reset - we overshot! * / X**************************************************************************/ X if (get_page(current)) X nuhead++; X else X nucurr++; 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 ctrl('Q') : X case '\177' : X case 'x' : PutLine0(LINES-3, strlen("Command: "), "Exit"); X fflush(stdout); leave(); 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]) { X if (selected) X current = previous_visible(current); X else { X i = current; X while ( --current > 0 && X header_table[current-1].status & DELETED) X /* continue searching */ ; X if (current <= 0) current = i;/* reset */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; X } X else if (ch == down[key_offset]) { X if (selected) { X if ((current = next_visible(current)) < 0) X current = visible_to_index(selected)+1; X } X else { X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please **/ ; X if (current > message_count) X current = i; /* reset - overshot! */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; X } X else if (hp_terminal) { X X switch (ch) { X case 'U' : /* <NEXT> */ X header_page++; X nuhead++; X if (move_when_paged && header_page X <= (message_count / headers_per_page)) { X current = header_page*headers_per_page + 1; X if (selected) X current = visible_to_index(current)+1; X } X break; X X case 'V' : /* <PREV> */ X header_page--; X nuhead++; X if (move_when_paged && header_page >= 0) { X current = header_page*headers_per_page + 1; X if (selected) X current = visible_to_index(current)+1; X } X break; X X case 'h' : X case 'H' : /* <HOME UP> */ X if (selected) X current = visible_to_index(1)+1; X else X current = 1; X if (get_page(current)) X nuhead++; X else X nucurr++; X break; X X case 'F' : /* <HOME DOWN> */ X if (selected) X current = visible_to_index(selected)+1; X else X current = message_count; X if (get_page(current)) X nuhead++; X else X nucurr++; X break; X X /** let's continue, what the heck... **/ X X case 'A' : /* <UP> */ X case 'D' : /* <BACKTAB> */ X case 'i' : /* <LEFT> */ X if (selected) X current = previous_visible(current); X else { X i = current; X while ( --current > 0 && X header_table[current-1].status & DELETED) X /* continue searching */ ; X if (current <= 0) current = i;/* reset */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; X break; X X case 'B' : /* <UP> */ X case 'I' : /* <BACKTAB> */ X case 'C' : /* <LEFT> */ X if (selected) { X if ((current = next_visible(current)) < 0) X current = visible_to_index(selected)+1; X } X else { X i = current; X while (++current <= message_count && X (header_table[current-1].status & DELETED)) X /** continue moving forward, please **/ ; X if (current > message_count) X current = i; /* reset - overshot! */ X } X if (get_page(current)) X nuhead++; X else X nucurr++; X break; X X default: PutLine2(LINES-3, strlen("Command: "), X "%c%c", ESCAPE, ch); X } X } X else /* false hit - output */ X PutLine2(LINES-3, strlen("Command: "), X "%c%c", ESCAPE, ch); X break; 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 current = read_number(ch); X if (selected) { X if ((current = visible_to_index(current)+1) > X message_count) X goto too_big; X } X if (get_page(current)) X nuhead++; X else X nucurr++; X } X else { X error("Unknown command: Use '?' for commands"); X fflush(stdin); X } X } X X if (redraw) X showscreen(); X X if (current < 1) { X if (message_count > 0) { X error("already at message #1!"); X fflush(stdin); X if (selected) X current = compute_visible(0); /* get to #0 */ X else X current = 1; X } X else if (current < 0) { X error("No messages to read!"); X fflush(stdin); X current = 0; X } X } X else if (current > message_count) { X if (message_count > 0) { Xtoo_big: X if (selected) { X error2("only %d message%s selected!", selected, X plural(selected)); X fflush(stdin); X current = compute_visible(selected); X } X else { X error2("only %d message%s!", message_count, X plural(message_count)); X dprint(8, (debugfile,"[user selected %d, but only %d msgs]\n", X current, message_count)); X fflush(stdin); X current = message_count; X } X } X else { X error("No messages to read!"); X fflush(stdin); X current = 0; X } X } X else if (selected && (i=visible_to_index(selected)) > message_count) { X error2("only %d message%s selected!", selected, plural(selected)); X fflush(stdin); X current = i+1; /* FIXED! Phew! */ X } X X if (nuhead) X show_headers(); X else if (nucurr) 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 } 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", infile); 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\n",0); X X while (i <= j) { X sprintf(buffer, X "%3d %-16.16s %-40.40s %4d %d\n", X i+1, X header_table[i].from, X header_table[i].subject, X header_table[i].lines, X header_table[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 X ClearScreen(); X Raw(OFF); X X Write_to_screen("\t\t\t----- Message %d -----\n\n\n\n", 1, X current); X X Write_to_screen("Lines : %-5d\t\t\tStatus: A C D E F N P T U V\n", 1, X header_table[current-1].lines); X Write_to_screen(" \t\t\t c o e x o e r a r i\n", 0); X Write_to_screen(" \t\t\t t n l p r w i g g s\n", 0); X Write_to_screen(" \t\t\t n f d d m v d n i\n", 0); X X sprintf(buffer, X "\nOffset: %ld\t\t\t %d %d %d %d %d %d %d %d %d %d\n", X header_table[current-1].offset, X (header_table[current-1].status & ACTION) != 0, X (header_table[current-1].status & CONFIDENTIAL) != 0, X (header_table[current-1].status & DELETED) != 0, X (header_table[current-1].status & EXPIRED) != 0, X (header_table[current-1].status & FORM_LETTER) != 0, X (header_table[current-1].status & NEW) != 0, X (header_table[current-1].status & PRIVATE) != 0, X (header_table[current-1].status & TAGGED) != 0, X (header_table[current-1].status & URGENT) != 0, SHAR_EOF echo "End of part 11" echo "File src/elm.c is continued in part 12" echo "12" > s2_seq_.tmp exit 0 -- ===================================================================== Sydney S. Weinstein, CDP, CCP Elm Coordinator Datacomp Systems, Inc. Voice: (215) 947-9900 {allegra,bellcore,bpa,vu-vlsi}!dsinc!syd FAX: (215) 938-0235