home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume22
/
elm2.3
/
part22
< prev
next >
Wrap
Text File
|
1990-06-07
|
51KB
|
1,868 lines
Subject: v22i081: ELM mail syste, release 2.3, Part22/26
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
X-Checksum-Snefru: 0e2b97fa ddaa5585 f39798e4 27be6325
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
Posting-number: Volume 22, Issue 81
Archive-name: elm2.3/part22
---- Cut Here and unpack ----
#!/bin/sh
# this is part 22 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/showmsg.c continued
#
CurArch=22
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"
sed 's/^X//' << 'SHAR_EOF' >> src/showmsg.c
X sleep(2);
X break;
X }
X if ((buf_len=strlen(buffer)) > 0) {
X if(buffer[buf_len - 1] == '\n') {
X lines--;
X lines_displayed++;
X }
X no_ret(buffer);
X }
X
X if (strlen(buffer) == 0) {
X weed_header = 0; /* past header! */
X weeding_out = 0;
X }
X
X if (form_letter && weed_header)
X /* skip it. NEVER display random headers in forms! */;
X else if (weed_header && matches_weedlist(buffer))
X weeding_out = 1; /* aha! We don't want to see this! */
X else if (buffer[0] == '[') {
X if (strcmp(buffer, START_ENCODE)==0)
X crypted = ON;
X else if (strcmp(buffer, END_ENCODE)==0)
X crypted = OFF;
X else if (crypted) {
X encode(buffer);
X val = show_line(buffer, builtin);
X }
X else
X val = show_line(buffer, builtin);
X }
X else if (crypted) {
X encode(buffer);
X val = show_line(buffer, builtin);
X }
X else if (weeding_out) {
X weeding_out = (whitespace(buffer[0])); /* 'n' line weed */
X if (! weeding_out) /* just turned on! */
X val = show_line(buffer, builtin);
X }
X else if (form_letter && first_word(buffer,"***") && filter) {
X strcpy(buffer,
X"\n------------------------------------------------------------------------------\n");
X val = show_line(buffer, builtin); /* hide '***' */
X form_letter_section++;
X }
X else if (form_letter_section == 1 || form_letter_section == 3)
X /** skip this stuff - we can't deal with it... **/;
X else
X val = show_line(buffer, builtin);
X
X if (val != 0) /* discontinue the display */
X break;
X }
X
X if (cursor_control) transmit_functions(ON);
X
X if (!builtin) {
X fclose(pipe_wr_fp);
X while ((wait_ret = wait(&wait_stat)) != fork_ret
X && wait_ret!= -1)
X ;
X /* turn raw on **after** child terminates in case child
X * doesn't put us back to cooked mode after we return ourselves
X * to raw.
X */
X Raw(ON);
X }
X
X /* If we are to prompt for a user input command and we don't
X * already have one */
X if ((prompt_after_pager || builtin) && val == 0) {
X MoveCursor(LINES,0);
X StartBold();
X Write_to_screen(" Command ('i' to return to index): ", 0);
X EndBold();
X fflush(stdout);
X val = ReadCh();
X }
X
X if (memory_lock) EndMemlock(); /* turn it off!! */
X
X /* 'q' means quit current operation and pop back up to previous level -
X * in this case it therefore means return to index screen.
X */
X return(val == 'i' || val == 'q' ? 0 : val);
X}
X
Xint
Xshow_line(buffer, builtin)
Xchar *buffer;
Xint builtin;
X{
X /** Hands the given line to the output pipe. 'builtin' is true if
X we're using the builtin pager.
X Return the character entered by the user to indicate
X a command other than continuing with the display (only possible
X with the builtin pager), otherwise 0. **/
X
X#ifdef MMDF
X if (strcmp(buffer, MSG_SEPERATOR) == 0)
X strcpy(buffer," ");
X#endif /* MMDF */
X if (builtin) {
X strcat(buffer, "\n");
X return(display_line(buffer));
X }
X errno = 0;
X fprintf(pipe_wr_fp, "%s\n", buffer);
X if (errno != 0)
X dprint(1, (debugfile, "\terror %s hit!\n", error_name(errno)));
X return(0);
X}
SHAR_EOF
echo "File src/showmsg.c is complete"
chmod 0444 src/showmsg.c || echo "restore of src/showmsg.c fails"
echo "x - extracting src/showmsg_c.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/showmsg_c.c &&
X
Xstatic char rcsid[] = "@(#)$Id: showmsg_c.c,v 4.1 90/04/28 22:44:08 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: showmsg_c.c,v $
X * Revision 4.1 90/04/28 22:44:08 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This is an interface for the showmsg command line. The possible
X functions that could be invoked from the showmsg command line are
X almost as numerous as those from the main command line and include
X the following;
X
X | = pipe this message to command...
X ! = call Unix command
X < = scan message for calendar info
X b = bounce (remail) message
X d = mark message for deletion
X f = forward message
X g = group reply
X h = redisplay this message from line #1, showing headers
X <CR> = redisplay this message from line #1, weeding out headers
X i,q = move back to the index page (simply returns from function)
X J = move to body of next message
X j,n = move to body of next undeleted message
X K = move to body of previous message
X k = move to body of previous undeleted message
X m = mail a message out to someone
X p = print this (all tagged) message
X r = reply to this message
X s = save this message to a maibox/folder
X t = tag this message
X u = undelete message
X x = Exit Elm NOW
X
X all commands not explicitly listed here are beeped at. Use i)ndex
X to get back to the main index page, please.
X
X This function returns when it is ready to go back to the index
X page.
X**/
X
X#include "headers.h"
X
Xint screen_mangled = 0;
Xchar msg_line[SLEN];
X#define store_msg(a) (void)strcpy(msg_line,a)
X#define put_prompt() PutLine0(LINES-3, 0, "Command:")
X#define put_help() PutLine0(LINES-3, 45, "(Use 'i' to return to index.)")
X#define POST_PROMPT_COL strlen("Command: ")
X
X
Xint
Xprocess_showmsg_cmd(command)
Xint command;
X{
X int i, intbuf; /* for dummy parameters...etc */
X int ch; /* for arrow keys */
X int key_offset; /* for arrow keys */
X int istagged; /* for tagging and subsequent msg */
X
X Raw(ON);
X
X while (TRUE) {
X clear_error();
X switch (command) {
X case '?' : if (help(TRUE)) {
X ClearScreen();
X build_bottom();
X } else screen_mangled = TRUE;
X break;
X
X case '|' : put_cmd_name("Pipe", TRUE);
X (void) do_pipe(); /* do pipe - ignore return val */
X ClearScreen();
X build_bottom();
X break;
X
X#ifdef ALLOW_SUBSHELL
X case '!' : put_cmd_name("System call", TRUE);
X (void) subshell();
X ClearScreen();
X build_bottom();
X break;
X#endif
X
X case '<' :
X#ifdef ENABLE_CALENDAR
X put_cmd_name("Scan messages for calendar entries", TRUE);
X scan_calendar();
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' : put_cmd_name("Exit", TRUE);
X exit_prog();
X break;
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 = ReadCh(); /* 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
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 4.1 90/04/28 22:44:10 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: signals.c,v $
X * Revision 4.1 90/04/28 22:44:10 syd
X * checkin of Elm 2.3 as of Release PL0
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
X#ifdef VOIDSIG
Xtypedef void sighan_type;
X#else
Xtypedef int sighan_type;
X#endif
X
Xextern int pipe_abort; /* set to TRUE if receive SIGPIPE */
X
Xsighan_type
Xquit_signal()
X{
X dprint(1, (debugfile, "\n\n** Received SIGQUIT **\n\n\n\n"));
X leave();
X}
X
Xsighan_type
Xhup_signal()
X{
X dprint(1, (debugfile, "\n\n** Received SIGHUP **\n\n\n\n"));
X leave();
X}
X
Xsighan_type
Xterm_signal()
X{
X dprint(1, (debugfile, "\n\n** Received SIGTERM **\n\n\n\n"));
X leave();
X}
X
Xsighan_type
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
Xsighan_type
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
Xsighan_type
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
Xsighan_type
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
Xsighan_type
Xalarm_signal()
X{
X /** silently process alarm signal for timeouts... **/
X#ifdef BSD
X if (InGetPrompt)
X longjmp(GetPromptBuf, 1);
X#else
X signal(SIGALRM, alarm_signal);
X#endif
X}
X
Xsighan_type
Xpipe_signal()
X{
X /** silently process pipe signal... **/
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
Xsighan_type
Xsig_user_stop()
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
Xsighan_type
Xsig_return_from_user_stop()
X{
X /** this is called when returning from a ^Z stop **/
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#ifdef BSD
X if (InGetPrompt)
X longjmp(GetPromptBuf, 1);
X#endif
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 4.1 90/04/28 22:44:11 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: softkeys.c,v $
X * Revision 4.1 90/04/28 22:44:11 syd
X * checkin of Elm 2.3 as of Release PL0
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 4.1 90/04/28 22:44:12 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: sort.c,v $
X * Revision 4.1 90/04/28 22:44:12 syd
X * checkin of Elm 2.3 as of Release PL0
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 if (entries > 1)
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 long diff;
X
X first = *p1;
X second = *p2;
X
X switch (abs(sortby)) {
X case SENT_DATE:
X diff = first->time_sent - second->time_sent;
X if ( diff < 0 ) ret = -1;
X else if ( diff > 0 ) ret = 1;
X else ret = 0;
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 4.1 90/04/28 22:44:14 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: string2.c,v $
X * Revision 4.1 90/04/28 22:44:14 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This file contains string functions that are shared throughout the
X various ELM utilities...
X
X**/
X
X#include "headers.h"
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower
X#undef toupper
X#endif
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[VERY_LONG_STRING];
X register char *bufptr = buffer;
X
X for (; *string; string++, bufptr++)
X if (isupper(*string))
X *bufptr = tolower(*string);
X else
X *bufptr = *string;
X
X *bufptr = 0;
X
X return( (char *) buffer);
X}
X
X
Xint
Xin_list(list, target)
Xchar *list, *target;
X
X{
X /* Returns TRUE iff target is an item in the list - case ignored.
X * If target is simple (an atom of an address) match must be exact.
X * If target is complex (contains a special character that separates
X * address atoms), the target need only match a whole number of atoms
X * at the right end of an item in the list. E.g.
X * target: item: match:
X * joe joe yes
X * joe jojoe no (wrong logname)
X * joe machine!joe no (similar logname on a perhaps
X * different machine - to
X * test this sort of item the
X * passed target must include
X * proper machine name, is
X * in next two examples)
X * machine!joe diffmachine!joe no "
X * machine!joe diffmachine!machine!joe yes
X * joe@machine jojoe@machine no (wrong logname)
X * joe@machine diffmachine!joe@machine yes
X */
X
X register char *rest_of_list,
X *next_item,
X ch;
X int offset;
X char *shift_lower(),
X lower_list[VERY_LONG_STRING],
X lower_target[SLEN];
X
X rest_of_list = strcpy(lower_list, shift_lower(list));
X strcpy(lower_target, shift_lower(target));
X while((next_item = strtok(rest_of_list, ", \t\n")) != NULL) {
X /* see if target matches the whole item */
X if(strcmp(next_item, lower_target) == 0)
X return(TRUE);
X
X if(strpbrk(lower_target,"!@%:") != NULL) {
X
X /* Target is complex */
X
X if((offset = strlen(next_item) - strlen(lower_target)) > 0) {
X
X /* compare target against right end of next item */
X if(strcmp(&next_item[offset], lower_target) == 0) {
X
X /* make sure we are comparing whole atoms */
X ch=next_item[offset-1];
X if(ch == '!' || ch == '@' || ch == '%' || ch == ':')
X return(TRUE);
X }
X }
X }
X rest_of_list = NULL;
X }
X return(FALSE);
X}
X
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, len;
X
X for (i=0, len = strlen(string); i<len; 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;
X
X for (; *string; string++)
X if (*string == 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); --i >= 0 && whitespace(string[i]); )
X /** spin backwards, semicolon intented **/ ;
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 4.1 90/04/28 22:44:16 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: strings.c,v $
X * Revision 4.1 90/04/28 22:44:16 syd
X * checkin of Elm 2.3 as of Release PL0
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(),
X *get_token(), *strip_parens(), *argv_zero(), *strcpy(), *strncpy();
X
Xchar *index();
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
X/**
X This routine will return true if the "addr" contains the "user" subject
X to the following contstraints: (1) either the "user" is at the front
X of "addr" or it is preceded by an appropriate meta-char, and (2)
X either the "user" is at the end of "addr" or it is suceeded by an
X appropriate meta-char.
X**/
Xint addr_matches_user(addr,user)
Xregister char *addr, *user;
X{
X int len = strlen(user);
X static char c_before[] = "!:%"; /* these can appear before a username */
X static char c_after[] = ":%@"; /* these can appear after a username */
X
X do {
X if ( strncmp(addr,user,len) == 0 ) {
X if ( addr[len] == '\0' || index(c_after,addr[len]) != NULL )
X return TRUE;
X }
X } while ( (addr=strpbrk(addr,c_before)) != NULL && *++addr != '\0' ) ;
X return FALSE;
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", hostfullname);
X if (chloc(from,'!') != -1 && in_string(from, buffer))
X from[strlen(from)-strlen(buffer)] = '\0';
X
X#endif
X
X /**
X Produce a simplified version of the from into buffer. If the
X from is just "username" or "Full Username" it will be preserved.
X If it is an address, the rightmost "stuff!stuff", "stuff@stuff",
X or "stuff:stuff" will be used.
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 buffer[i] = '\0';
X reverse(buffer);
X
X#ifdef MMDF
X if (strlen(buffer) == 0) {
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#endif /* MMDF */
X
X if ( strcmp(buffer,full_username) == 0 ||
X addr_matches_user(buffer,username) ) {
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, len;
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), len = strlen(word); i<len; i++)
X ret_buffer[iindex++] = word[i];
X current_length = len + 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), len = strlen(word); i<len; i++)
X ret_buffer[iindex++] = word[i];
X current_length += len;
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 char *strptr = string;
X
X for (; *strptr; strptr++)
X if (*strptr == COMMA)
X *strptr = 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 depth = 0, buffer_index = 0;
X
X for (; *string; string++) {
X if (*string == '(')
X depth++;
X else if (*string == ')')
X depth--;
X else if (depth == 0)
X buffer[buffer_index++] = *string;
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 /** skip leading white space, just in case.. **/
X
X while(whitespace(*buffer)) buffer++;
X
X /** now copy into 'first' until we hit white space or EOLN **/
X
X for (; *buffer && ! whitespace(*buffer); buffer++, first++)
X if (islower(*buffer))
X *first = tolower(*buffer);
X else
X *first = *buffer;
X
X *first = '\0';
X
X while (whitespace(*buffer)) buffer++;
X
X for (; *buffer; buffer++, rest++)
X if (islower(*buffer))
X *rest = tolower(*buffer);
X else
X *rest = *buffer;
X
X *rest = '\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, len;
X
X for (iindex=0, len = strlen(string);! whitespace(string[iindex]) && iindex < len;
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
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}
X
X
Xquote_args(out_string,in_string)
Xregister char *out_string, *in_string;
X{
X /** Copy from "in_string" to "out_string", collapsing multiple
X white space and quoting each word. Returns a pointer to
X the resulting word.
X **/
X
X int empty_string = TRUE;
X
X while ( *in_string != '\0' ) {
X
X /** If this is a space then advance to the start of the next word.
X Otherwise, copy through the word surrounded by quotes.
X **/
X
X if ( isspace(*in_string) ) {
X while ( isspace(*in_string) )
X ++in_string;
X } else {
X *out_string++ = '"';
X while ( *in_string != '\0' && !isspace(*in_string) )
X *out_string++ = *in_string++;
X *out_string++ = '"';
X *out_string++ = ' ';
X empty_string = FALSE;
X }
X
X }
X
X if ( !empty_string )
X --out_string;
X *out_string = '\0';
X}
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 4.1 90/04/28 22:44:18 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: syscall.c,v $
X * Revision 4.1 90/04/28 22:44:18 syd
X * checkin of Elm 2.3 as of Release PL0
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
X#ifdef ALLOW_SUBSHELL
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];
SHAR_EOF
echo "End of part 22"
echo "File src/syscall.c is continued in part 23"
echo "23" > s2_seq_.tmp
exit 0
exit 0 # Just in case...