v18i100: Elm mail system, release 2.2, Part21/24
Rich Salz
rsalz at uunet.uu.net
Fri Apr 14 07:19:27 AEST 1989
Submitted-by: dsinc!syd at 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 at 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 at 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 at 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 at 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 at 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 at c we want to get back a at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list