rsalz@uunet.uu.net (Rich Salz) (04/13/89)
Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein) Posting-number: Volume 18, Issue 94 Archive-name: elm2.2/part15 #!/bin/sh # this is part 15 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/forms.c continued # CurArch=15 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/forms.c" sed 's/^X//' << 'SHAR_EOF' >> src/forms.c X} X Xint Xmail_filled_in_form(address, subject) Xchar *address, *subject; X{ X /** This is the interesting routine. This one will read the X message and prompt the user, line by line, for each of X the fields...returns non-zero if it succeeds X **/ X X FILE *fd; X register int lines = 0, count; X char buffer[SLEN], *ptr; X X dprint(4, (debugfile, X "replying to form with;\n\taddress=%s and\n\t subject=%s\n", X address, subject)); X X if (fseek(mailfile, headers[current-1]->offset, 0) == -1) { X dprint(1, (debugfile, X "Error: seek %ld resulted in errno %s (%s)\n", X headers[current-1]->offset, error_name(errno), X "mail_filled_in_form")); X error2("ELM [seek] couldn't read %d bytes into file (%s).", X headers[current-1]->offset, error_name(errno)); X return(0); X } X X /* now we can fly along and get to the message body... */ X X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) { X if (strlen(buffer) == 1) /* <return> only */ X break; X else if (strncmp(buffer,"From ", 5) == 0 && lines++ > 0) { X error("No form in this message!?"); X return(0); X } X } X X if (ptr == NULL) { X error("No form in this message!?"); X return(0); X } X X dprint(6, (debugfile, "- past header of form message -\n")); X X /* at this point we're at the beginning of the body of the message */ X X /* now we can skip to the FORM-IMAGE section by reading through a X line with a triple asterisk... */ X X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) { X if (strcmp(buffer, "***\n") == 0) X break; /* we GOT it! It's a miracle! */ X else if (strncmp(buffer, "From ",5) == 0) { X error("Badly constructed form. Can't reply!"); X return(0); X } X } X X if (ptr == NULL) { X error("Badly constructed form. Can't reply!"); X return(0); X } X X dprint(6, (debugfile, "- skipped the non-forms-image stuff -\n")); X X /* one last thing - let's open the tempfile for output... */ X X sprintf(buffer, "%s%d", temp_form_file, getpid()); X X dprint(2, (debugfile,"-- forms sending using file %s --\n", buffer)); X X if ((fd = fopen(buffer,"w")) == NULL) { X error2("Can't open \"%s\" as output file! (%s).", buffer, X error_name(errno)); X dprint(1, (debugfile, X "** Error %s encountered trying to open temp file %s;\n", X error_name(errno), buffer)); X return(0); X } X X /* NOW we're ready to read the form image in and start prompting... */ X X Raw(OFF); X ClearScreen(); X X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) { X dprint(9, (debugfile, "- read %s", buffer)); X if (strcmp(buffer, "***\n") == 0) /* end of form! */ X break; X X switch ((count = occurances_of(COLON, buffer))) { X case 0 : printf("%s", buffer); /* output line */ X fprintf(fd, "%s", buffer); X break; X case 1 : if (buffer[0] == COLON) { X printf( X"(Enter as many lines as needed, ending with a '.' by itself on a line)\n"); X while (fgets(buffer, SLEN, stdin) != NULL) X no_ret(buffer); X if (strcmp(buffer, ".") == 0) X break; X else X fprintf(fd,"%s\n", buffer); X } X else X prompt_for_entry(buffer, fd); X break; X default: prompt_for_multiple_entries(buffer, fd, count); X } X } X X Raw(ON); X fclose(fd); X X /** let's just mail this off now... **/ X X mail_form(address, subject); X X return(1); X} X Xprompt_for_entry(buffer, fd) Xchar *buffer; XFILE *fd; X{ X /** This is called with an entry of the form "prompt:" and will X display the prompt and save the prompt and the user reply X in the file "fd" X **/ X X char mybuffer[SLEN]; X X no_ret(buffer); X X dprint(7, (debugfile, "prompt-for-entry \"%s\"\n", buffer)); X X printf("%s ", buffer); fflush(stdout); X X fgets(mybuffer, SLEN, stdin); X X fprintf(fd, "%s: %s", buffer, mybuffer); X} X Xprompt_for_multiple_entries(buffer, fd, entries) Xchar *buffer; XFILE *fd; Xint entries; X{ X /** Almost the same as the above routine, this one deals with lines X that have multiple colons on them. It must first figure out how X many spaces to allocate for each field then prompts the user, X line by line, for the entries... X **/ X X char mybuffer[SLEN], prompt[SLEN], spaces[SLEN]; X register int field_size, i, j, offset = 0, extra_tabs = 0; X X dprint(7, (debugfile, X "prompt-for-multiple [%d] -entries \"%s\"\n", entries, X buffer)); X X strcpy(prompt, "No Prompt Available:"); X X while (entries--) { X j=0; X i = chloc((char *) buffer + offset, COLON) + 1; X while (j < i - 1) { X prompt[j] = buffer[j+offset]; X j++; X } X prompt[j] = '\0'; X X field_size = 0; X X while (whitespace(buffer[i+offset])) { X if (buffer[i+offset] == TAB) { X field_size += 8 - (i % 8); X extra_tabs += (8 - (i % 8)) - 1; X } X else X field_size += 1; X i++; X } X X offset += i; X X if (field_size == 0) /* probably last prompt in line... */ X field_size = 80 - (offset + extra_tabs); X X prompt_for_sized_entry(prompt, mybuffer, field_size); X X spaces[0] = ' '; /* always at least ONE trailing space... */ X spaces[1] = '\0'; X X for (j = strlen(mybuffer); j < field_size; j++) X strcat(spaces, " "); X X fprintf(fd, "%s: %s%s", prompt, mybuffer, spaces); X fflush(fd); X } X X fprintf(fd, "\n"); X} X Xprompt_for_sized_entry(prompt, buffer, field_size) Xchar *prompt, *buffer; Xint field_size; X{ X /* This routine prompts for an entry of the size specified. */ X X register int i; X X dprint(7, (debugfile, "prompt-for-sized-entry \"%s\" %d chars\n", X prompt, field_size)); X X printf("%s : ", prompt); X X for (i=0;i<field_size; i++) X putchar('_'); X for (i=0;i<field_size; i++) X putchar(BACKSPACE); X fflush(stdout); X X fgets(buffer, SLEN, stdin); X no_ret(buffer); X X if (strlen(buffer) > field_size) buffer[field_size-1] = '\0'; X} SHAR_EOF echo "File src/forms.c is complete" chmod 0444 src/forms.c || echo "restore of src/forms.c fails" echo "x - extracting src/hdrconfg.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/hdrconfg.c && X Xstatic char rcsid[] = "@(#)$Id: hdrconfg.c,v 2.12 89/03/25 21:46:24 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.12 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@dsinc.UUCP dsinc!elm X * X ******************************************************************************* X * $Log: hdrconfg.c,v $ X * Revision 2.12 89/03/25 21:46:24 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** This file contains the routines necessary to be able to modify X the mail headers of messages on the way off the machine. The X headers currently supported for modification are: X X Subject: X To: X Cc: X Bcc: X Reply-To: X Expires: X Priority: X In-Reply-To: X Action: X X <user defined> X**/ X X#include "headers.h" X X#include <ctype.h> X X#ifdef BSD X#undef toupper X#endif X X/* allow two lines for address-type headers, subject, and in-reply-to */ X/* allow one line for all others - unlikely to exceed one line */ X#define TO_LINE 2 X#define CC_LINE 4 X#define BCC_LINE 6 X#define SUBJECT_LINE 8 X#define REPLY_TO_LINE 10 X#define ACTION_LINE 11 X#define EXPIRES_LINE 12 X#define PRIORITY_LINE 13 X#define IN_REPLY_TO_LINE 14 X#define USER_DEFINED_HDR_LINE 16 X#define INSTRUCT_LINE LINES-5 X#define EXTRA_PROMPT_LINE LINES-3 X#define INPUT_LINE LINES-2 X#define ERROR_LINE LINES-1 X X#define put_to() {ClearLine(TO_LINE+1);\ X PutLine1(TO_LINE,0,"To: %s",expanded_to);CleartoEOLN();} X X#define put_cc() {ClearLine(CC_LINE+1);\ X PutLine1(CC_LINE,0,"Cc: %s", expanded_cc);CleartoEOLN();} X X#define put_bcc() {ClearLine(BCC_LINE+1);\ X PutLine1(BCC_LINE,0,"Bcc: %s",expanded_bcc);CleartoEOLN();} X X#define put_replyto() {PutLine1(REPLY_TO_LINE,0,"Reply-to: %s",reply_to);\ X CleartoEOLN();} X X#define put_subject() {ClearLine(SUBJECT_LINE+1);\ X PutLine1(SUBJECT_LINE,0,"Subject: %s",subject);CleartoEOLN();} X X#define put_action() {PutLine1(ACTION_LINE,0,"Action: %s",action);\ X CleartoEOLN();} X X#define put_expires() {PutLine1(EXPIRES_LINE,0,"Expires: %s",expires);\ X CleartoEOLN();} X X#define put_priority() {PutLine1(PRIORITY_LINE,0,"Priority: %s",priority);\ X CleartoEOLN();} X X#define put_inreplyto() {ClearLine(IN_REPLY_TO_LINE+1);\ X PutLine1(IN_REPLY_TO_LINE,0,"In-reply-to: %s",in_reply_to);CleartoEOLN();} X X#define put_userdefined() {PutLine1(USER_DEFINED_HDR_LINE,0,"%s",\ X user_defined_header);CleartoEOLN();} X X/* these are all defined in the mailmsg file! */ Xextern char subject[SLEN], in_reply_to[SLEN], expires[SLEN], X action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], X cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], X expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN], X bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING]; X Xchar *strip_commas(), *strcpy(); X Xedit_headers() X{ X /** Edit headers. **/ X int c; X X /* Expand address-type headers for main part of display */ X /* (Unexpanded ones are used on the 'edit-line') */ X (void) build_address(strip_commas(to), expanded_to); X (void) build_address(strip_commas(cc), expanded_cc); X (void) build_address(strip_commas(bcc), expanded_bcc); X X display_headers(); X X clearerr(stdin); X X clearerr(stdin); X X while (TRUE) { /* forever */ X PutLine0(INPUT_LINE,0,"Choice: "); X CleartoEOS(); X c = getchar(); X c = toupper(c); X clear_error(); X if (c == EOF) X return(0); X switch (c) { X case RETURN: X case LINE_FEED: X case 'Q' : return(0); X case ctrl('L') : display_headers(); X break; X case 'T' : PutLine0(INPUT_LINE, 0, "To: "); CleartoEOLN(); X if (optionally_enter(to, INPUT_LINE, 4, TRUE, FALSE) == -1) X return(0); X (void) build_address(strip_commas(to), expanded_to); X put_to(); X break; X case 'S' : PutLine0(INPUT_LINE, 0, "Subject: "); CleartoEOLN(); X if (optionally_enter(subject, X INPUT_LINE, 9, FALSE, FALSE) == -1) X return(0); X put_subject(); X break; X case 'B' : PutLine0(INPUT_LINE, 0, "Bcc: "); CleartoEOLN(); X if (optionally_enter(bcc, X INPUT_LINE, 5, TRUE, FALSE) == -1) X return(0); X (void) build_address(strip_commas(bcc), expanded_bcc); X put_bcc(); X break; X case 'C' : PutLine0(INPUT_LINE, 0, "Cc: "); CleartoEOLN(); X if (optionally_enter(cc, INPUT_LINE, 4, TRUE, FALSE) == -1) X return(0); X (void) build_address(strip_commas(cc), expanded_cc); X put_cc(); X break; X case 'R' : PutLine0(INPUT_LINE, 0, "Reply-To: "); CleartoEOLN(); X if(optionally_enter(reply_to, X INPUT_LINE, 10, FALSE, FALSE) == -1) X return(0); X put_replyto(); X break; X X case 'A' : PutLine0(INPUT_LINE, 0, "Action: "); CleartoEOLN(); X if (optionally_enter(action, X INPUT_LINE, 8, FALSE, FALSE) == -1) X return(0); X put_action(); X break; X X case 'P' : PutLine0(INPUT_LINE, 0, "Priority: "); CleartoEOLN(); X if (optionally_enter(priority, X INPUT_LINE, 10, FALSE, FALSE)==-1) X return(0); X put_priority(); X break; X X case 'E' : enter_date(INPUT_LINE, 9, expires); X put_expires(); X break; X X case 'U' : PutLine0(EXTRA_PROMPT_LINE, 0, "User defined header: "); X CleartoEOLN(); X if (optionally_enter(user_defined_header, X INPUT_LINE, 0, FALSE, FALSE)==-1) X return(0); X check_user_header(user_defined_header); X put_userdefined(); X ClearLine(EXTRA_PROMPT_LINE); X break; X X case 'I' : if (strlen(in_reply_to) > 0) { X PutLine0(INPUT_LINE, 0, "In-Reply-To: "); CleartoEOLN(); X if (optionally_enter(in_reply_to, X INPUT_LINE, 13, FALSE, FALSE) == -1) X return(0); X put_inreplyto(); X break; X } X /** else fall through as an error **/ X default : Centerline(ERROR_LINE, "Unknown header being specified!"); X } X } X} X Xdisplay_headers() X{ X ClearScreen(); X X Centerline(0,"Message Header Edit Screen"); X X put_to(); X put_cc(); X put_bcc(); X put_subject(); X put_replyto(); X put_action(); X put_expires(); X put_priority(); X if (strlen(in_reply_to) > 0) put_inreplyto(); X if (strlen(user_defined_header) > 0) put_userdefined(); X X Centerline(INSTRUCT_LINE, X"Choose first letter of existing header, u)ser defined header, or <return>."); X} X Xenter_date(x, y, datebuf) Xint x, y; Xchar *datebuf; X{ X /** Enter the number of days this message is valid for, then X display at (x,y) the actual date of expiration. This X routine relies heavily on the routine 'days_ahead()' in X the file date.c X **/ X X int days; X char numdaysbuf[SLEN]; X X static char prompt[] = X "How many days in the future should this message expire? "; X X PutLine0(INPUT_LINE,0, prompt); X CleartoEOLN(); X *datebuf = *numdaysbuf = '\0'; X X optionally_enter(numdaysbuf, INPUT_LINE, strlen(prompt), FALSE, FALSE); X sscanf(numdaysbuf, "%d", &days); X if (days < 1) X Centerline(ERROR_LINE, "That doesn't make sense!"); X else if (days > 56) X Centerline(ERROR_LINE, X "Expiration date must be within eight weeks of today."); X else { X days_ahead(days, datebuf); X } X} X Xcheck_user_header(header) Xchar *header; X{ X /** check the header format...if bad print error and erase! **/ X X register int i = -1; X X if (strlen(header) == 0) X return; X X if (whitespace(header[0])) { X error ("You can't have leading white space in a header!"); X header[0] = '\0'; X ClearLine(USER_DEFINED_HDR_LINE); X return; X } X X if (header[0] == ':') { X error ("You can't have a colon as the first character!"); X header[0] = '\0'; X ClearLine(USER_DEFINED_HDR_LINE); X return; X } X X while (header[++i] != ':') { X if (header[i] == '\0') { X Centerline(ERROR_LINE, "You need to have a colon ending the field name!"); X header[0] = '\0'; X ClearLine(USER_DEFINED_HDR_LINE); X return; X } X else if (whitespace(header[i])) { X Centerline(ERROR_LINE, "You can't have white space imbedded in the header name!"); X header[0] = '\0'; X ClearLine(USER_DEFINED_HDR_LINE); X return; X } X } X X return; X} SHAR_EOF chmod 0444 src/hdrconfg.c || echo "restore of src/hdrconfg.c fails" echo "x - extracting src/help.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/help.c && X Xstatic char rcsid[] = "@(#)$Id: help.c,v 2.13 89/03/25 21:46:26 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.13 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@dsinc.UUCP dsinc!elm X * X ******************************************************************************* X * $Log: help.c,v $ X * Revision 2.13 89/03/25 21:46:26 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/*** help routine for ELM program X X***/ X X#include <ctype.h> X#include "headers.h" X Xhelp(pager) Xint pager; X{ X /** Process the request for help [section] from the user. X If pager is TRUE, then act a little differently from X if pager is FALSE (index screen) X **/ X X char ch; /* character buffer for input */ X char *s; /* string pointer... */ X int prompt_line, info_line; X X MoveCursor(LINES-4,0); X CleartoEOS(); X X if(pager) { X put_border(); X Centerline(LINES, X "Press keys you want help for, '?' for a list, or '.' to end."); X prompt_line = LINES-3; X } else { X Centerline(LINES-4, "ELM Help System"); X Centerline(LINES-3, X "Press keys you want help for, '?' for a list, or '.' to end."); X prompt_line = LINES-2; X } X info_line = prompt_line + 1; X X PutLine0(prompt_line, 0, "Help on key: "); X X do { X MoveCursor(prompt_line, strlen("Help on key: ")); X ch = ReadCh(); X X if (ch == '.') return(0); /* zero means footer rewrite only */ X X s = "Unknown command. Use '?' for a list of commands."; X X switch (ch) { X X case '?': display_helpfile(pager? PAGER_HELP : MAIN_HELP); X return(1); X X case '$': if(!pager) s = X"$ = Force resynchronization of the current folder. This will purge deleted mail."; X break; X X case '!': s = X "! = Escape to the Unix shell of your choice, or just to enter commands."; X break; X X case '@': if(!pager) s = X "@ = Debug - display a summary of the messages on the header page."; X break; X X case '|': s = X "| = Pipe the current message or tagged messages to the command specified."; X break; X X case '#': if(!pager) s = X "# = Debug - display all information known about current message."; X break; X X case '%': s = X "% = Debug - display the computed return address of the current message."; X break; X X case '*': if(!pager) X s = "* = Go to the last message in the current folder."; X break; X X case '-': if(!pager) s = X"- = Go to the previous page of messages. This is the same as the LEFT arrow."; X break; X X case '=': if(!pager) s = X "'=' = Go to the first message in the current folder."; X break; X X case ' ': if(pager) s = X "<space> = Display next screen of current message (or first screen of next)."; X else s = "<space> = Display the current message."; X break; X X case '+': if(!pager) X s = X "+ = Go to the next page of messages. This is the same as the RIGHT arrow."; X break; X X case '/': if(!pager) X s = "/ = Search for specified pattern in folder."; X break; X X case '<': s = X "< = Scan current message for calendar entries (if enabled)."; X break; X X case '>': s = X "> = Save current message or tagged messages to specified file."; X break; X X case '^': if(!pager) s = X "^ = Toggle the Delete/Undelete status of the current message."; X break; X X case 'a': if(!pager) s = X "a = Enter the alias sub-menu section. Create and display aliases."; X break; X X case 'b': s = X "b = Bounce (remail) a message to someone as if you have never seen it."; X break; X X case 'C': s = X "C = Copy current message or tagged messages to specified file."; X break; X X case 'c': if(!pager) s = X "c = Change folders, leaving the current folder as if 'quitting'."; X break; X X case 'd': s = "d = Mark the current message for future deletion."; X break; X X case ctrl('D') : if(!pager) s = X "^D = Mark for deletion all messages with the specified pattern."; X break; X X case 'e': if(!pager) s = X "e = Invoke the editor on the entire folder, resynchronizing when done."; X break; X X case 'f': s = X "f = Forward the current message to someone, return address is yours."; X break; X X case 'g': s = X "g = Group reply not only to the sender, but to everyone who received msg."; X break; X X case 'h': s = X "h = Display message with all Headers (ignore weedout list)."; X break; X X case 'i': if(pager) s = "i = Return to the index."; X break; X X case 'J': s = "J = Go to the next message."; X break; X X case 'j': s = X "j = Go to the next undeleted message. This is the same as the DOWN arrow."; X break; X X case 'K': s = "K = Go to the previous message."; X break; X X case 'k': s = X"k = Go to the previous undeleted message. This is the same as the UP arrow."; X break; X X case 'l': if(!pager) s = X "l = Limit displayed messages based on the specified criteria."; X break; X X case 'm': s = X "m = Create and send mail to the specified person or persons."; X break; X X case 'n': if(pager) X s = "n = Display the next message."; X else X s = X "n = Display the current message, then move current to next messge."; X break; X X case 'o': if(!pager) s = "o = Go to the options submenu."; X break; X X case 'p': s = X "p = Print the current message or the tagged messages."; X break; X X case 'q': if(pager) s = X "q = Quit the pager and return to the index."; X else s = X "q = Quit the mailer, asking about deletion, saving, etc."; X break; X X case 'r': s = X"r = Reply to the message. This only sends to the originator of the message."; X break; X X case 's': s = X "s = Save current message or tagged messages to specified file."; X break; X X case 't': s = X "t = Tag a message for further operations (or untag if tagged)."; X break; X X case ctrl('T') : if(!pager) s = X "^T = Tag all messages with the specified pattern."; X break; X X case 'u': s = X "u = Undelete - remove the deletion mark on the message."; X break; X X case 'x': s = "x = Exit the mail system quickly."; X break; X X case 'Q': if(!pager) s = X "Q = Quick quit the mailer, save read, leave unread, delete deleted."; X break; X X case '\n': X case '\r': if(pager) X s = X "<return> = Display current message, or (builtin pager only) scroll forward."; X else X s = "<return> = Display the current message."; X break; X X case ctrl('L'): if(!pager) s = "^L = Rewrite the screen."; X break; X X case ctrl('?'): /* DEL */ X case ctrl('Q'): if(!pager) s = "Exit the mail system quickly."; X break; X X default : if (isdigit(ch) && !pager) X s = "<number> = Make specified number the current message."; X } X X ClearLine(info_line); X Centerline(info_line, s); X X } while (ch != '.'); X X /** we'll never actually get here, but that's okay... **/ X X return(0); X} X Xdisplay_helpfile(section) Xint section; X{ X /*** Help me! Read file 'helpfile.<section>' and echo to screen ***/ X X char buffer[SLEN]; X X sprintf(buffer, "%s/%s.%d", helphome, helpfile, section); X return(display_file(buffer)); X} X Xdisplay_file(file) Xchar *file; X{ X /*** Display file to screen ***/ X X FILE *fileptr; X int lines=0; X char buffer[SLEN]; X X if ((fileptr = fopen(file,"r")) == NULL) { X dprint(1, (debugfile, X "Error: Couldn't open file %s (help)\n", file)); X error1("Couldn't open file %s.",buffer); X return(FALSE); X } X X ClearScreen(); X X while (fgets(buffer, SLEN, fileptr) != NULL) { X if (lines > LINES-3) { X PutLine0(LINES,0,"Press <space> to continue, 'q' to return."); X if(ReadCh() == 'q') { X clear_error(); X fclose(fileptr); X return(TRUE); X } X lines = 0; X ClearScreen(); X Write_to_screen("%s\r", 1, buffer); X } X else X Write_to_screen("%s\r", 1, buffer); X X lines += strlen(buffer)/COLUMNS + 1; X } X X PutLine0(LINES,0,"Press any key to return."); X X (void) ReadCh(); X clear_error(); X X fclose(fileptr); X return(TRUE); X} SHAR_EOF chmod 0444 src/help.c || echo "restore of src/help.c fails" echo "x - extracting src/in_utils.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/in_utils.c && X Xstatic char rcsid[] = "@(#)$Id: in_utils.c,v 2.13 89/03/25 21:46:28 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.13 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@dsinc.UUCP dsinc!elm X * X ******************************************************************************* X * $Log: in_utils.c,v $ X * Revision 2.13 89/03/25 21:46:28 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** Mindless I/O routines for ELM X X**/ X X#include "headers.h" X#include <errno.h> X#include <ctype.h> X X#ifdef BSD X# undef tolower X#endif X Xextern int errno; /* system error number */ X Xunsigned alarm(); X X#define isstopchar(c) (c == ' ' || c == '\t' || c == '/') X#define isslash(c) (c == '/') X#define erase_a_char() { Writechar(BACKSPACE); Writechar(' '); \ X Writechar(BACKSPACE); fflush(stdout); } X Xint Xwant_to(question, dflt) Xchar *question, dflt; X{ X /** Ask 'question' on LINES-2 left enough to just leave room for an X answer, returning the answer in lower case. X Echo answer as full "Yes" or "No". 'dflt' is the X default answer if <return> is pressed. (Note: 'dflt' is also what X will be returned if <return> is pressed!) X **/ X register int ch, cols; X X cols = COLUMNS - (strlen(question) + 5 ); /* 5 for "Yes." + 1 */ X X MoveCursor(LINES-3, cols); X CleartoEOLN(); X PutLine3(LINES-3, cols,"%s%c%c", question, dflt, BACKSPACE); X fflush(stdout); X fflush(stdin); X X ch = ReadCh(); X ch = tolower(ch); X X while (!( ch == 'y' || ch == 'n' || ch == '\n' || ch == '\r')) { X ch = ReadCh(); X ch = tolower(ch); X } X if(ch == '\n' || ch == '\r') X ch = dflt; X X if(ch == 'y') X Write_to_screen("Yes.", 0); X else X Write_to_screen("No.", 0); X X return(ch); X} X Xint Xread_number(ch) Xchar ch; X{ X /** Read a number, where 'ch' is the leading digit! **/ X X char buff[NLEN]; X int num; X X buff[0] = ch; X buff[1] = '\0'; X X PutLine0(LINES-3, COLUMNS-40,"Set current message to :"); X if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE, FALSE) == -1) X return(current); X X sscanf(buff,"%d", &num); X return(num); X} X Xint Xoptionally_enter(string, x, y, append_current, passwd) Xchar *string; Xint x,y, append_current, passwd; X{ X /** This will display the string on the screen and allow the user to X either accept it (by pressing RETURN) or alter it according to X what the user types. The various flags are: X string is the buffer to use (with optional initial value) X x,y is the location we're at on the screen (-1,-1 means X that we can't use this info and need to explicitly X use backspace-space-backspace sequences) X append_current means that we have an initial string and that X the cursor should be placed at the END of the line, X not the beginning (the default). X passwd accept non-printing characters and do not echo X entered characters. X X If we hit an interrupt or EOF we'll return non-zero. X **/ X X int ch; X register int ch_count = 0, iindex = 0, X use_cursor_control, escaped = OFF; X X clearerr(stdin); X X if(!passwd) { X if(use_cursor_control = (x >=0 && y >= 0)) X PutLine1(x, y, "%s", string); X else X printf("%s", string); X } X X CleartoEOLN(); X X if (! append_current) { X if (use_cursor_control) X MoveCursor(x,y); X else if(!passwd) X non_destructive_back_up(strlen(string)); X } X else X iindex = strlen(string); X X if (cursor_control) X transmit_functions(OFF); X X /** now we have the screen as we want it and the cursor in the X right place, we can loop around on the input and return the X string as soon as the user presses <RETURN> X **/ X X do { X ch = getchar(); X X if (ch == ctrl('D') || ch == EOF) { /* we've hit EOF */ X if (cursor_control) X transmit_functions(ON); X return(1); X } X X if (ch_count++ == 0) { X if (ch == '\n' || ch == '\r') { X if (cursor_control) X transmit_functions(ON); X return(0); X } X else if (! append_current) { X CleartoEOLN(); X iindex = (append_current? strlen(string) : 0); X } X } X X /* the following is converted from a case statement to X allow the variable characters (backspace, kill_line X and break) to be processed. Case statements in X C require constants as labels, so it failed ... X */ X X if (ch == backspace && X (!escaped || (ch < ' ' || ch > '~' && !passwd))) { X /* This is tricky. Here we are dealing with all situations X * under which a backspace (really whatever erase char is X * set to, not necessarily \b) erases the previous character. X * It will erase unless escaped, because if it's escaped X * it is taken literally. There is one exception to that -- X * if backspace would be rejected (we don't accept non-printing X * characters in non-passwd mode), we accept it here as an X * erasing character, for it if got rejected there would X * be no way of erasing a preceding backslash. */ X escaped = OFF; X if (iindex > 0) { X if(!passwd) X Writechar(BACKSPACE); X iindex--; X } X if(!passwd) { X Writechar(' '); X Writechar(BACKSPACE); X fflush(stdout); X } X } X else if (ch == EOF || ch == '\n' || ch == '\r') { X escaped = OFF; X string[iindex] = '\0'; X if (cursor_control) X transmit_functions(ON); X return(0); X } X else if (!passwd && ch == ctrl('W')) { /* back up a word! */ X escaped = OFF; X if (iindex == 0) X continue; /* no point staying here.. */ X iindex--; X if (isslash(string[iindex])) { X erase_a_char(); X } X else { X while (iindex >= 0 && isspace(string[iindex])) { X iindex--; X erase_a_char(); X } X X while (iindex >= 0 && ! isstopchar(string[iindex])) { X iindex--; X erase_a_char(); X } X iindex++; /* and make sure we point at the first AVAILABLE slot */ X } X } X else if (!passwd && ch == ctrl('R')) { X escaped = OFF; X string[iindex] = '\0'; X if (use_cursor_control) { X PutLine1(x,y, "%s", string); X CleartoEOLN(); X } X else X printf("\n\r%s", string); X } X else if (!escaped && ch == kill_line) { X /* needed to test if escaped since kill_line character could X * be a desired valid printing character */ X escaped = OFF; X if(!passwd) { X if (use_cursor_control) X MoveCursor(x,y); X else X back_up(iindex); X CleartoEOLN(); X } X iindex = 0; X } X else if (ch == '\0') { X escaped = OFF; X if (cursor_control) X transmit_functions(ON); X fflush(stdin); /* remove extraneous chars, if any */ X string[0] = '\0'; /* clean up string, and... */ X return(-1); X } X else if (!passwd && (ch < ' ' || ch > '~')) { X /* non-printing character - warn with bell*/ X /* don't turn off escaping backslash since current character X * doesn't "use it up". X */ X Writechar('\007'); X } X else { /* default case */ X if(escaped && (ch == backspace || ch == kill_line)) { X /* if last character was a backslash, X * and if this character is escapable X * simply write this character over it even if X * this character is a backslash. X */ X if(!passwd) X Writechar(BACKSPACE); X iindex--; X string[iindex++] = ch; X if(!passwd) X Writechar(ch); X escaped = OFF; X } else { X string[iindex++] = ch; X if(!passwd) X Writechar(ch); X escaped = ( ch == '\\' ? ON : OFF); X } X } X } while (iindex < SLEN); X X string[iindex] = '\0'; X X if (cursor_control) X transmit_functions(ON); X X return(0); X} X Xint Xpattern_enter(string, alt_string, x, y, alternate_prompt) Xchar *string, *alt_string, *alternate_prompt; Xint x,y; X{ X /** This function is functionally similar to the routine X optionally-enter, but if the first character pressed X is a '/' character, then the alternate prompt and string X are used rather than the normal one. This routine X returns 1 if alternate was used, 0 if not X **/ X X int ch; X register iindex = 0, escaped = OFF; X X PutLine1(x, y, "%s", string); X CleartoEOLN(); X MoveCursor(x,y); X X if (cursor_control) X transmit_functions(OFF); X X ch = getchar(); X X if (ch == '\n' || ch == '\r') { X if (cursor_control) X transmit_functions(ON); X return(0); /* we're done. No change needed */ X } X X if (ch == '/') { X PutLine1(x, 0, "%s", alternate_prompt); X CleartoEOLN(); X (void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1, X FALSE, FALSE); X return(1); X } X X CleartoEOLN(); X X iindex = 0; X X if (ch == kill_line) { X MoveCursor(x,y); X CleartoEOLN(); X iindex = 0; X } X else if (ch != backspace) { X if(ch == '\\') escaped = ON; X Writechar(ch); X string[iindex++] = ch; X } X else if (iindex > 0) { X iindex--; X erase_a_char(); X } X else { X Writechar(' '); X Writechar(BACKSPACE); X } X X do { X fflush(stdout); X ch = getchar(); X X /* the following is converted from a case statement to X allow the variable characters (backspace, kill_line X and break) to be processed. Case statements in X C require constants as labels, so it failed ... X */ X X if (ch == backspace && X (!escaped || (ch < ' ' || ch > '~'))) { X /* This is tricky. Here we are dealing with all situations X * under which a backspace (really whatever erase char is X * set to, not necessarily \b) erases the previous character. X * It will erase unless escaped, because if it's escaped X * it is taken literally. There is one exception to that -- X * if backspace would be rejected (we don't accept non-printing X * characters in non-passwd mode), we accept it here as an X * erasing character, for it if got rejected there would X * be no way of erasing a preceding backslash. */ X escaped = OFF; X if (iindex > 0) { X iindex--; X erase_a_char(); X } X else { X Writechar(' '); X Writechar(BACKSPACE); X } X } X else if (ch == '\n' || ch == '\r') { X escaped = OFF; X string[iindex] = '\0'; X if (cursor_control) X transmit_functions(ON); X return(0); X } X else if (ch == ctrl('W')) { X escaped = OFF; X if (iindex == 0) X continue; /* no point staying here.. */ X iindex--; X if (isslash(string[iindex])) { X erase_a_char(); X } X else { X while (iindex >= 0 && isspace(string[iindex])) { X iindex--; X erase_a_char(); X } X X while (iindex >= 0 && ! isstopchar(string[iindex])) { X iindex--; X erase_a_char(); X } X iindex++;/* and make sure we point at the first AVAILABLE slot */ X } X } X else if (ch == ctrl('R')) { X escaped = OFF; X string[iindex] = '\0'; X PutLine1(x,y, "%s", string); X CleartoEOLN(); X } X else if (!escaped && ch == kill_line) { X /* needed to test if escaped since kill_line character could X * be a desired valid printing character */ X escaped = OFF; X MoveCursor(x,y); X CleartoEOLN(); X iindex = 0; X } X else if (ch == '\0') { X escaped = OFF; X if (cursor_control) X transmit_functions(ON); X fflush(stdin); /* remove extraneous chars, if any */ X string[0] = '\0'; /* clean up string, and... */ X return(-1); X } X else if (ch < ' ' || ch > '~') { X /* non-printing character - warn with bell*/ X /* don't turn off escaping backslash since current character X * doesn't "use it up". X */ X Writechar('\007'); X } X else { /* default case */ X if(escaped && (ch == backspace || ch == kill_line)) { X /* if last character was a backslash, X * and if this character is escapable X * simply write this character over it even if X * this character is a backslash. X */ X Writechar(BACKSPACE); X iindex--; X string[iindex++] = ch; X Writechar(ch); X escaped = OFF; X } else { X string[iindex++] = ch; X Writechar(ch); X escaped = ( ch == '\\' ? ON : OFF); X } X } X } while (iindex < SLEN); X X string[iindex] = '\0'; X X if (cursor_control) X transmit_functions(ON); X return(0); X} X Xback_up(spaces) Xint spaces; X{ X /** this routine is to replace the goto x,y call for when sending X mail without starting the entire "elm" system up... **/ X X while (spaces--) { X erase_a_char(); X } X} X Xnon_destructive_back_up(spaces) Xint spaces; X{ X /** same as back_up() but doesn't ERASE the characters on the screen **/ X X while (spaces--) X Writechar(BACKSPACE); X fflush(stdout); X} X Xint XGetPrompt() X{ X /** This routine does a read/timeout for a single character. X The way that this is determined is that the routine to X read a character is called, then the "errno" is checked X against EINTR (interrupted call). If they match, this X returns NO_OP_COMMAND otherwise it returns the normal X command. X **/ X X int ch; X X if (timeout > 0) { X alarm((unsigned) timeout); X errno = 0; /* we actually have to do this. *sigh* */ X ch = ReadCh(); X if (errno == EINTR) ch = NO_OP_COMMAND; X alarm((unsigned) 0); X } X else X ch = ReadCh(); X X return(ch); X} SHAR_EOF chmod 0444 src/in_utils.c || echo "restore of src/in_utils.c fails" echo "x - extracting src/init.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/init.c && X Xstatic char rcsid[] = "@(#)$Id: init.c,v 2.24 89/03/25 21:46:31 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.24 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@dsinc.UUCP dsinc!elm X * X ******************************************************************************* X * $Log: init.c,v $ X * Revision 2.24 89/03/25 21:46:31 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/***** Initialize - read in all the defaults etc etc X*****/ X X#include "headers.h" X#include "patchlevel.h" X X#ifdef BSD X# include <sgtty.h> X#else X# include <termio.h> X#endif X X#include <pwd.h> X X#ifdef BSD X# include <sys/time.h> X#else X# include <time.h> X#endif X X#include <signal.h> X#include <ctype.h> X#include <errno.h> X X#ifdef BSD X#undef toupper X#undef tolower X#endif X Xextern int errno; /* system error number on failure */ Xextern char version_buff[]; X Xchar *error_name(), *error_description(); X Xchar *getenv(), *getlogin(), *strcpy(), *strcat(); Xunsigned short getgid(), getuid(); Xvoid exit(); X Xinitialize(requestedmfile) Xchar *requestedmfile; /* first mail file to open, empty if the default */ X{ X /** initialize the whole ball of wax. X **/ X struct passwd *pass, *getpwuid(); X char *getenv(), *get_full_name(); X X register int i, j; X#ifdef VOIDSIG X void quit_signal(), term_signal(), ill_signal(), X fpe_signal(), bus_signal(), segv_signal(), X alarm_signal(), pipe_signal(), hup_signal(); X#else X int quit_signal(), term_signal(), ill_signal(), X fpe_signal(), bus_signal(), segv_signal(), X alarm_signal(), pipe_signal(), hup_signal(); X#endif X#ifdef SIGTSTP X#ifdef VOIDSIG X int sig_user_stop(), sig_return_from_user_stop(); X#else X int sig_user_stop(), sig_return_from_user_stop(); X#endif X#endif X char buffer[SLEN], *cp; X X sprintf(version_buff, "%s PL%d", VERSION, PATCHLEVEL); X Raw(ON); X X userid = getuid(); X groupid = getgid(); X X (void)umask(077); /* make all newly created files private */ X X /* Get username (logname), home (login directory), and full_username X * (part of GCOS) field from the password entry for this user id. X * Full_username will get overridden by fullname in elmrc, if defined. X */ X X if((pass = getpwuid(userid)) == NULL) { X error("You have no password entry!"); X Raw(OFF); X exit(1); X } X strcpy(username, pass->pw_name); X strcpy(home, pass->pw_dir); X X if((cp = get_full_name(username)) != NULL) X strcpy(full_username, cp); X else X strcpy(full_username, username); /* fall back on logname */ X X#ifdef DEBUG X if (debug) { /* setup for dprint() statements! */ X char newfname[SLEN], filename[SLEN]; X X sprintf(filename, "%s/%s", home, DEBUGFILE); X if (access(filename, ACCESS_EXISTS) == 0) { /* already one! */ X sprintf(newfname,"%s/%s", home, OLDEBUG); X (void) rename(filename, newfname); X } X X /* Note what we just did up there: we always save the old X version of the debug file as OLDEBUG, so users can mail X copies of bug files without trashing 'em by starting up X the mailer. Dumb, subtle, but easy enough to do! X */ X X if ((debugfile = fopen(filename, "w")) == NULL) { X debug = 0; /* otherwise 'leave' will try to log! */ X leave(fprintf(stderr,"Could not open file %s for debug output!\n", X filename)); X } X chown(filename, userid, groupid); /* file owned by user */ X X fprintf(debugfile, X "Debug output of the ELM program (at debug level %d). Version %s\n\n", X debug, version_buff); X } X#endif X X if(!check_only && !batch_only) { X if ((i = InitScreen()) < 0) { X if (i == -1) { X printf( X"Sorry, but you must specify what type of terminal you're on if you want to\n"); X printf( X"run the \"elm\" program. (You need your environment variable \"TERM\" set.)\n" X ); X dprint(1,(debugfile,"No $TERM variable in environment!\n")); X } X else if (i == -2) { X printf( X"You need a cursor-addressable terminal to run \"elm\" and I can't find any\n"); X printf( X"kind of termcap entry for \"%s\" - check your \"TERM\" setting...\n", X getenv("TERM")); X dprint(1, X (debugfile,"$TERM variable is an unknown terminal type!\n")); X } else { X printf("Failed trying to initialize your terminal entry: unknown return code %d\n", i); X dprint(1, (debugfile, "Initscreen returned unknown code: %d\n", X i)); X } X Raw(OFF); X exit(1); /* all the errors share this exit statement */ X } X } X X if (debug < 5) { /* otherwise let the system trap 'em! */ X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, quit_signal); /* Quit signal */ X signal(SIGTERM, term_signal); /* Terminate signal */ X signal(SIGILL, ill_signal); /* Illegal instruction */ X signal(SIGFPE, fpe_signal); /* Floating point exception */ X signal(SIGBUS, bus_signal); /* Bus error */ X signal(SIGSEGV, segv_signal); /* Segmentation Violation */ X signal(SIGHUP, hup_signal); /* HangUp (line dropped) */ X } X else { X dprint(3,(debugfile, X "\n*** Elm-Internal Signal Handlers Disabled due to debug level %d ***\n\n", X debug)); X } X X signal(SIGALRM, alarm_signal); /* Process Timer Alarm */ X signal(SIGPIPE, pipe_signal); /* Illegal Pipe Operation */ X#ifdef SIGTSTP X signal(SIGTSTP, sig_user_stop); /* Suspend signal from tty */ X signal(SIGCONT, sig_return_from_user_stop); /* Continue Process */ X#endif X X get_term_chars(); X X#ifdef HOSTCOMPILED X strncpy(hostname, HOSTNAME, sizeof(hostname)); X#else X gethostname(hostname, sizeof(hostname)); X#endif X gethostdomain(hostdomain, sizeof(hostdomain)); X X /* Determine the default mail file name. X * X * First look for an environment variable MAIL, then X * use then mailhome if it is not found X */ X if ((cp = getenv("MAIL")) == NULL) X sprintf(defaultfile, "%s%s", mailhome, username); X else X strcpy(defaultfile, cp); X X /* Determine options that might be set in the .elm/elmrc */ X read_rc_file(); X X /* Determine the mail file to read */ X if (*requestedmfile == '\0') X strcpy(requestedmfile, defaultfile); X else if(!expand_filename(requestedmfile, FALSE)) { X Raw(OFF); X exit(0); X } X if (check_size) X if(check_mailfile_size(requestedmfile) != 0) { X Raw(OFF); X exit(0); X } X X /* check for permissions only if not default mail file */ X if(strcmp(requestedmfile, defaultfile) != 0) { X if ((errno = can_access(requestedmfile, READ_ACCESS))) { X dprint(1, (debugfile, X "Error: given file %s as folder - unreadable (%s)!\n", X requestedmfile, error_name(errno))); X fprintf(stderr,"Can't open folder '%s' for reading!\n", X requestedmfile); X Raw(OFF); X exit(1); X } X } X X /** check to see if the user has defined a LINES or COLUMNS X value different to that in the termcap entry (for X windowing systems, of course!) **/ X X ScreenSize(&LINES, &COLUMNS); X X if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) { X sscanf(cp, "%d", &LINES); X LINES -= 1; /* kludge for HP Window system? ... */ X } X X if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp)) X sscanf(cp, "%d", &COLUMNS); X X /** fix the shell if needed **/ X X if (shell[0] != '/') { X sprintf(buffer, "/bin/%s", shell); X strcpy(shell, buffer); X } X X if (! mail_only && ! check_only) { X X /* get the cursor control keys... */ X X cursor_control = FALSE; X X if ((cp = return_value_of("ku")) != NULL) { X strcpy(up, cp); X if ((cp = return_value_of("kd")) != NULL) { X strcpy(down, cp); X if ((cp = return_value_of("kl")) != NULL) { X strcpy(left, cp); X if ((cp = return_value_of("kr")) != NULL) { X strcpy(right, cp); X cursor_control = TRUE; X transmit_functions(ON); X } X } X } X } X X strcpy(start_highlight, "->"); X end_highlight[0] = '\0'; X X if (!arrow_cursor) { /* try to use inverse bar instead */ X if ((cp = return_value_of("so")) != NULL) { X strcpy(start_highlight, cp); X if ((cp = return_value_of("se")) == NULL) X strcpy(start_highlight, "->"); X else { X strcpy(end_highlight, cp); X has_highlighting = TRUE; X } X } X } X } X X /** clear the screen **/ X if(!check_only && !batch_only) X ClearScreen(); X X if (! mail_only && ! check_only) { X if (mini_menu) X headers_per_page = LINES - 13; X else X headers_per_page = LINES - 8; /* 5 more headers! */ X X newmbox(requestedmfile, FALSE); /* read in the folder! */ X } X X#ifdef DEBUG X if (debug >= 2 && debug < 10) { X fprintf(debugfile, X"hostname = %-20s \tusername = %-20s \tfullname = %-20s\n", X hostname, username, full_username); X X fprintf(debugfile, X"home = %-20s \teditor = %-20s \trecvd_mail = %-20s\n", X home, editor, recvd_mail); X X fprintf(debugfile, X"cur_folder = %-20s \tfolders = %-20s \tprintout = %-20s\n", X cur_folder, folders, printout); X X fprintf(debugfile, X"sent_mail = %-20s \tprefix = %-20s \tshell = %-20s\n\n", X sent_mail, prefixchars, shell); X X if (local_signature[0]) X fprintf(debugfile, "local_signature = \"%s\"\n", X local_signature); X if (remote_signature[0]) X fprintf(debugfile, "remote_signature = \"%s\"\n", X remote_signature); X if (local_signature[0] || remote_signature[0]) X fprintf(debugfile, "\n"); X } X#endif X} X Xget_term_chars() X{ X /** This routine sucks out the special terminal characters X ERASE and KILL for use in the input routine. The meaning X of the characters are (dare I say it?) fairly obvious... **/ X X#ifdef BSD X struct sgttyb term_buffer; X X# define TCGETA TIOCGETP X X#else X struct termio term_buffer; X#endif X X if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) { X dprint(1, (debugfile, X "Error: %s encountered on ioctl call (get_term_chars)\n", X error_name(errno))); X /* set to defaults for terminal driver */ X backspace = BACKSPACE; X kill_line = ctrl('U'); X } X else { X#ifdef BSD X backspace = term_buffer.sg_erase; X kill_line = term_buffer.sg_kill; X#else X backspace = term_buffer.c_cc[VERASE]; X kill_line = term_buffer.c_cc[VKILL]; X#endif X } X} SHAR_EOF chmod 0444 src/init.c || echo "restore of src/init.c fails" echo "x - extracting src/leavembox.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/leavembox.c && X Xstatic char rcsid[] = "@(#)$Id: leavembox.c,v 2.26 89/03/25 21:46:33 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.26 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@dsinc.UUCP dsinc!elm X * SHAR_EOF echo "End of part 15" echo "File src/leavembox.c is continued in part 16" echo "16" > s2_seq_.tmp exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.