rsalz@uunet.uu.net (Rich Salz) (04/14/89)
Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein) Posting-number: Volume 18, Issue 100 Archive-name: elm2.2/part21 #!/bin/sh # this is part 21 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/showmsg_c.c continued # CurArch=21 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/showmsg_c.c" sed 's/^X//' << 'SHAR_EOF' >> src/showmsg_c.c X#else X store_msg("Can't scan for calendar entries!"); X#endif X break; X X case '%' : put_cmd_name("Display return address", TRUE); X get_return(msg_line, current-1); X break; X X case 'b' : put_cmd_name("Bounce message", TRUE); X remail(); X break; X X case 'd' : delete_msg(TRUE, FALSE); /* really delete it, silent */ X if (! resolve_mode) X store_msg("Message marked for deletion."); X else X goto next_undel_msg; X break; X X case 'f' : put_cmd_name("Forward message", TRUE); X if(forward()) put_border(); X break; X X case 'g' : put_cmd_name("Group reply", TRUE); X (void) reply_to_everyone(); X break; X X case 'h' : screen_mangled = 0; X if (filter) { X filter = 0; X intbuf = show_msg(current); X filter = 1; X return(intbuf); X } else X return(show_msg(current)); X X case 'q' : X case 'i' : (void) get_page(current); X clear_error(); /* zero out pending msg */ X if (cursor_control) X transmit_functions(ON); X screen_mangled = 0; X return(0); /* avoid <return> looping */ X Xnext_undel_msg : /* a target for resolve mode actions */ X X case ' ' : X case 'j' : X case 'n' : screen_mangled = 0; X if((i=next_message(current-1, TRUE)) != -1) X return(show_msg(current = i+1)); X else return(0); X Xnext_msg: X case 'J' : screen_mangled = 0; X if((i=next_message(current-1, FALSE)) != -1) X return(show_msg(current = i+1)); X else return(0); X Xprev_undel_msg: X case 'k' : screen_mangled = 0; X if((i=prev_message(current-1, TRUE)) != -1) X return(show_msg(current = i+1)); X else return(0); X X case 'K' : screen_mangled = 0; X if((i=prev_message(current-1, FALSE)) != -1) X return(show_msg(current = i+1)); X else return(0); X X case 'm' : put_cmd_name("Mail message", TRUE); X if(sendmsg("","","", TRUE, allow_forms, FALSE)) X put_border(); X break; X X case 'p' : put_cmd_name("Print message", FALSE); X print_msg(); X store_msg("Queued for printing."); X break; X X case 'r' : put_cmd_name("Reply to message", TRUE); X if(reply()) put_border(); X break; X X case '>' : X case 'C' : X case 's' : put_cmd_name((command != 'C' ? "Save" : "Copy"), TRUE); X (void) save(&intbuf, TRUE, (command != 'C')); X if (resolve_mode && command != 'C') X goto next_undel_msg; X break; X X case 't' : istagged=tag_message(FALSE); X if(istagged) X store_msg("Message tagged."); X else X store_msg("Message untagged."); X break; X X case 'u' : undelete_msg(FALSE); /* undelete it, silently */ X if (! resolve_mode) X store_msg("Message undeleted."); X else { X/****************************************************************************** X ** We're special casing the U)ndelete command here *not* to move to the next X ** undeleted message ; instead it'll blindly move to the next message in the X ** list. See 'elm.c' and the command by "case 'u'" for further information. X ** The old code was: X goto next_undel_msg; X*******************************************************************************/ X goto next_msg; X } X break; X X case 'x' : fflush(stdout); leave(); X X case ctrl('J'): X case ctrl('M'): screen_mangled = 0; X return(show_msg(current)); X X X case ESCAPE : if (cursor_control) { X X key_offset = 1; X X ch = ReadCh(); X X if (ch == ESCAPE) 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 goto prev_undel_msg; X else if (ch == down[key_offset]) X goto next_undel_msg; X else { X screen_mangled = 0; X return(0); X } X } X else /* Eat 2 chars for escape codes */ X { X ch = ReadCh(); X ch = ReadCh(); X putchar((char) 007); X fflush(stdout); X screen_mangled = 0; X return(0); X } X X default : putchar((char) 007); /* BEEP! */ X } X X /* display prompt */ X if (screen_mangled) { X /* clear what was left over from previous command X * and display last generated message. X */ X put_prompt(); X CleartoEOS(); X put_help(); X Centerline(LINES, msg_line); X MoveCursor(LINES-3, POST_PROMPT_COL); X } else { X /* display bottom line prompt with last generated message */ X MoveCursor(LINES, 0); X CleartoEOS(); X StartBold(); X Write_to_screen("%s Command ('i' to return to index): ", X 1, msg_line); X EndBold(); X } X *msg_line = '\0'; /* null last generated message */ X X command = GetPrompt(); /* get next command from user */ X } X} X Xput_cmd_name(command, will_mangle) Xchar *command; Xint will_mangle; X{ X X /* If screen is or will be mangled display the command name X * and erase the bottom of the screen. X * But first if the border line hasn't yet been drawn, draw it. X */ X if(will_mangle && !screen_mangled) { X build_bottom(); X screen_mangled = TRUE; X } X if(screen_mangled) { X PutLine0(LINES-3, POST_PROMPT_COL, command); X CleartoEOS(); X } X} X Xput_border() X{ X PutLine0(LINES-4, 0, X"--------------------------------------------------------------------------\n"); X} X Xbuild_bottom() X{ X MoveCursor(LINES-4, 0); X CleartoEOS(); X put_border(); X put_prompt(); X put_help(); X} SHAR_EOF echo "File src/showmsg_c.c is complete" chmod 0444 src/showmsg_c.c || echo "restore of src/showmsg_c.c fails" echo "x - extracting src/signals.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/signals.c && X Xstatic char rcsid[] = "@(#)$Id: signals.c,v 2.5 89/03/25 21:47:23 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.5 $ $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: signals.c,v $ X * Revision 2.5 89/03/25 21:47:23 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** This set of routines traps various signals and informs the X user of the error, leaving the program in a nice, graceful X manner. X X**/ X X#include "headers.h" X#include <signal.h> X Xextern int pipe_abort; /* set to TRUE if receive SIGPIPE */ X Xquit_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGQUIT **\n\n\n\n")); X leave(); X} X Xhup_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGHUP **\n\n\n\n")); X leave(); X} X Xterm_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGTERM **\n\n\n\n")); X leave(); X} X Xill_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGILL **\n\n\n\n")); X PutLine0(LINES, 0, "\n\nIllegal Instruction signal!\n\n"); X emergency_exit(); X} X Xfpe_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGFPE **\n\n\n\n")); X PutLine0(LINES, 0,"\n\nFloating Point Exception signal!\n\n"); X emergency_exit(); X} X Xbus_signal() X{ X dprint(1, (debugfile, "\n\n** Received SIGBUS **\n\n\n\n")); X PutLine0(LINES, 0,"\n\nBus Error signal!\n\n"); X emergency_exit(); X} X Xsegv_signal() X{ X dprint(1, (debugfile,"\n\n** Received SIGSEGV **\n\n\n\n")); X PutLine0(LINES, 0,"\n\nSegment Violation signal!\n\n"); X emergency_exit(); X} X X#ifdef VOIDSIG Xvoid alarm_signal() X#else Xint alarm_signal() X#endif X{ X /** silently process alarm signal for timeouts... **/ X X#ifdef VOIDSIG X void alarm_signal(); X#else X int alarm_signal(); X#endif X X signal(SIGALRM, alarm_signal); X} X X#ifdef VOIDSIG Xvoid pipe_signal() X#else Xint pipe_signal() X#endif X{ X /** silently process pipe signal... **/ X X#ifdef VOIDSIG X void pipe_signal(); X#else X int pipe_signal(); X#endif X X dprint(2, (debugfile, "*** received SIGPIPE ***\n\n")); X X pipe_abort = TRUE; /* internal signal ... wheeee! */ X X signal(SIGPIPE, pipe_signal); X} X X#ifdef SIGTSTP Xint was_in_raw_state; X X#ifdef VOIDSIG Xvoid sig_user_stop() X#else Xint sig_user_stop() X#endif X{ X /* This is called when the user presses a ^Z to stop the X process within BSD X */ X if (signal(SIGTSTP, SIG_DFL) != SIG_DFL) X signal(SIGTSTP, SIG_DFL); X X was_in_raw_state = RawState(); X Raw(OFF); /* turn it off regardless */ X X printf("\n\nStopped. Use \"fg\" to return to ELM\n\n"); X X kill(0, SIGSTOP); X} X Xsig_return_from_user_stop() X{ X /** this is called when returning from a ^Z stop **/ X X#ifdef VOIDSIG X void sig_user_stop(); X#else X int sig_user_stop(); X#endif X X if (signal(SIGTSTP, sig_user_stop) == SIG_DFL) X signal(SIGTSTP, sig_user_stop); X X printf( X "\nBack in ELM. (You might need to explicitly request a redraw.)\n\n"); X X if (was_in_raw_state) X Raw(ON); X} X#endif SHAR_EOF chmod 0444 src/signals.c || echo "restore of src/signals.c fails" echo "x - extracting src/softkeys.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/softkeys.c && X Xstatic char rcsid[] = "@(#)$Id: softkeys.c,v 2.8 89/03/25 21:47:25 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.8 $ $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: softkeys.c,v $ X * Revision 2.8 89/03/25 21:47:25 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X X#include "headers.h" X Xdefine_softkeys(level) Xint level; X{ X if (! hp_softkeys) return; X X if (level == MAIN) { X X define_key(f1, " Display Msg", "\r"); X define_key(f2, " Mail Msg", "m"); X define_key(f3, " Reply to Msg", "r"); X X if (user_level == 0) { X define_key(f4, " Save Msg", "s"); X define_key(f5, " Delete Msg", "d"); X define_key(f6, "Undelete Msg", "u"); X } X else { X define_key(f4, " Change Folder", "c"); X define_key(f5, " Save Msg", "s"); X define_key(f6, " Delete/Undelete", "^"); X } X X define_key(f7, " Print Msg", "p"); X define_key(f8, " Quit ELM", "q"); X } X else if (level == ALIAS) { X define_key(f1, " Alias Current", "a"); X define_key(f2, " Check Person", "p"); X define_key(f3, " Check System", "s"); X define_key(f4, " Make Alias", "m"); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " Return to ELM", "r"); X } X else if (level == YESNO) { X define_key(f1, " Yes", "y"); X clear_key(f2); X clear_key(f3); X clear_key(f4); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " No", "n"); X } X else if (level == READ) { X define_key(f1, " Next Page ", " "); X clear_key(f2); X define_key(f3, " Next Msg ", "j"); X define_key(f4, " Prev Msg ", "k"); X define_key(f5, " Reply to Msg ", "r"); X define_key(f6, " Delete Msg ", "d"); X define_key(f7, " Send Msg ", "m"); X define_key(f8, " Return to ELM ", "q"); X } X else if (level == CHANGE) { X define_key(f1, " Mail Directry", "=/"); X define_key(f2, " Home Directry", "~/"); X clear_key(f3); X define_key(f4, "Incoming Mailbox", "!\n"); X define_key(f5, "\"Received\" Folder", ">\n"); X define_key(f6, "\"Sent\" Folder ", "<\n"); X clear_key(f7); X define_key(f8, " Cancel", "\n"); X } X X softkeys_on(); X} X Xdefine_key(key, display, send) Xint key; Xchar *display, *send; X{ X X char buffer[30]; X X sprintf(buffer,"%s%s", display, send); X X fprintf(stderr, "%c&f%dk%dd%dL%s", ESCAPE, key, X strlen(display), strlen(send), buffer); X fflush(stdout); X} X Xsoftkeys_on() X{ X /* enable (esc&s1A) turn on softkeys (esc&jB) and turn on MENU X and USER/SYSTEM options. */ X X if (hp_softkeys) { X fprintf(stderr, "%c&s1A%c&jB%c&jR", ESCAPE, ESCAPE, ESCAPE); X fflush(stdout); X } X X} X Xsoftkeys_off() X{ X /* turn off softkeys (esc&j@) */ X X if (hp_softkeys) { X fprintf(stderr, "%c&s0A%c&j@", ESCAPE, ESCAPE); X fflush(stdout); X } X} X Xclear_key(key) X{ X /** set a key to nothing... **/ X X if (hp_softkeys) X define_key(key, " ", ""); X} SHAR_EOF chmod 0444 src/softkeys.c || echo "restore of src/softkeys.c fails" echo "x - extracting src/sort.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/sort.c && X Xstatic char rcsid[] = "@(#)$Id: sort.c,v 2.7 89/03/25 21:47:26 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.7 $ $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: sort.c,v $ X * Revision 2.7 89/03/25 21:47:26 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** Sort folder header table by the field specified in the global X variable "sortby"...if we're sorting by something other than X the default SENT_DATE, also put some sort of indicator on the X screen. X X**/ X X#include "headers.h" X Xchar *sort_name(), *skip_re(); Xvoid qsort(); X Xsort_mailbox(entries, visible) Xint entries, visible; X{ X /** Sort the header_table definitions... If 'visible', then X put the status lines etc **/ X X int last_index = -1; X int compare_headers(); /* for sorting */ X X dprint(2, (debugfile, "\n** sorting folder by %s **\n\n", X sort_name(FULL))); X X /* Don't get last_index if no entries or no current. */ X /* There would be no current if we are sorting a new mail file. */ X if (entries > 0 && current > 0) X last_index = headers[current-1]->index_number; X X if (entries > 30 && visible) X error1("Sorting messages by %s...", sort_name(FULL)); X X qsort(headers, (unsigned) entries, sizeof (struct header_rec *), X compare_headers); X X if (last_index > -1) X find_old_current(last_index); X X clear_error(); X} X Xint Xcompare_headers(p1, p2) Xstruct header_rec **p1, **p2; X{ X /** compare two headers according to the sortby value. X X Sent Date uses a routine to compare two dates, X Received date is keyed on the file offsets (think about it) X Sender uses the truncated from line, same as "build headers", X and size and subject are trivially obvious!! X (actually, subject has been modified to ignore any leading X patterns [rR][eE]*:[ \t] so that replies to messages are X sorted with the message (though a reply will always sort to X be 'greater' than the basenote) X **/ X X char from1[SLEN], from2[SLEN]; /* sorting buffers... */ X struct header_rec *first, *second; X int ret; X X first = *p1; X second = *p2; X X switch (abs(sortby)) { X case SENT_DATE: X ret = compare_dates(first, second); X break; X X case RECEIVED_DATE: X ret = compare_parsed_dates(first->received, second->received); X break; X X case SENDER: X tail_of(first->from, from1, first->to); X tail_of(second->from, from2, second->to); X ret = strcmp(from1, from2); X break; X X case SIZE: X ret = (first->lines - second->lines); X break; X X case MAILBOX_ORDER: X ret = (first->index_number - second->index_number); X break; X X case SUBJECT: X /* need some extra work 'cause of STATIC buffers */ X strcpy(from1, skip_re(shift_lower(first->subject))); X ret = strcmp(from1, skip_re(shift_lower(second->subject))); X break; X X case STATUS: X ret = (first->status - second->status); X break; X X default: X /* never get this! */ X ret = 0; X break; X } X X if (sortby < 0) X ret = -ret; X X return ret; X} X Xchar *sort_name(type) Xint type; X{ X /** return the name of the current sort option... X type can be "FULL", "SHORT" or "PAD" X **/ X int pad, abr; X X pad = (type == PAD); X abr = (type == SHORT); X X if (sortby < 0) { X switch (- sortby) { X case SENT_DATE : return( X pad? "Reverse Date Mail Sent " : X abr? "Reverse-Sent" : X "Reverse Date Mail Sent"); X case RECEIVED_DATE: return( X abr? "Reverse-Received": X "Reverse Date Mail Rec'vd" ); X X case MAILBOX_ORDER: return( X pad? "Reverse Mailbox Order " : X abr? "Reverse-Mailbox": X "Reverse Mailbox Order"); X X case SENDER : return( X pad? "Reverse Message Sender " : X abr? "Reverse-From": X "Reverse Message Sender"); X case SIZE : return( X abr? "Reverse-Lines" : X "Reverse Lines in Message"); X case SUBJECT : return( X pad? "Reverse Message Subject " : X abr? "Reverse-Subject" : X "Reverse Message Subject"); X case STATUS : return( X pad? "Reverse Message Status " : X abr? "Reverse-Status": X "Reverse Message Status"); X } X } X else { X switch (sortby) { X case SENT_DATE : return( X pad? "Date Mail Sent " : X abr? "Sent" : X "Date Mail Sent"); X case RECEIVED_DATE: return( X pad? "Date Mail Rec'vd " : X abr? "Received" : X "Date Mail Rec'vd"); X case MAILBOX_ORDER: return( X pad? "Mailbox Order " : X abr? "Mailbox" : X "Mailbox Order"); X case SENDER : return( X pad? "Message Sender " : X abr? "From" : X "Message Sender"); X case SIZE : return( X pad? "Lines in Message " : X abr? "Lines" : X "Lines in Message"); X case SUBJECT : return( X pad? "Message Subject " : X abr? "Subject" : X "Message Subject"); X case STATUS : return( X pad? "Message Status " : X abr? "Status" : X "Message Status"); X } X } X X return("*UNKNOWN-SORT-PARAMETER*"); X} X Xfind_old_current(iindex) Xint iindex; X{ X /** Set current to the message that has "index" as it's X index number. This is to track the current message X when we resync... **/ X X register int i; X X dprint(4, (debugfile, "find-old-current(%d)\n", iindex)); X X for (i = 0; i < message_count; i++) X if (headers[i]->index_number == iindex) { X current = i+1; X dprint(4, (debugfile, "\tset current to %d!\n", current)); X return; X } X X dprint(4, (debugfile, X "\tcouldn't find current index. Current left as %d\n", X current)); X return; /* can't be found. Leave it alone, then */ X} X Xchar *skip_re(string) Xchar *string; X{ X /** this routine returns the given string minus any sort of X "re:" prefix. specifically, it looks for, and will X remove, any of the pattern: X X ( [Rr][Ee][^:]:[ ] ) * X X If it doesn't find a ':' in the line it will return it X intact, just in case! X **/ X X static char buffer[SLEN]; X register int i=0; X X while (whitespace(string[i])) i++; X X do { X if (string[i] == '\0') return( (char *) string); /* forget it */ X X if (string[i] != 'r' || string[i+1] != 'e') X return( (char *) string); /* ditto */ X X i += 2; /* skip the "re" */ X X while (string[i] != ':') X if (string[i] == '\0') X return( (char *) string); /* no colon in string! */ X else X i++; X X /* now we've gotten to the colon, skip to the next non-whitespace */ X X i++; /* past the colon */ X X while (whitespace(string[i])) i++; X X } while (string[i] == 'r' && string[i+1] == 'e'); X X /* and now copy it into the buffer and sent it along... */ X X strcpy(buffer, (char *) string + i); X X return( (char *) buffer); X} SHAR_EOF chmod 0444 src/sort.c || echo "restore of src/sort.c fails" echo "x - extracting src/string2.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/string2.c && X Xstatic char rcsid[] = "@(#)$Id: string2.c,v 2.3 89/03/25 21:47:28 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.3 $ $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: string2.c,v $ X * Revision 2.3 89/03/25 21:47:28 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** This file contains string functions that are shared throughout the X various ELM utilities... X X**/ X X#ifndef TRUE X#define TRUE 1 X#define FALSE 0 X#endif X X#define whitespace(c) (c == ' ' || c == '\t') X Xint Xin_string(buffer, pattern) Xchar *buffer, *pattern; X{ X /** Returns TRUE iff pattern occurs IN IT'S ENTIRETY in buffer. **/ X X register int i = 0, j = 0; X X while (buffer[i] != '\0') { X while (buffer[i++] == pattern[j++]) X if (pattern[j] == '\0') X return(TRUE); X i = i - j + 1; X j = 0; X } X return(FALSE); X} X Xint Xchloc(string, ch) Xchar *string, ch; X{ X /** returns the index of ch in string, or -1 if not in string **/ X register int i; X X for (i=0; i<strlen(string); i++) X if (string[i] == ch) return(i); X return(-1); X} X Xint Xoccurances_of(ch, string) Xchar ch, *string; X{ X /** returns the number of occurances of 'ch' in string 'string' **/ X X register int count = 0, i; X X for (i=0; i<strlen(string); i++) X if (string[i] == ch) count++; X X return(count); X} X Xremove_possible_trailing_spaces(string) Xchar *string; X{ X /** an incredibly simple routine that will read backwards through X a string and remove all trailing whitespace. X **/ X X register int i; X X for (i=strlen(string)-1; whitespace(string[i]); i--) X /** spin backwards **/ X X string[i+1] = '\0'; /* note that even in the worst case when there X are no trailing spaces at all, we'll simply X end up replacing the existing '\0' with X another one! No worries, as M.G. would say X */ X} SHAR_EOF chmod 0444 src/string2.c || echo "restore of src/string2.c fails" echo "x - extracting src/strings.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/strings.c && X Xstatic char rcsid[] = "@(#)$Id: strings.c,v 2.10 89/03/25 21:47:29 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.10 $ $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: strings.c,v $ X * Revision 2.10 89/03/25 21:47:29 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** This file contains all the string oriented functions for the X ELM Mailer, and lots of other generally useful string functions! X X For BSD systems, this file also includes the function "tolower" X to translate the given character from upper case to lower case. X X**/ X X#include "headers.h" X#include <ctype.h> X X#ifdef BSD X#undef tolower X#undef toupper X#endif X X/** forward declarations **/ X Xchar *format_long(), *strip_commas(), *tail_of_string(), *shift_lower(), X *get_token(), *strip_parens(), *argv_zero(), *strcpy(), *strncpy(); X X Xcopy_sans_escape(dest, source, len) Xchar *dest, *source; Xint len; X{ X /** this performs the same function that strncpy() does, but X also will translate any escape character to a printable X format (e.g. ^(char value + 32)) X **/ X X register int i = 0, j = 0; X X while (i < len && source[i] != '\0') { X if (iscntrl(source[i]) && source[i] != '\t') { X dest[j++] = '^'; X dest[j++] = source[i++] + 'A' - 1; X } X else X dest[j++] = source[i++]; X } X X dest[j] = '\0'; X} X Xint Xtail_of(from, buffer, to) Xchar *from, *buffer, *to; X{ X /** Return last two words of 'from'. This is to allow X painless display of long return addresses as simply the X machine!username. X Or if the first word of the 'from' address is username or X full_username and 'to' is not NULL, then use the 'to' line X instead of the 'from' line. X If the 'to' line is used, return 1, else return 0. X X Also modified to know about X.400 addresses (sigh) and X that when we ask for the tail of an address similar to X a%b@c we want to get back a@b ... X **/ X X /** Note: '!' delimits Usenet nodes, '@' delimits ARPA nodes, X ':' delimits CSNet & Bitnet nodes, '%' delimits multi- X stage ARPA hops, and '/' delimits X.400 addresses... X (it is fortunate that the ASCII character set only has X so many metacharacters, as I think we're probably using X them all!!) **/ X X register int loc, i = 0, cnt = 0, using_to = 0; X X#ifndef INTERNET X X /** let's see if we have an address appropriate for hacking: X what this actually does is remove the spuriously added X local bogus Internet header if we have one and the message X has some sort of UUCP component too... X **/ X X sprintf(buffer, "@%s%s", hostname, hostdomain); X if (chloc(from,'!') != -1 && in_string(from, buffer)) X from[strlen(from)-strlen(buffer)] = '\0'; X X#endif X X for (loc = strlen(from)-1; loc >= 0 && cnt < 2; loc--) { X if (from[loc] == BANG || from[loc] == AT_SIGN || X from[loc] == COLON) cnt++; X if (cnt < 2) buffer[i++] = from[loc]; X } X X buffer[i] = '\0'; X X reverse(buffer); X X if ((strncmp(buffer, username, strlen(username)) == 0) || X (strncmp(buffer, full_username, strlen(full_username)) == 0)) { X X /* This message is from the user, so use the "to" header instead X * if possible, to be more informative. Otherwise be nice and X * use full_username rather than the bare username even if X * we've only matched on the bare username. X */ X X if(to && *to != '\0') { X tail_of(to, buffer, (char *)0); X using_to = 1; X } else X strcpy(buffer, full_username); X X } else { /* user%host@host? */ X X /** The logic here is that we're going to use 'loc' as a handy X flag to indicate if we've hit a '%' or not. If we have, X we'll rewrite it as an '@' sign and then when we hit the X REAL at sign (we must have one) we'll simply replace it X with a NULL character, thereby ending the string there. X **/ X X loc = 0; X X for (i=0; buffer[i] != '\0'; i++) X if (buffer[i] == '%') { X buffer[i] = AT_SIGN; X loc++; X } X else if (buffer[i] == AT_SIGN && loc) X buffer[i] = '\0'; X } X return(using_to); X X} X Xchar *format_long(inbuff, init_len) Xchar *inbuff; Xint init_len; X{ X /** Return buffer with \n\t sequences added at each point where it X would be more than 80 chars long. It only allows the breaks at X legal points (ie commas followed by white spaces). init-len is X the characters already on the first line... Changed so that if X this is called while mailing without the overhead of "elm", it'll X include "\r\n\t" instead. X Changed to use ',' as a separator and to REPLACE it after it's X found in the output stream... X **/ X X static char ret_buffer[VERY_LONG_STRING]; X register int iindex = 0, current_length = 0, depth=15, i; X char buffer[VERY_LONG_STRING]; X char *word, *bufptr; X X strcpy(buffer, inbuff); X X bufptr = (char *) buffer; X X current_length = init_len + 2; /* for luck */ X X while ((word = get_token(bufptr,",", depth)) != NULL) { X X /* first, decide what sort of separator we need, if any... */ X X if (strlen(word) + current_length > 80) { X if (iindex > 0) { X ret_buffer[iindex++] = ','; /* close 'er up, doctor! */ X ret_buffer[iindex++] = '\n'; X ret_buffer[iindex++] = '\t'; X } X X /* now add this pup! */ X X for (i=(word[0] == ' '? 1:0); i<strlen(word); i++) X ret_buffer[iindex++] = word[i]; X current_length = strlen(word) + 8; /* 8 = TAB */ X } X X else { /* just add this address to the list.. */ X X if (iindex > 0) { X ret_buffer[iindex++] = ','; /* comma added! */ X ret_buffer[iindex++] = ' '; X current_length += 2; X } X for (i=(word[0] == ' '? 1:0); i<strlen(word); i++) X ret_buffer[iindex++] = word[i]; X current_length += strlen(word); X } X X bufptr = NULL; X } X X ret_buffer[iindex] = '\0'; X X return( (char *) ret_buffer); X} X Xchar *strip_commas(string) Xchar *string; X{ X /** return string with all commas changed to spaces. This IS X destructive and will permanently change the input string.. **/ X X register int i; X X for (i=0; i < strlen(string); i++) X if (string[i] == COMMA) X string[i] = SPACE; X X return( (char *) string); X} X Xchar *strip_parens(string) Xchar *string; X{ X /** Return string with all parenthesized information removed. X This is a non-destructive algorithm... **/ X X static char buffer[VERY_LONG_STRING]; X register int i, depth = 0, buffer_index = 0; X X for (i=0; i < strlen(string); i++) { X if (string[i] == '(') X depth++; X else if (string[i] == ')') X depth--; X else if (depth == 0) X buffer[buffer_index++] = string[i]; X } X X buffer[buffer_index] = '\0'; X X return( (char *) buffer); X} X Xmove_left(string, chars) Xchar string[]; Xint chars; X{ X /** moves string chars characters to the left DESTRUCTIVELY **/ X X register int i; X X /* chars--; /* index starting at zero! */ X X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++) X string[i-chars] = string[i]; X X string[i-chars] = '\0'; X} X Xremove_first_word(string) Xchar *string; X{ /** removes first word of string, ie up to first non-white space X following a white space! **/ X X register int loc; X X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) X ; X X while (string[loc] == ' ' || string[loc] == '\t') X loc++; X X move_left(string, loc); X} X Xsplit_word(buffer, first, rest) Xchar *buffer, *first, *rest; X{ X /** Rip the buffer into first word and rest of word, translating it X all to lower case as we go along.. X **/ X X register int i, j = 0; X X /** skip leading white space, just in case.. **/ X X for (i=0; whitespace(buffer[i]); i++) ; X X /** now copy into 'first' until we hit white space or EOLN **/ X X for (j=0; i < strlen(buffer) && ! whitespace(buffer[i]); ++i) X first[j++] = tolower(buffer[i]); X X first[j] = '\0'; X X while (whitespace(buffer[i])) i++; X X for (j=0; i < strlen(buffer); i++) X rest[j++] = tolower(buffer[i]); X X rest[j] = '\0'; X X return; X} X Xchar *tail_of_string(string, maxchars) Xchar *string; Xint maxchars; X{ X /** Return a string that is the last 'maxchars' characters of the X given string. This is only used if the first word of the string X is longer than maxchars, else it will return what is given to X it... X **/ X X static char buffer[SLEN]; X register int iindex, i; X X for (iindex=0;! whitespace(string[iindex]) && iindex < strlen(string); X iindex++) X ; X X if (iindex < maxchars) { X strncpy(buffer, string, maxchars-2); /* word too short */ X buffer[maxchars-2] = '.'; X buffer[maxchars-1] = '.'; X buffer[maxchars] = '.'; X buffer[maxchars+1] = '\0'; X } X else { X i = maxchars; X buffer[i--] = '\0'; X while (i > 1) X buffer[i--] = string[iindex--]; X buffer[2] = '.'; X buffer[1] = '.'; X buffer[0] = '.'; X } X X return( (char *) buffer); X} X Xreverse(string) Xchar *string; X{ X /** reverse string... pretty trivial routine, actually! **/ X X char buffer[SLEN]; X register int i, j = 0; X X for (i = strlen(string)-1; i >= 0; i--) X buffer[j++] = string[i]; X X buffer[j] = '\0'; X X strcpy(string, buffer); X} X Xint Xget_word(buffer, start, word) Xchar *buffer, *word; Xint start; X{ X /** return next word in buffer, starting at 'start'. X delimiter is space or end-of-line. Returns the X location of the next word, or -1 if returning X the last word in the buffer. -2 indicates empty X buffer! **/ X X register int loc = 0; X X while (buffer[start] == ' ' && buffer[start] != '\0') X start++; X X if (buffer[start] == '\0') return(-2); /* nothing IN buffer! */ X X while (buffer[start] != ' ' && buffer[start] != '\0') X word[loc++] = buffer[start++]; X X word[loc] = '\0'; X return(start); X} X Xchar *shift_lower(string) Xchar *string; X{ X /** return 'string' shifted to lower case. Do NOT touch the X actual string handed to us! **/ X X static char buffer[SLEN]; X register int i; X X for (i=0; i < strlen(string); i++) X if (isupper(string[i])) X buffer[i] = tolower(string[i]); X else X buffer[i] = string[i]; X X buffer[strlen(string)] = 0; X X return( (char *) buffer); X} X XCenterline(line, string) Xint line; Xchar *string; X{ X /** Output 'string' on the given line, centered. **/ X X register int length, col; X X length = strlen(string); X X if (length > COLUMNS) X col = 0; X else X col = (COLUMNS - length) / 2; X X PutLine0(line, col, string); X} X Xchar *argv_zero(string) Xchar *string; X{ X /** given a string of the form "/something/name" return a X string of the form "name"... **/ X X static char buffer[NLEN]; X register int i, j=0; X X for (i=strlen(string)-1; string[i] != '/'; i--) X buffer[j++] = string[i]; X buffer[j] = '\0'; X X reverse(buffer); X X return( (char *) buffer); X} X X#define MAX_RECURSION 20 /* up to 20 deep recursion */ X Xchar *get_token(source, keys, depth) Xchar *source, *keys; Xint depth; X{ X /** This function is similar to strtok() (see "opt_utils") X but allows nesting of calls via pointers... X **/ X X register int last_ch; X static char *buffers[MAX_RECURSION]; X char *return_value, *sourceptr; X X if (depth > MAX_RECURSION) { X error1("Get_token calls nested greater than %d deep!", X MAX_RECURSION); X emergency_exit(); X } X X if (source != NULL) X buffers[depth] = source; X X sourceptr = buffers[depth]; X X if (*sourceptr == '\0') X return(NULL); /* we hit end-of-string last time!? */ X X sourceptr += strspn(sourceptr, keys); /* skip the bad.. */ X X if (*sourceptr == '\0') { X buffers[depth] = sourceptr; X return(NULL); /* we've hit end-of-string */ X } X X last_ch = strcspn(sourceptr, keys); /* end of good stuff */ X X return_value = sourceptr; /* and get the ret */ X X sourceptr += last_ch; /* ...value */ X X if (*sourceptr != '\0') /** don't forget if we're at end! **/ X sourceptr++; X X return_value[last_ch] = '\0'; /* ..ending right */ X X buffers[depth] = sourceptr; /* save this, mate! */ X X return((char *) return_value); /* and we're outta here! */ X} SHAR_EOF chmod 0444 src/strings.c || echo "restore of src/strings.c fails" echo "x - extracting src/syscall.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/syscall.c && X Xstatic char rcsid[] = "@(#)$Id: syscall.c,v 2.14 89/03/25 21:47:31 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.14 $ $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: syscall.c,v $ X * Revision 2.14 89/03/25 21:47:31 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** These routines are used for user-level system calls, including the X '!' command and the '|' commands... X X**/ X X#include "headers.h" X X#include <signal.h> X X#ifdef BSD X# include <sys/wait.h> X#endif X Xchar *argv_zero(); Xvoid _exit(); X Xint Xsubshell() X{ X /** spawn a subshell with either the specified command X returns non-zero if screen rewrite needed X **/ X X char command[SLEN]; X int ret; X int old_raw; X X PutLine0(LINES-3,COLUMNS-40,"(Use the shell name for a shell.)"); X PutLine0(LINES-2,0,"Shell command: "); X command[0] = '\0'; X (void) optionally_enter(command, LINES-2, 15, FALSE, FALSE); X if (strlen(command) == 0) { X MoveCursor(LINES-2,0); CleartoEOLN(); X return(0); X } X X MoveCursor(LINES,0); CleartoEOLN(); X if (( old_raw = RawState()) == ON) X Raw(OFF); X if (cursor_control) transmit_functions(OFF); X X ret = system_call(command, USER_SHELL, TRUE); X X PutLine0(LINES, 0, "\n\nPress any key to return to ELM."); X X if (old_raw == ON) X Raw(ON); X (void) getchar(); X if (cursor_control) transmit_functions(ON); X X if (ret != 0) error1("Return code was %d.", ret); X return(1); X} X Xsystem_call(string, shell_type, allow_signals) Xchar *string; Xint shell_type, allow_signals; X{ X /** execute 'string', setting uid to userid... **/ X /** if shell-type is "SH" /bin/sh is used regardless of the X users shell setting. Otherwise, "USER_SHELL" is sent. X If allow_signals is TRUE, then allow the executed X command handle interrupt and hangup in its X own way. This is useful for executed programs with X user interaction that handle those signals on their X own terms. It is especially important for vi, so that X a message being edited when a user connection is X dropped is recovered by vi's expreserve program **/ X X int stat = 0, pid, w; X#ifdef BSD X union wait status; X#else X int status; X#endif X#ifdef VOIDSIG X register void (*istat)(), (*qstat)(); X# ifdef SIGTSTP X# ifndef BSD X register void (*oldstop)(), (*oldstart)(); X# endif X# endif X#else X register int (*istat)(), (*qstat)(); X# ifdef SIGTSTP X# ifndef BSD X register int (*oldstop)(), (*oldstart)(); X# endif X# endif X#endif X X dprint(2, (debugfile, X "System Call: %s\n\t%s\n", shell_type == SH? "/bin/sh" : shell, X string)); X X if ((pid = vfork()) == 0) { X setgid(groupid); /* and group id */ X setuid(userid); /* back to the normal user! */ X X if(allow_signals) { X /* program to exec should handle interrupt, accidental hangup, and stop signals */ X (void)signal(SIGHUP, SIG_DFL); X (void)signal(SIGINT, SIG_DFL); X#ifdef SIGTSTP X# ifndef BSD X (void)signal(SIGTSTP, SIG_DFL); X (void)signal(SIGCONT, SIG_DFL); X# endif X#endif X } else { X /* program to exec should ignore interrupt, accidental hangup, and stop signals */ X (void)signal(SIGHUP, SIG_IGN); X (void)signal(SIGINT, SIG_IGN); X#ifdef SIGTSTP X# ifndef BSD X (void)signal(SIGTSTP, SIG_IGN); X (void)signal(SIGCONT, SIG_IGN); X# endif X#endif X } X X if (strlen(shell) > 0 && shell_type == USER_SHELL) { X execl(shell, argv_zero(shell), "-c", string, (char *) 0); X } X else X execl("/bin/sh", "sh", "-c", string, (char *) 0); X _exit(127); X } X X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X#ifdef SIGTSTP X# ifndef BSD X oldstop = signal(SIGTSTP, SIG_IGN); X oldstart = signal(SIGCONT, SIG_IGN); X# endif X#endif X X while ((w = wait(&status)) != pid && w != -1) X ; X X#ifdef BSD X if (status.w_retcode != 0) stat = status.w_retcode; X#else X if (w == -1) stat = status; X#endif X X (void)signal(SIGINT, istat); X (void)signal(SIGQUIT, qstat); X#ifdef SIGTSTP X# ifndef BSD X (void)signal(SIGTSTP, oldstop); X (void)signal(SIGCONT, oldstart); X# endif X#endif X X return(stat); X} X Xint Xdo_pipe() X{ X /** pipe the current message or tagged messages to X the specified sequence.. **/ X X char command[SLEN], buffer[SLEN], message_list[SLEN]; X register int ret, to_pipe = 0, i; X int old_raw; X X message_list[0] = '\0'; /* NULL string to start... */ X X for (i=0; i < message_count; i++) X if (ison(headers[i]->status, TAGGED)) { X sprintf(message_list,"%s %d", message_list, X headers[i]->index_number); X to_pipe++; X } X X if (!to_pipe) { X sprintf(message_list,"%d", headers[current-1]->index_number); X to_pipe = 1; X } X sprintf(buffer, "Pipe message%s to: ", plural(to_pipe)); X PutLine0(LINES-2,0,buffer); X X command[0] = '\0'; X X (void) optionally_enter(command, LINES-2, strlen(buffer), FALSE, FALSE); X if (strlen(command) == 0) { X MoveCursor(LINES-2,0); CleartoEOLN(); X return(0); X } X X MoveCursor(LINES,0); CleartoEOLN(); X if (( old_raw = RawState()) == ON) X Raw(OFF); X X if (cursor_control) transmit_functions(OFF); X X sprintf(buffer, "%s -f %s -h %s | %s", X readmsg, X (folder_type == NON_SPOOL ? cur_folder : cur_tempfolder), X message_list, X command); X X ret = system_call(buffer, USER_SHELL, TRUE); X X PutLine0(LINES, 0, "\n\nPress any key to return to ELM."); X if (old_raw == ON) X Raw(ON); X (void) getchar(); X if (cursor_control) transmit_functions(ON); X X if (ret != 0) error1("Return code was %d.", ret); X return(1); X} X Xprint_msg() X{ X /** Print current message or tagged messages using 'printout' X variable. Error message iff printout not defined! **/ X X char buffer[SLEN], filename[SLEN], printbuffer[SLEN]; X char message_list[SLEN]; X register int retcode, to_print = 0, i; X X if (strlen(printout) == 0) { X error("Don't know how to print - option \"printmail\" undefined!"); X return; X } X X message_list[0] = '\0'; /* reset to null... */ X X for (i=0; i < message_count; i++) X if (headers[i]->status & TAGGED) { X sprintf(message_list, "%s %d", message_list, X headers[i]->index_number); X to_print++; X } X X if (! to_print) { X sprintf(message_list," %d", headers[current-1]->index_number); X to_print = 1; X } X X sprintf(filename,"%s%d", temp_print, getpid()); X X if (in_string(printout, "%s")) X sprintf(printbuffer, printout, filename); X else X sprintf(printbuffer, "%s %s", printout, filename); X X sprintf(buffer,"(%s -p -f %s%s > %s; %s 2>&1) > /dev/null", X readmsg, X (folder_type == NON_SPOOL ? cur_folder : cur_tempfolder), X message_list, X filename, X printbuffer); X X dprint(2, (debugfile, "Printing system call...\n")); X X Centerline(LINES, "Queuing..."); X X if ((retcode = system_call(buffer, SH, FALSE)) == 0) { X sprintf(buffer, "Message%s queued up to print.", plural(to_print)); X Centerline(LINES, buffer); X } X else X error1("Printout failed with return code %d.", retcode); X X unlink(filename); /* remove da temp file! */ X} X Xlist_folders(numlines, helpmsg) Xunsigned numlines; Xchar *helpmsg; X{ X /** list the folders in the users FOLDERHOME directory. This is X simply a call to "ls -C" X Numlines is the number of lines to scroll afterwards. This is X useful when a portion of the screen needs to be cleared for X subsequent prompts, but you don't want to overwrite the X list of folders. X Helpmsg is what should be printed before the listing if not NULL. X **/ X X char buffer[SLEN]; X X Raw(OFF); X ClearScreen(); X MoveCursor(LINES, 0); X if(helpmsg) X printf(helpmsg); X sprintf(buffer, "cd %s;ls -C", folders); X printf("\n\rContents of your folder directory:\n\r\n\r"); X system_call(buffer, SH, FALSE); X while(numlines--) X printf("\n\r"); X Raw(ON); X} SHAR_EOF chmod 0444 src/syscall.c || echo "restore of src/syscall.c fails" echo "x - extracting src/utils.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/utils.c && X Xstatic char rcsid[] = "@(#)$Id: utils.c,v 2.22 89/03/25 21:47:33 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.22 $ $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: utils.c,v $ X * Revision 2.22 89/03/25 21:47:33 syd X * Initial 2.2 Release checkin X * X * X ******************************************************************************/ X X/** Utility routines for ELM X X**/ X X#include "headers.h" X#include <sys/types.h> X#include <sys/stat.h> X#include <ctype.h> X#include <errno.h> X X#ifdef BSD X#undef tolower X#endif X X#include <signal.h> X Xextern int errno; X Xchar *error_name(); Xvoid exit(); X Xcreate_new_folders() X{ X /* this creates a new folders directory */ X X char source[SLEN]; X char com[SLEN]; X X X /** Some systems don't have a mkdir call - how inconvienient! **/ X X#ifdef MKDIR X (void) mkdir(folders, 0700); X#else X sprintf(com, "mkdir %s", folders); X system_call(com, SH, FALSE); X sprintf(com, "chmod 700 %s", folders); X system_call(com, SH, FALSE); X#endif /* MKDIR */ X X chown( source, userid, groupid); X} X Xcreate_new_elmdir() X{ X /** this routine is just for allowing new users who don't have the X old elm files to create a new .elm directory **/ X X char source[SLEN]; X char com[SLEN]; X X X /** Some systems don't have a mkdir call - how inconvienient! **/ X X#ifdef MKDIR X sprintf(source, "%s/.elm", home); X (void) mkdir(source, 0700); X#else X sprintf(com, "mkdir %s/.elm", home); X system_call(com, SH, FALSE); X sprintf(com, "chmod 700 %s/.elm", home); X system_call(com, SH, FALSE); X#endif /* MKDIR */ X X chown( source, userid, groupid); X} X Xmove_old_files_to_new() X{ X /** this routine is just for allowing people to transition from X the old Elm, where things are all kept in their $HOME dir, X to the new one where everything is in $HOME/.elm... **/ X X char source[SLEN], dest[SLEN], temp[SLEN]; X char com[SLEN]; X X /** simply go through all the files... **/ X X sprintf(source, "%s/.alias_text", home); X if (access(source, ACCESS_EXISTS) != -1) { X sprintf(dest, "%s/%s", home, ALIAS_TEXT); X printf("\n\rCopying from: %s\n\rCopying to: %s\n\r", source, dest); X X sprintf(temp, "/tmp/%d", getpid()); X sprintf(com, "%s -e 's/:/=/g' %s > %s\n", sed_cmd, source, temp); X (void) system_call(com, SH, FALSE); X sprintf(com, "%s %s %s\n", move_cmd, temp, dest); X (void) system_call(com, SH, FALSE); X (void) system_call("newalias", SH, FALSE); X } X X sprintf(source, "%s/.elmheaders", home); X if (access(source, ACCESS_EXISTS) != -1) { X sprintf(dest, "%s/%s", home, mailheaders); X printf("\n\rCopying from: %s\n\rCopying to: %s\n\r", source, dest); X copy(source, dest); X } X X sprintf(source, "%s/.elmrc", home); X if (access(source, ACCESS_EXISTS) != -1) { X sprintf(dest, "%s/%s", home, elmrcfile); X printf("\n\rCopying from: %s\n\rCopying to: %s\n\r", source, dest); X copy(source, dest); X } X X printf( X "\n\rWelcome to the new version of ELM!\n\n\rHit return to continue."); X getchar(); X} X Xshow_mailfile_stats() X{ X /** when we're about to die, let's try to dump lots of good stuff X to the debug file... **/ X X struct stat buffer; X X if (debug == 0) return; /* Damn! Can't do it! */ X X if (fstat(fileno(mailfile), &buffer) == 0) { SHAR_EOF echo "End of part 21" echo "File src/utils.c is continued in part 22" echo "22" > s2_seq_.tmp exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.