home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume9
/
elm2
/
part12
< prev
next >
Wrap
Text File
|
1987-03-09
|
55KB
|
2,044 lines
Subject: v09i012: ELM Mail System, Part12/19
Newsgroups: mod.sources
Approved: rs@mirror.TMC.COM
Submitted by: Dave Taylor <hplabs!taylor>
Mod.sources: Volume 9, Issue 12
Archive-name: elm2/Part12
#! /bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
# "End of archive 12 (of 19)."
# Contents: src/curses.q src/editmsg.c src/leavembox.c utils/readmsg.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"src/curses.q\" \(11832 characters\)
if test -f src/curses.q ; then
echo shar: Will not over-write existing file \"src/curses.q\"
else
sed "s/^X//" >src/curses.q <<'END_OF_src/curses.q'
X/** curses.c **/
X
X/** This library gives programs the ability to easily access the
X termcap information and write screen oriented and raw input
X programs. The routines can be called as needed, except that
X to use the cursor / screen routines there must be a call to
X InitScreen() first. The 'Raw' input routine can be used
X independently, however.
X
X Modified 2/86 to work (hopefully) on Berkeley systems. If
X there are any problems with BSD Unix, please report them to
X the author at hpcnoe!dat@HPLABS (fixed, if possible!)
X
X (C) Copyright 1985 Dave Taylor, HP Colorado Networks
X**/
X
X#include "headers.h"
X
X#ifdef RAWMODE
X# ifdef BSD
X# include <sgtty.h>
X# else
X# include <termio.h>
X# endif
X#endif
X
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower
X#endif
X#include "curses.h"
X
X#ifdef BSD
X# include "/usr/include/curses.h" /* don't ask! */
X#endif
X
X#ifdef RAWMODE
X# define TTYIN 0
X#endif
X
Xextern int debug;
X
X#ifdef RAWMODE
X# ifndef BSD
X struct termio _raw_tty,
X _original_tty;
X# endif
X
Xstatic int _inraw = 0; /* are we IN rawmode? */
Xstatic int _line = -1, /* initialize to "trash" */
X _col = -1;
X
X#ifdef UTS
Xstatic int _clear_screen = 0; /* Next i/o clear screen? */
Xstatic char _null_string[SLEN]; /* a string of nulls... */
X#endif
X
X#endif
X
Xstatic int _intransmit; /* are we transmitting keys? */
X
Xstatic
Xchar *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
X *_setbold, *_clearbold, *_setunderline, *_clearunderline,
X *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
X *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off;
Xstatic
Xint
X _lines, _columns;
X
Xstatic char _terminal[1024]; /* Storage for terminal entry */
Xstatic char _capabilities[256]; /* String for cursor motion */
X
Xstatic char *ptr = _capabilities; /* for buffering */
X
Xint outchar(); /* char output for tputs */
X
XInitScreen()
X{
X /* Set up all this fun stuff: returns zero if all okay, or;
X -1 indicating no terminal name associated with this shell,
X -2..-n No termcap for this terminal type known
X */
X
X int tgetent(), /* get termcap entry */
X error;
X char *tgetstr(), /* Get termcap capability */
X termname[40];
X
X#ifdef SUN
X if (getenv("TERM") == NULL)
X return(-1);
X#endif
X
X#ifdef UTS
X
X /* use _line for lack of a better variable, what the heck! */
X
X for (_line = 0; _line < SLEN; _line++)
X _null_string[_line] = '\0';
X#endif
X
X if (strcpy(termname, getenv("TERM")) == NULL)
X return(-1);
X
X if ((error = tgetent(_terminal, termname)) != 1)
X return(error-2);
X
X _line = 1; /* where are we right now?? */
X _col = 1; /* assume zero, zero... */
X
X /* load in all those pesky values */
X _clearscreen = tgetstr("cl", &ptr);
X _moveto = tgetstr("cm", &ptr);
X _up = tgetstr("up", &ptr);
X _down = tgetstr("do", &ptr);
X _right = tgetstr("nd", &ptr);
X _left = tgetstr("bs", &ptr);
X _setbold = tgetstr("so", &ptr);
X _clearbold = tgetstr("se", &ptr);
X _setunderline = tgetstr("us", &ptr);
X _clearunderline = tgetstr("ue", &ptr);
X _setinverse = tgetstr("so", &ptr);
X _clearinverse = tgetstr("se", &ptr);
X _sethalfbright = tgetstr("hs", &ptr);
X _clearhalfbright = tgetstr("he", &ptr);
X _cleartoeoln = tgetstr("ce", &ptr);
X _cleartoeos = tgetstr("cd", &ptr);
X _lines = tgetnum("li");
X _columns = tgetnum("co");
X _transmit_on = tgetstr("ks", &ptr);
X _transmit_off = tgetstr("ke", &ptr);
X
X
X if (!_left) {
X _left = ptr;
X *ptr++ = '\b';
X *ptr++ = '\0';
X }
X
X#ifdef BSD
X initscr(); /* initalize curses too! */
X#endif
X
X return(0);
X}
X
Xchar *return_value_of(termcap_label)
Xchar *termcap_label;
X{
X /** This will return the string kept by termcap for the
X specified capability. Modified to ensure that if
X tgetstr returns a pointer to a transient address
X that we won't bomb out with a later segmentation
X fault (thanks to Dave@Infopro for this one!) **/
X
X static char escape_sequence[20];
X
X char *tgetstr(); /* Get termcap capability */
X
X strcpy(escape_sequence, tgetstr(termcap_label, &ptr));
X return( (char *) escape_sequence);
X}
X
Xtransmit_functions(newstate)
Xint newstate;
X{
X /** turn function key transmission to ON | OFF **/
X
X if (newstate != _intransmit) {
X _intransmit = ! _intransmit;
X if (newstate == ON)
X tputs(_transmit_on, 1, outchar);
X else
X tputs(_transmit_off, 1, outchar);
X
X fflush(stdout); /* clear the output buffer */
X }
X}
X
X/****** now into the 'meat' of the routines...the cursor stuff ******/
X
XScreenSize(lines, columns)
Xint *lines, *columns;
X{
X /** returns the number of lines and columns on the display. **/
X
X *lines = _lines - 1; /* assume index from zero */
X *columns = _columns;
X}
X
XClearScreen()
X{
X /* clear the screen: returns -1 if not capable */
X
X#ifdef UTS
X if (isatube) {
X _clear_screen++; /* queue up for clearing... */
X return(0);
X }
X#endif
X
X if (!_clearscreen)
X return(-1);
X
X tputs(_clearscreen, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X return(0);
X}
X
XMoveCursor(row, col)
Xint row, col;
X{
X /** move cursor to the specified row column on the screen.
X 0,0 is the top left! **/
X
X char *tgoto();
X char *stuff;
X
X _line = row; /* update current location... */
X _col = col;
X
X#ifdef UTS
X if (isatube) {
X at row, col;
X return(0);
X }
X#endif
X if (!_moveto)
X return(-1);
X
X stuff = (char *) tgoto(_moveto, col, row);
X tputs(stuff, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XCursorUp()
X{
X /** move the cursor up one line **/
X
X _line = (_line> 0? _line - 1: _line); /* up one line... */
X
X#ifdef UTS
X if (isatube) {
X at _line, _col;
X return(0);
X }
X#endif
X if (!_up)
X return(-1);
X
X tputs(_up, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XCursorDown()
X{
X /** move the cursor down one line **/
X
X _line = (_line< LINES? _line + 1: _line); /* up one line... */
X
X#ifdef UTS
X if (isatube) {
X at _line, _col ;
X return(0);
X }
X#endif
X
X if (!_down)
X return(-1);
X
X tputs(_down, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XCursorLeft()
X{
X /** move the cursor one character to the left **/
X
X _col = (_col > 0? _col - 1: _col); /* up one line... */
X
X#ifdef UTS
X if (isatube) {
X at _line, _col;
X return(0);
X }
X#endif
X
X if (!_left)
X return(-1);
X
X tputs(_left, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XCursorRight()
X{
X /** move the cursor one character to the right (nondestructive) **/
X
X _col = (_col < COLUMNS? _col + 1: _col); /* up one line... */
X
X#ifdef UTS
X if (isatube) {
X at _line, _col;
X return(0);
X }
X#endif
X
X if (!_right)
X return(-1);
X
X tputs(_right, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XStartBold()
X{
X /** start boldface/standout mode **/
X
X if (!_setbold)
X return(-1);
X
X tputs(_setbold, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XEndBold()
X{
X /** compliment of startbold **/
X
X if (!_clearbold)
X return(-1);
X
X tputs(_clearbold, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XStartUnderline()
X{
X /** start underline mode **/
X
X if (!_setunderline)
X return(-1);
X
X tputs(_setunderline, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XEndUnderline()
X{
X /** the compliment of start underline mode **/
X
X if (!_clearunderline)
X return(-1);
X
X tputs(_clearunderline, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XStartHalfbright()
X{
X /** start half intensity mode **/
X
X if (!_sethalfbright)
X return(-1);
X
X tputs(_sethalfbright, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
XEndHalfbright()
X{
X /** compliment of starthalfbright **/
X
X if (!_clearhalfbright)
X return(-1);
X
X tputs(_clearhalfbright, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
XStartInverse()
X{
X /** set inverse video mode **/
X
X if (!_setinverse)
X return(-1);
X
X tputs(_setinverse, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
X
XEndInverse()
X{
X /** compliment of startinverse **/
X
X if (!_clearinverse)
X return(-1);
X
X tputs(_clearinverse, 1, outchar);
X fflush(stdout);
X return(0);
X}
X
XPutLine0(x, y, line)
Xint x,y;
Xchar *line;
X{
X /** Write a zero argument line at location x,y **/
X
X _line = x;
X _col = y;
X
X#ifdef UTS
X if (isatube) {
X panel (erase=_clear_screen, cursor=_line, _col) {
X #ON, line, strlen(line)-1#
X }
X _clear_screen = 0;
X _col += (printable_chars(line) - 1);
X return(0);
X }
X#endif
X MoveCursor(x,y);
X printf("%s", line); /* to avoid '%' problems */
X fflush(stdout);
X _col += (printable_chars(line) - 1);
X}
X
XPutLine1(x,y, line, arg1)
Xint x,y;
Xchar *line;
Xchar *arg1;
X{
X /** write line at location x,y - one argument... **/
X
X char buffer[SLEN];
X
X sprintf(buffer, line, arg1);
X
X PutLine0(x, y, buffer);
X}
X
XPutLine2(x,y, line, arg1, arg2)
Xint x,y;
Xchar *line;
Xchar *arg1, *arg2;
X{
X /** write line at location x,y - one argument... **/
X
X char buffer[SLEN];
X
X sprintf(buffer, line, arg1, arg2);
X
X PutLine0(x, y, buffer);
X}
X
XPutLine3(x,y, line, arg1, arg2, arg3)
Xint x,y;
Xchar *line;
Xchar *arg1, *arg2, *arg3;
X{
X /** write line at location x,y - one argument... **/
X
X char buffer[SLEN];
X
X sprintf(buffer, line, arg1, arg2, arg3);
X
X PutLine0(x, y, buffer);
X}
X
XCleartoEOLN()
X{
X /** clear to end of line **/
X#ifdef UTS
X char buffer[SLEN];
X register int cols, i = 0;
X
X if (isatube) {
X
X for (cols = _col; cols < COLUMNS; cols++)
X buffer[i++] = ' ';
X
X buffer[i] = '\0';
X
X panel (noerase, cursor=_line, _col) {
X #ON, buffer, strlen(buffer)-1#
X }
X }
X#endif
X
X if (!_cleartoeoln)
X return(-1);
X
X tputs(_cleartoeoln, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X return(0);
X}
X
XCleartoEOS()
X{
X /** clear to end of screen **/
X
X#ifdef UTS
X register int line_at;
X
X for (line_at = _line; line_at < LINES-1; line_at++) {
X panel (noerase) {
X #ON, _null_string, COLUMNS#
X }
X }
X return(0);
X
X#endif
X
X if (!_cleartoeos)
X return(-1);
X
X tputs(_cleartoeos, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X return(0);
X}
X
X#ifdef RAWMODE
X
XRaw(state)
Xint state;
X{
X /** state is either ON or OFF, as indicated by call **/
X
X if (state == OFF && _inraw) {
X#ifdef BSD
X echo();
X nocrmode();
X#else
X (void) ioctl(TTYIN, TCSETAW, &_original_tty);
X#endif
X _inraw = 0;
X }
X else if (state == ON && ! _inraw) {
X#ifdef BSD
X noecho();
X crmode();
X#else
X (void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/
X
X (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/
X _raw_tty.c_iflag &= ~(INLCR | ICRNL |BRKINT);
X _raw_tty.c_iflag |= IXON;
X _raw_tty.c_oflag |= OPOST;
X _raw_tty.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET);
X _raw_tty.c_lflag &= ~(ICANON | ECHO);
X _raw_tty.c_cc[VMIN] = '\01';
X _raw_tty.c_cc[VTIME] = '\0';
X (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
X#endif
X
X _inraw = 1;
X }
X}
X
Xint
XReadCh()
X{
X /** read a character with Raw mode set! **/
X
X register int result;
X char ch;
X
X result = read(0, &ch, 1);
X
X return(result == 0? EOF : ch);
X}
X
X#endif
X
Xoutchar(c)
Xchar c;
X{
X /** output the given character. From tputs... **/
X /** Note: this CANNOT be a macro! **/
X
X putc(c, stdout);
X}
END_OF_src/curses.q
if test 11832 -ne `wc -c <src/curses.q`; then
echo shar: \"src/curses.q\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/editmsg.c\" \(12220 characters\)
if test -f src/editmsg.c ; then
echo shar: Will not over-write existing file \"src/editmsg.c\"
else
sed "s/^X//" >src/editmsg.c <<'END_OF_src/editmsg.c'
X/** editmsg.c **/
X
X/** This contains routines to do with starting up and using an editor (or two)
X from within Elm. This stuff used to be in mailmsg2.c...
X
X (C) Copyright 1986, Dave Taylor
X**/
X
X#include "headers.h"
X#include <errno.h>
X#include <setjmp.h>
X#include <signal.h>
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy();
Xunsigned long sleep();
X
Xint
Xedit_the_message(filename, already_has_text)
Xchar *filename;
Xint already_has_text;
X{
X /** Invoke the users editor on the filename. Return when done.
X If 'already has text' then we can't use the no-editor option
X and must use 'alternative editor' (e.g. $EDITOR or default_editor)
X instead... **/
X
X char buffer[SLEN];
X register int stat, return_value = 0;
X
X buffer[0] = '\0';
X
X if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
X if (already_has_text)
X sprintf(buffer, "%s %s", alternative_editor, filename);
X else
X return(no_editor_edit_the_message(filename));
X }
X
X PutLine0(LINES, 0, "invoking editor..."); fflush(stdout);
X if (strlen(buffer) == 0)
X sprintf(buffer,"%s %s", editor, filename);
X
X Raw(OFF);
X
X chown(filename, userid, groupid); /* file was owned by root! */
X
X if (cursor_control)
X transmit_functions(OFF); /* function keys are local */
X
X if ((stat = system_call(buffer, SH)) != 0) {
X dprint1(1,"System call failed with stat %d (edit_the_message)\n",
X stat);
X error1("Can't invoke editor '%s' for composition", editor);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X ClearLine(LINES-1);
X sleep(2);
X return_value = 1;
X }
X
X if (cursor_control)
X transmit_functions(ON); /* function keys are local */
X
X Raw(ON);
X
X return(return_value);
X}
X
Xextern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING],
X expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING],
X subject[SLEN];
X
Xint interrupts_while_editing; /* keep track 'o dis stuff */
Xjmp_buf edit_location; /* for getting back from interrupt */
X
X#ifdef ALLOW_BCC
Xextern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X#endif
X
Xchar *strip_commas();
X
Xint
Xno_editor_edit_the_message(filename)
Xchar *filename;
X{
X /** If the current editor is set to either "builtin" or "none", then
X invoke this program instead. As it turns out, this and the
X routine above have a pretty incestuous relationship (!)...
X **/
X
X FILE *edit_fd;
X char buffer[SLEN], editor_name[SLEN];
X int edit_interrupt(), (*oldint)(), (*oldquit)();
X
X Raw(OFF);
X
X if ((edit_fd = fopen(filename, "a")) == NULL) {
X error2("Couldn't open %s for appending [%s]", filename,
X error_name(errno));
X sleep (2);
X dprint1(1,"Error encountered trying to open file %s;\n", filename);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X Raw(ON);
X return(1);
X }
X
X /** file open...let's start accepting input! **/
X
X printf(
X "\nPlease enter message, ^D to end, or ~? <RETURN> for help;\n\n");
X
X oldint = signal(SIGINT, edit_interrupt);
X oldquit = signal(SIGQUIT, edit_interrupt);
X
X interrupts_while_editing = 0;
X
Xmore_input:
X
X while (gets(buffer) != NULL) {
X
X if (setjmp(edit_location) != 0) {
X if (interrupts_while_editing > 1) {
X Raw(ON);
X
X (void) signal(SIGINT, oldint);
X (void) signal(SIGQUIT, oldquit);
X
X if (edit_fd != NULL) /* insurance... */
X fclose(edit_fd);
X return(1);
X }
X goto more_input; /* read input again, please! */
X }
X
X interrupts_while_editing = 0; /* reset to zero... */
X
X if (strcmp(buffer, ".") == 0)
X break; /* '.' is as good as a ^D to us dumb programs :-) */
X if (buffer[0] == TILDE)
X switch (tolower(buffer[1])) {
X case '?' : tilde_help(); printf("(continue)\n"); goto more_input;
X case '~' : move_left(buffer, 1); goto tilde_input; /*!!*/
X
X case 't' : get_with_expansion("To: ", to, expanded_to); break;
X#ifdef ALLOW_BCC
X case 'b' : get_with_expansion("Bcc: ", bcc,expanded_bcc); break;
X#endif
X case 'c' : get_with_expansion("Cc: ", cc, expanded_cc); break;
X case 's' : get_with_expansion("Subject: ", subject,NULL); break;
X
X case 'h' : get_with_expansion("To: ", to, expanded_to);
X get_with_expansion("Cc: ", cc, expanded_cc);
X#ifdef ALLOW_BCC
X get_with_expansion("Bcc: ", bcc,expanded_bcc);
X#endif
X get_with_expansion("Subject: ", subject,NULL); break;
X
X case 'r' : read_in_file(edit_fd, (char *) buffer + 2);
X goto more_input;
X case 'e' : if (strlen(emacs_editor) > 0)
X if (access(emacs_editor, ACCESS_EXISTS) == 0) {
X strcpy(buffer, editor);
X strcpy(editor, emacs_editor);
X fclose(edit_fd);
X (void) edit_the_message(filename,0);
X Raw(OFF);
X strcpy(editor, buffer);
X edit_fd = fopen(filename, "a");
X printf("(continue entering message, ^D to end)\n");
X goto more_input;
X }
X else
X printf(
X "(Can't find Emacs on this system! continue)\n");
X else
X printf(
X "(Don't know where Emacs would be...continue)\n");
X goto more_input;
X
X case 'v' : strcpy(buffer, editor);
X strcpy(editor, default_editor);
X fclose(edit_fd);
X (void) edit_the_message(filename,0);
X Raw(OFF);
X strcpy(editor, buffer);
X edit_fd = fopen(filename, "a");
X printf("(continue entering message, ^D to end)\n");
X goto more_input;
X
X case 'o' : printf("Please enter the name of the editor : ");
X gets(editor_name);
X if (strlen(editor_name) > 0) {
X strcpy(buffer, editor);
X strcpy(editor, editor_name);
X fclose(edit_fd);
X (void) edit_the_message(filename,0);
X Raw(OFF);
X strcpy(editor, buffer);
X edit_fd = fopen(filename, "a");
X printf("(continue entering message, ^D to end)\n");
X goto more_input;
X }
X printf("(continue)\n");
X goto more_input;
X case '!' : if (strlen(buffer) < 3)
X (void) system_call(shell, USER_SHELL);
X else
X (void) system_call((char *) buffer+2, USER_SHELL);
X printf("(continue)\n");
X goto more_input;
X case 'm' : /* same as 'f' but with leading prefix added */
X case 'f' : /* this can be directly translated into a
X 'readmsg' call with the same params! */
X read_in_messages(edit_fd, (char *) buffer + 1);
X goto more_input;
X case 'p' : /* print out message so far. Soooo simple! */
X print_message_so_far(edit_fd, filename);
X goto more_input;
X default : printf(
X "(don't know what ~%c is. Try ~? for help)\n",
X buffer[1]);
X }
X else
Xtilde_input:
X fprintf(edit_fd, "%s\n", buffer);
X };
X
X printf("<end-of-message>\n\n");
X
X Raw(ON);
X
X (void) signal(SIGINT, oldint);
X (void) signal(SIGQUIT, oldquit);
X
X if (edit_fd != NULL) /* insurance... */
X fclose(edit_fd);
X
X return(0);
X}
X
Xtilde_help()
X{
X /* a simple routine to print out what is available at this level */
X
X printf(
X"(Available 'tilde' commands at this point are;\n\
X\n\
X\t~?\tPrint this help menu\n\
X\t~~\tAdd line prefixed by a single '~' character\n");
X
X#ifdef ALLOW_BCC
X printf("\
X\t~b\tChange the addresses in the Blind-carbon-copy list\n");
X#endif
X
X printf("\
X\t~c\tChange the addresses in the Carbon-copy list\n\
X\t~e\tInvoke the Emacs editor on the message, if possible\n\
X\t~f\tadd the specified list of messages, or current\n");
X#ifdef ALLOW_BCC
X printf("\t~h\tchange all available headers (to,cc,bcc,subject)\n");
X#endif
X printf("\
X\t~m\tsame as '~f', but with the current 'prefix'\n\
X\t~o\tInvoke a user specified editor on the message\n\
X\t~p\tprint out message as typed in so far\n\
X\t~r\tRead in the specified file\n\
X\t~s\tChange the subject of the message\n\
X\t~t\tChange the addresses in the To list\n\
X\t~v\tInvoke the Vi visual editor on the message\n\
X\t~!\texecute a unix command (or give a shell if no command)\n\
X\n");
X
X}
X
Xread_in_file(fd, filename)
XFILE *fd;
Xchar *filename;
X{
X /** Open the specified file and stream it in to the already opened
X file descriptor given to us. When we're done output the number
X of lines we added, if any... **/
X
X FILE *myfd;
X char myfname[SLEN], buffer[LONG_SLEN];
X register int lines = 0;
X
X while (whitespace(filename[lines])) lines++;
X
X strcpy(myfname, (char *) filename + lines);
X
X if (strlen(myfname) == 0) {
X printf("(no filename specified for file read! Continue...)\n");
X return;
X }
X
X if ((myfd = fopen(myfname,"r")) == NULL) {
X printf("(Couldn't open file '%s' for reading! Continue...)\n",
X myfname);
X return;
X }
X
X lines = 0;
X
X while (fgets(buffer, LONG_SLEN, myfd) != NULL) {
X lines++;
X fputs(buffer, fd);
X fflush(stdout);
X }
X
X fclose(myfd);
X
X printf("(added %d line%s from file %s. Please continue...)\n",
X lines, plural(lines), myfname);
X return;
X}
X
Xprint_message_so_far(edit_fd, filename)
XFILE *edit_fd;
Xchar *filename;
X{
X /** This prints out the message typed in so far. We accomplish
X this in a cheap manner - close the file, reopen it for reading,
X stream it to the screen, then close the file, and reopen it
X for appending. Simple, but effective!
X
X A nice enhancement would be for this to -> page <- the message
X if it's sufficiently long. Too much work for now, though.
X **/
X
X char buffer[LONG_SLEN];
X
X fclose(edit_fd);
X
X if ((edit_fd = fopen(filename, "r")) == NULL) {
X printf("\nMayday! Mayday! Mayday!\n");
X printf("\nPanic: Can't open file for reading! Bail!\n");
X emergency_exit();
X }
X
X printf("To: %s\n", format_long(to, 4));
X printf("Cc: %s\n", format_long(cc, 4));
X#ifdef ALLOW_BCC
X printf("Bcc: %s\n", format_long(bcc, 5));
X#endif
X printf("Subject: %s\n\n", subject);
X
X while (fgets(buffer, LONG_SLEN, edit_fd) != NULL)
X printf("%s", buffer);
X
X fclose(edit_fd);
X
X if ((edit_fd = fopen(filename, "a")) == NULL) {
X printf("Mayday! Mayday! Abandon Ship! Aiiieeeeee\n");
X printf("\nPanic: Can't reopen file for appending!\n");
X emergency_exit();
X }
X
X printf("(continue entering message, please)\n\n");
X}
X
Xread_in_messages(fd, buffer)
XFILE *fd;
Xchar *buffer;
X{
X /** Read the specified messages into the open file. If the
X first character of "buffer" is 'm' then prefix it, other-
X wise just stream it in straight...
X **/
X
X FILE *myfd, *popen();
X char local_buffer[LONG_SLEN];
X register int lines = 0, add_prefix=0;
X
X add_prefix = (tolower(buffer[0]) == 'm');
X
X sprintf(local_buffer, "%s %s", readmsg, ++buffer);
X
X if ((myfd = popen(local_buffer, "r")) == NULL) {
X printf("(can't get to 'readmsg' command. Sorry...)\n");
X return;
X }
X
X while (fgets(local_buffer, LONG_SLEN, myfd) != NULL) {
X lines++;
X if (add_prefix)
X fprintf(fd, "%s%s", prefixchars, local_buffer);
X else
X fputs(local_buffer, fd);
X }
X
X pclose(myfd);
X
X if (lines == 0)
X printf("(Couldn't add the requested message. Continue)\n");
X else
X printf("(added %d line%s to message... Please continue)\n",
X lines, plural(lines));
X
X return;
X}
X
Xget_with_expansion(prompt, buffer, expanded_buffer)
Xchar *prompt, *buffer, *expanded_buffer;
X{
X /** This is used to prompt for a new value of the specified field.
X If expanded_buffer == NULL then we won't bother trying to expand
X this puppy out!
X **/
X
X char mybuffer[VERY_LONG_STRING];
X
X printf(prompt); fflush(stdout); /* output! */
X
X strcpy(mybuffer, buffer);
X
X Raw(ON);
X optionally_enter(buffer, -1, -1, TRUE); /* already data! */
X Raw(OFF);
X putchar('\n');
X
X if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL)
X build_address(strip_commas(buffer), expanded_buffer);
X
X return;
X}
X
Xedit_interrupt()
X{
X /** This routine is called when the user hits an interrupt key
X while in the builtin editor...it increments the number of
X times an interrupt is hit and returns it.
X **/
X
X signal(SIGINT, edit_interrupt);
X signal(SIGQUIT, edit_interrupt);
X
X if (! interrupts_while_editing++)
X printf("(Interrupt. One more to cancel this letter...)\n\r");
X
X longjmp(edit_location); /* get back */
X}
END_OF_src/editmsg.c
if test 12220 -ne `wc -c <src/editmsg.c`; then
echo shar: \"src/editmsg.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/leavembox.c\" \(12961 characters\)
if test -f src/leavembox.c ; then
echo shar: Will not over-write existing file \"src/leavembox.c\"
else
sed "s/^X//" >src/leavembox.c <<'END_OF_src/leavembox.c'
X/** leavembox.c **/
X
X/** leave current mailbox, updating etc. as needed...
X
X (C) Copyright 1985, Dave Taylor
X**/
X
X#include "headers.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X
X#define ECHOIT 1 /* echo on for prompting! */
X
X/** added due to a bug in the 2.1 OS **/
X
Xstruct utimbuf {
X time_t actime; /** access time **/
X time_t modtime; /** modification */
X };
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy();
Xunsigned short getegid();
Xunsigned long sleep();
X
Xint
Xleave_mbox(quitting)
Xint quitting;
X{
X /** Exit, saving files into mbox and deleting specified, or simply
X delete specified mail... If "quitting" is true, then output status
X regardless of what happens. Returns 1 iff mailfile was
X changed (ie messages deleted from file), 0 if not, and -1 if new
X mail has arrived in the meantime...
X **/
X
X FILE *temp;
X char outfile[SLEN], buffer[SLEN];
X struct stat buf; /* stat command */
X struct utimbuf times; /* utime command */
X register int to_delete = 0, to_save = 0, i, mode = 00644,
X pending = 0, number_saved = 0, last_sortby;
X char dflt;
X long bytes();
X
X dprint0(1,"\n\n-- leaving_mailbox --\n\n");
X
X if (message_count == 0)
X return(FALSE); /* nothing changed */
X
X for (i = 0; i < message_count; i++)
X if (ison(header_table[i].status, DELETED)) to_delete++;
X else to_save++;
X
X dprint2(2,"Count: %d to delete and %d to save\n", to_delete, to_save);
X
X if (mbox_specified == 0)
X update_mailtime();
X
X if (hp_softkeys && question_me) {
X define_softkeys(YESNO); /* YES or NO on softkeys */
X softkeys_on();
X }
X
X if (always_del) /* set up the default answer... */
X dflt = 'y';
X else
X dflt = 'n';
X
X if (question_me && to_delete)
X if (to_save) {
X fflush(stdin);
X sprintf(buffer, "Delete message%s? (y/n) ", plural(to_delete));
X if (want_to(buffer, dflt, ECHOIT) != 'y') {
X if (mbox_specified == 0) unlock(); /* remove lock! */
X dprint1(3,"\tDelete message%s? - answer was NO\n",
X plural(to_delete));
X error("Nothing deleted");
X return(FALSE); /* nothing was deleted! */
X }
X }
X else if (! to_save) { /* nothing to save!! */
X fflush(stdin);
X if (want_to("Delete all mail? (y/n) ", dflt, ECHOIT)!='y') {
X if (mbox_specified == 0) unlock(); /* remove lock! */
X dprint0(3,"Delete all mail? - answer was NO\n");
X error("Nothing deleted");
X return(FALSE); /* nothing was deleted */
X }
X }
X
X if (always_leave)
X dflt = 'y';
X else
X dflt = 'n';
X
X /** we have to check to see what the sorting order was...so that
X the order of saved messages is the same as the order of the
X messages originally (a subtle point...) **/
X
X if (sortby != RECEIVED_DATE) { /* what we want anyway! */
X last_sortby = sortby;
X sortby = RECEIVED_DATE;
X sort_mailbox(message_count, FALSE);
X sortby = last_sortby;
X }
X
X if (question_me && to_save && mbox_specified == 0) {
X fflush(stdin);
X if (want_to("Keep mail in incoming mailbox? (y/n) ",dflt, ECHOIT)
X == 'y')
X if (to_delete) /* okay - keep undeleted as pending! */
X pending++;
X else { /* gag! nothing to delete, don't save! */
X unlock(); /* remove mailfile lock! */
X dprint0(3,"Keep mail in incoming mailbox? -- answer was YES\n");
X error("Mailbox unchanged");
X return(FALSE); /* nothing changed! */
X }
X }
X
X /** okay...now lets do it! **/
X
X if (to_save > 0) {
X if (to_delete > 0)
X sprintf(buffer ,"[%s %d message%s, and deleting %d]",
X pending? "keeping" : "storing",
X to_save, plural(to_save), to_delete);
X else if (quitting)
X sprintf(buffer,"[%s %s]",
X pending? "keeping" : "storing",
X to_save > 1? "all messages" : "message");
X else
X buffer[0] = '\0'; /* no string! */
X }
X else {
X if (to_delete > 0)
X sprintf(buffer, "[deleting all messages]");
X else if (quitting)
X sprintf(buffer, "[no messages to %s, and none to delete]",
X pending? "keep" : "save");
X else
X buffer[0] = '\0';
X }
X
X dprint1(2,"Action: %s\n", buffer);
X
X error(buffer);
X
X if (! mbox_specified) {
X if (pending) { /* keep some messages pending! */
X sprintf(outfile,"%s%d", temp_mbox, getpid());
X unlink(outfile);
X }
X else if (mailbox_defined) /* save to specified mailbox */
X strcpy(outfile, mailbox);
X else /* save to $home/mbox */
X sprintf(outfile,"%s/mbox", home);
X }
X else {
X if (! to_delete) return(FALSE); /* no work to do! */
X sprintf(outfile, "%s%d", temp_file, getpid());
X unlink(outfile); /* ensure it's empty! */
X }
X
X if (to_save) {
X if ((errno = can_open(outfile, "a"))) {
X error1(
X "Permission to append to %s denied! Leaving mailbox intact\n",
X outfile);
X dprint2(1,
X "Error: Permission to append to outfile %s denied!! (%s)\n",
X outfile, "leavembox");
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X unlock();
X return(0);
X }
X if ((temp = fopen(outfile,"a")) == NULL) {
X if (mbox_specified == 0)
X unlock(); /* remove mailfile lock! */
X dprint1(1,"Error: could not append to file %s\n",
X outfile);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X sprintf(buffer, " Could not append to file %s! ",
X outfile);
X Centerline(LINES-1, buffer);
X emergency_exit();
X }
X
X for (i = 0; i < message_count; i++)
X if (! (header_table[i].status & DELETED)) {
X current = i+1;
X if (! number_saved++) {
X dprint2(2,"Saving message%s #%d, ", plural(to_save), current);
X }
X else {
X dprint1(2,"#%d, ", current);
X }
X copy_message("", temp, FALSE, FALSE);
X }
X fclose(temp);
X dprint0(2,"\n\n");
X }
X
X /* remove source file...either default mailbox or original copy of
X specified one! */
X
X /** let's grab the original mode and date/time of the mailfile
X before removing it **/
X
X if (stat(infile, &buf) == 0)
X mode = buf.st_mode & 00777;
X else {
X dprint2(1,"Error: errno %s attempting to stat file %s\n",
X error_name(errno), infile);
X error3("Error %s (%s) on stat(%s)", error_name(errno),
X error_description(errno), infile);
X }
X
X fclose(mailfile); /* close the baby... */
X
X if (mailfile_size != bytes(infile)) {
X sort_mailbox(message_count, FALSE); /* display sorting order! */
X unlock();
X error("New mail has just arrived - resyncing...");
X return(-1);
X }
X unlink(infile); /* and BLAMO! */
X
X if (to_save && (mbox_specified || pending)) {
X if (link(outfile, infile) != 0)
X if (errno == EXDEV) { /** different file devices! Use copy! **/
X if (copy(outfile, infile) != 0) {
X dprint2(1,"leavembox: copy(%s, %s) failed;",
X outfile, infile);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X error("couldn't modify mail file!");
X sleep(1);
X sprintf(infile,"%s/%s", home, unedited_mail);
X if (copy(outfile, infile) != 0) {
X dprint1(1,"leavembox: couldn't copy to %s either!! Help;",
X infile);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X error("something godawful is happening to me!!!");
X emergency_exit();
X }
X else {
X dprint1(1,"\nWoah! Confused - Saved mail in %s (leavembox)\n",
X infile);
X error1("saved mail in %s", infile);
X }
X }
X }
X else {
X dprint2(1,"link(%s, %s) failed (leavembox)\n", outfile, infile);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X error2("link failed! %s - %s", error_name(errno),
X error_description(errno));
X emergency_exit();
X }
X unlink(outfile);
X }
X else if (keep_empty_files) {
X sleep(1);
X error1("..keeping empty mail file '%s'..", infile);
X temp = fopen(infile, "w");
X fclose(temp);
X chmod(infile, mode);
X chown(infile, userid, groupid);
X }
X
X if (mbox_specified == 0) {
X if (mode != 00644) { /* if not the default mail access mode... */
X if (! pending) { /* if none still being saved */
X temp = fopen(infile, "w");
X fclose(temp);
X }
X chmod(infile,mode);
X
X /* let's set the access times of the new mail file to be
X the same as the OLD one (still sitting in 'buf') ! */
X
X times.actime = buf.st_atime;
X times.modtime= buf.st_mtime;
X
X if (utime(infile, ×) != 0) {
X dprint0(1,"Error: encountered error doing utime (leavmbox)\n");
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X error2("Error %s trying to change file %s access time",
X error_name(errno), infile);
X }
X }
X unlock(); /* remove the lock on the file ASAP! */
X
X /** finally, let's change the ownership of the default
X outgoing mailbox, if needed **/
X
X if (to_save)
X chown(outfile, userid, groupid);
X }
X
X#ifdef SAVE_GROUP_MAILBOX_ID
X chown(infile, userid, getegid()); /** see the Config Guide **/
X#else
X chown(infile, userid, groupid); /** file owned by user **/
X#endif
X
X return(to_delete);
X}
X
Xchar lock_name[SLEN];
X
Xlock(direction)
Xint direction;
X{
X /** Create lock file to ensure that we don't get any mail
X while altering the mailbox contents!
X If it already exists sit and spin until
X either the lock file is removed...indicating new mail
X or
X we have iterated MAX_ATTEMPTS times, in which case we
X either fail or remove it and make our own (determined
X by if REMOVE_AT_LAST is defined in header file
X
X If direction == INCOMING then DON'T remove the lock file
X on the way out! (It'd mess up whatever created it!).
X **/
X
X register int iteration = 0, access_val, lock_fd;
X
X sprintf(lock_name,"%s%s.lock", mailhome, username);
X
X access_val = access(lock_name, ACCESS_EXISTS);
X
X while (access_val != -1 && iteration++ < MAX_ATTEMPTS) {
X dprint1(2,"File '%s' currently exists! Waiting...(lock)\n",
X lock_name);
X if (direction == INCOMING)
X PutLine0(LINES, 0, "\nMail being received!\twaiting...");
X else
X error1("Attempt %d: Mail being received...waiting",
X iteration);
X sleep(5);
X access_val = access(lock_name, ACCESS_EXISTS);
X }
X
X if (access_val != -1) {
X
X#ifdef REMOVE_AT_LAST
X
X /** time to waste the lock file! Must be there in error! **/
X
X dprint0(2,
X "Warning: I'm giving up waiting - removing lock file(lock)\n");
X if (direction == INCOMING)
X PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
X else
X error("Throwing away the current lock file!");
X
X if (unlink(lock_name) != 0) {
X dprint3(1,"Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
X error_name(errno), error_description(errno), lock_name);
X PutLine1(LINES, 0,
X "\n\rI couldn't remove the current lock file %s\n\r",
X lock_name);
X PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
X error_description(errno));
X if (direction == INCOMING)
X leave();
X else
X emergency_exit();
X }
X
X /* everything is okay, so lets act as if nothing had happened... */
X
X#else
X
X /* okay...we die and leave, not updating the mailfile mbox or
X any of those! */
X if (direction == INCOMING) {
X PutLine1(LINES, 0, "\nGiving up after %d iterations...", iteration);
X PutLine0(LINES, 0,
X "Please try to read your mail again in a few minutes.\n");
X dprint1(2,"Warning:bailing out after %d iterations...(lock)\n",
X iteration);
X leave_locked(0);
X }
X else {
X dprint1(2,"Warning: after %d iterations, timed out! (lock)\n",
X iteration);
X leave(error("Timed out on lock file reads. Leaving program"));
X }
X
X#endif
X }
X
X /* if we get here we can create the lock file, so lets do it! */
X
X if ((lock_fd = creat(lock_name, 0)) == -1) {
X dprint2(1,"Can't create lock file: creat(%s) raises error %s (lock)\n",
X lock_name, error_name(errno));
X if (errno == EACCES)
X leave(error1(
X "Can't create lock file! I need write permission in %s!\n\r",
X mailhome));
X else {
X dprint1(1,"Error encountered attempting to create lock %s\n",
X lock_name);
X dprint2(1,"** %s - %s **\n", error_name(errno),
X error_description(errno));
X PutLine1(LINES, 0,
X "\n\rError encountered while attempting to create lock file %s;\n\r",
X lock_name);
X PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
X error_description(errno));
X leave();
X }
X }
X close(lock_fd); /* close it. We don't want to KEEP the thing! */
X}
X
Xunlock()
X{
X /** Remove the lock file! This must be part of the interrupt
X processing routine to ensure that the lock file is NEVER
X left sitting in the mailhome directory! **/
X
X (void) unlink(lock_name);
X}
END_OF_src/leavembox.c
if test 12961 -ne `wc -c <src/leavembox.c`; then
echo shar: \"src/leavembox.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/readmsg.c\" \(13084 characters\)
if test -f utils/readmsg.c ; then
echo shar: Will not over-write existing file \"utils/readmsg.c\"
else
sed "s/^X//" >utils/readmsg.c <<'END_OF_utils/readmsg.c'
X/** readmsg.c **/
X
X/** This routine adds the functionality of the "~r" command to the Elm mail
X system while still allowing the user to use the editor of their choice.
X
X The program, without any arguments, tries to read a file in the users home
X directory called ".readmsg" (actually defined in the sysdefs.h system
X defines file) and if it finds it reads the current message. If it doesn't
X find it, it will return a usage error.
X
X The program can also be called with an explicit message number, list of
X message numbers, or a string to match in the message (including the header).
X NOTE that when you use the string matching option it will match the first
X message containing that EXACT (case sensitive) string and then exit.
X
X Changed 5/86 to SORT the input list of message numbers to ensure that
X they're in first-to-last order...
X
X Added the "weed" option as the default. This is inspired by the mail
X system used at NASA RIACS. If THEY can do it, so can we!!
X
X Also added '*' as a flag - indicating ALL messages in the mailbox.
X
X (C) Copyright 1985, Dave Taylor
X
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "defs.h"
X
X/** three defines for what level of headers to display **/
X
X#define ALL 1
X#define WEED 2
X#define NONE 3
X
X#define metachar(c) (c == '=' || c == '+' || c == '%')
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define MAX_LIST 25 /* largest single list of arguments */
X
X#define LAST_MESSAGE 9999 /* last message in list ('$' char) */
X#define LAST_CHAR '$' /* char to delimit last message.. */
X#define STAR '*' /* char to delimit all messages... */
X
Xint read_message[MAX_LIST]; /* list of messages to read */
Xint messages = 0; /* index into list of messages */
X
Xint numcmp(); /* strcmp, but for numbers */
Xchar *words(), /* function defined below... */
X *expand_define(); /* ditto... */
X
X#define DONE 0 /* for use with the getopt */
X#define ERROR -1 /* library call... */
X
Xextern char *optional_arg; /* for parsing the ... */
Xextern int opt_index; /* .. starting arguments */
X
Xchar *getenv(); /* keep lint happy */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X FILE *file; /* generic file descriptor! */
X char filename[SLEN], /* filename buffer */
X infile[SLEN], /* input filename */
X buffer[SLEN], /* file reading buffer */
X string[SLEN]; /* string match buffer */
X
X int current_in_queue = 0, /* these are used for... */
X current = 0, /* ...going through msgs */
X list_all_messages = 0, /* just list 'em all?? */
X num, /* for argument parsing */
X page_breaks = 0, /* use "^L" breaks?? */
X total, /* number of msgs current */
X include_headers = WEED, /* flag: include msg header? */
X last_message = 0, /* flag: read last message? */
X not_in_header = 0, /* flag: in msg header? */
X string_match = 0; /* flag: using string match? */
X
X /**** start of the actual program ****/
X
X while ((num = get_options(argc, argv, "nhf:p")) > 0) {
X switch (num) {
X case 'n' : include_headers = NONE; break;
X case 'h' : include_headers = ALL; break;
X case 'f' : strcpy(infile, optional_arg);
X if (metachar(infile[0]))
X if (expand(infile) == 0)
X printf("%s: couldn't expand filename %s!\n",
X argv[0], infile);
X break;
X case 'p' : page_breaks++; break;
X }
X }
X
X if (num == ERROR) {
X printf("Usage: %s [-n|-h] [-f filename] [-p] <message list>\n",
X argv[0]);
X exit(1);
X }
X
X /** whip past the starting arguments so that we're pointing
X to the right stuff... **/
X
X *argv++; /* past the program name... */
X
X while (opt_index-- > 1) {
X *argv++;
X argc--;
X }
X
X /** now let's figure out the parameters to the program... **/
X
X if (argc == 1) { /* no arguments... called from 'Elm'? */
X sprintf(filename, "%s/%s", getenv("HOME"), readmsg_file);
X if ((file = fopen(filename, "r")) != NULL) {
X fscanf(file, "%d", &(read_message[messages++]));
X fclose(file);
X }
X else { /* no arguments AND no .readmsg file!! */
X fprintf(stderr,
X "Usage: readmsg [-n|-h] [-f filename] [-p] <message list>\n");
X exit(1);
X }
X }
X else if (! isdigit(*argv[0]) && *argv[0] != LAST_CHAR &&
X *argv[0] != STAR) {
X string_match++;
X
X while (*argv)
X sprintf(string, "%s%s%s", string, string[0] == '\0'? "" : " ",
X *argv++);
X }
X else if (*argv[0] == STAR) /* all messages.... */
X list_all_messages++;
X else { /* list of nums */
X
X while (--argc > 0) {
X num = -1;
X
X sscanf(*argv,"%d", &num);
X
X if (num < 0) {
X if (*argv[0] == LAST_CHAR) {
X last_message++;
X num = LAST_MESSAGE;
X }
X else {
X fprintf(stderr,"I don't understand what '%s' means...\n",
X *argv);
X exit(1);
X }
X }
X else if (num == 0) { /* another way to say "last" */
X last_message++;
X num = LAST_MESSAGE;
X }
X
X *argv++;
X
X read_message[messages++] = num;
X }
X
X /** and now sort 'em to ensure they're in a reasonable order... **/
X
X qsort(read_message, messages, sizeof(int), numcmp);
X }
X
X /** Now let's get to the mail file... **/
X
X if (strlen(infile) == 0)
X sprintf(infile, "%s/%s", mailhome, getenv("LOGNAME"));
X
X if ((file = fopen(infile, "r")) == NULL) {
X printf("But you have no mail! [ file = %d ]\n", infile);
X exit(0);
X }
X
X /** Now it's open, let's display some 'ole messages!! **/
X
X if (string_match || last_message) { /* pass through it once */
X
X if (last_message) {
X total = count_messages(file); /* instantiate count */
X for (num=0; num < messages; num++)
X if (read_message[num] == LAST_MESSAGE)
X read_message[num] = total;
X }
X else if (string_match)
X match_string(file, string); /* stick msg# in list */
X
X if (total == 0 && ! string_match) {
X printf("There aren't any messages to read!\n");
X exit(0);
X }
X }
X
X /** now let's have some fun! **/
X
X while (fgets(buffer, SLEN, file) != NULL) {
X if (strncmp(buffer, "From ", 5) == 0) {
X if (! list_all_messages) {
X if (current == read_message[current_in_queue])
X current_in_queue++;
X if (current_in_queue >= messages)
X exit(0);
X }
X current++;
X not_in_header = 0; /* we're in the header! */
X }
X if (current == read_message[current_in_queue] || list_all_messages)
X if (include_headers==ALL || not_in_header)
X printf("%s", buffer);
X else if (strlen(buffer) < 2) {
X not_in_header++;
X if (include_headers==WEED)
X list_saved_headers(page_breaks);
X }
X else if (include_headers==WEED)
X possibly_save(buffer); /* check to see if we want this */
X }
X
X exit(0);
X}
X
Xint
Xcount_messages(file)
XFILE *file;
X{
X /** Returns the number of messages in the file **/
X
X char buffer[SLEN];
X int count = 0;
X
X while (fgets(buffer, SLEN, file) != NULL)
X if (strncmp(buffer, "From ", 5) == 0)
X count++;
X
X rewind( file );
X return( count );
X}
X
Xmatch_string(mailfile, string)
XFILE *mailfile;
Xchar *string;
X{
X /** Increment "messages" and put the number of the message
X in the message_count[] buffer until we match the specified
X string... **/
X
X char buffer[SLEN];
X int message_count;
X
X while (fgets(buffer, SLEN, mailfile) != NULL) {
X if (strncmp(buffer, "From ", 5) == 0)
X message_count++;
X
X if (in_string(buffer, string)) {
X read_message[messages++] = message_count;
X rewind(mailfile);
X return;
X }
X }
X
X fprintf(stderr,"Couldn't find message containing '%s'\n", string);
X exit(1);
X}
X
Xint
Xnumcmp(a, b)
Xint *a, *b;
X{
X /** compare 'a' to 'b' returning less than, equal, or greater
X than, accordingly.
X **/
X
X return(*a - *b);
X}
X
Xstatic char from[SLEN], subject[SLEN], date[SLEN], to[SLEN];
X
Xpossibly_save(buffer)
Xchar *buffer;
X{
X /** Check to see what "buffer" is...save it if it looks
X interesting... We'll always try to get SOMETHING
X by tearing apart the "From " line... **/
X
X if (strncmp(buffer, "Date:", 5) == 0)
X strcpy(date, buffer);
X else if (strncmp(buffer, "Subject:", 8) == 0)
X strcpy(subject,buffer);
X else if (strncmp(buffer,"From:", 5) == 0)
X strcpy(from, buffer);
X else if (strncmp(buffer,"To: ", 3) == 0)
X strncpy(to, buffer, SLEN);
X else if (strncmp(buffer,"From ", 5) == 0) {
X sprintf(from, "From: %s\n", words(2,1, buffer));
X sprintf(date,"Date: %s", words(3,7, buffer));
X to[0] = '\0';
X }
X}
X
Xlist_saved_headers(page_break)
Xint page_break;
X{
X /** This routine will display the information saved from the
X message being listed...If it displays anything it'll end
X with a blank line... **/
X
X register int displayed_line = FALSE;
X static int messages_listed = 0;
X
X if (page_break && messages_listed++) putchar(FORMFEED);
X
X if (strlen(from) > 0) { printf("%s", from); displayed_line++;}
X if (strlen(subject) > 0) { printf("%s", subject); displayed_line++;}
X if (strlen(to) > 0) { printf("%s", to); displayed_line++;}
X if (strlen(date) > 0) { printf("%s", date); displayed_line++;}
X
X if (displayed_line)
X putchar('\n');
X}
X
Xchar *words(word, num_words, buffer)
Xint word, num_words;
Xchar *buffer;
X{
X /** Return a buffer starting at 'word' and containing 'num_words'
X words from buffer. Assume white space will delimit each word.
X **/
X
X static char internal_buffer[SLEN];
X char *wordptr, *bufptr, mybuffer[SLEN], *strtok();
X int wordnumber = 0, copying_words = 0;
X
X internal_buffer[0] = '\0'; /* initialize */
X
X strcpy(mybuffer, buffer);
X bufptr = (char *) mybuffer; /* and setup */
X
X while ((wordptr = strtok(bufptr, " \t")) != NULL) {
X if (++wordnumber == word) {
X strcpy(internal_buffer, wordptr);
X copying_words++;
X num_words--;
X }
X else if (copying_words) {
X strcat(internal_buffer, " ");
X strcat(internal_buffer, wordptr);
X num_words--;
X }
X
X if (num_words < 1)
X return((char *) internal_buffer);
X
X bufptr = NULL;
X }
X
X return( (char *) internal_buffer);
X}
X
Xint
Xexpand(infile)
Xchar *infile;
X{
X /** Expand the filename since the first character is a meta-
X character that should expand to the "maildir" variable
X in the users ".elmrc" file...
X
X Note: this is a brute force way of getting the entry out
X of the .elmrc file, and isn't recommended for the faint
X of heart!
X **/
X
X FILE *rcfile;
X char buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr;
X int foundit = 0;
X
X bufptr = (char *) buffer; /* same address */
X
X if ((home = getenv("HOME")) == NULL) {
X printf(
X "Can't expand environment variable $HOME to find .elmrc file!\n");
X exit(1);
X }
X
X sprintf(buffer, "%s/%s", home, elmrcfile);
X
X if ((rcfile = fopen(buffer, "r")) == NULL) {
X printf("Can't open your \".elmrc\" file (%s) for reading!\n",
X buffer);
X exit(1);
X }
X
X while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) {
X if (strncmp(buffer, "maildir", 7) == 0 ||
X strncmp(buffer, "folders", 7) == 0) {
X while (*bufptr != '=' && *bufptr)
X bufptr++;
X bufptr++; /* skip the equals sign */
X while (whitespace(*bufptr) && *bufptr)
X bufptr++;
X home = bufptr; /* remember this address */
X
X while (! whitespace(*bufptr) && *bufptr != '\n')
X bufptr++;
X
X *bufptr = '\0'; /* remove trailing space */
X foundit++;
X }
X }
X
X fclose(rcfile); /* be nice... */
X
X if (! foundit) {
X printf("Couldn't find \"maildir\" in your .elmrc file!\n");
X exit(1);
X }
X
X /** Home now points to the string containing your maildir, with
X no leading or trailing white space...
X **/
X
X expanded_dir = expand_define(home);
X
X sprintf(buffer, "%s%s%s", expanded_dir,
X (expanded_dir[strlen(expanded_dir)-1] == '/' ||
X infile[0] == '/') ? "" : "/", (char *) infile+1);
X
X strcpy(infile, buffer);
X}
X
Xchar *expand_define(maildir)
Xchar *maildir;
X{
X /** This routine expands any occurances of "~" or "$var" in
X the users definition of their maildir directory out of
X their .elmrc file.
X
X Again, another routine not for the weak of heart or staunch
X of will!
X **/
X
X static char buffer[SLEN]; /* static buffer AIEE!! */
X char name[SLEN], /* dynamic buffer!! (?) */
X *nameptr, /* pointer to name?? */
X *value; /* char pointer for munging */
X
X if (*maildir == '~')
X sprintf(buffer, "%s%s", getenv("HOME"), ++maildir);
X else if (*maildir == '$') { /* shell variable */
X
X /** break it into a single word - the variable name **/
X
X strcpy(name, (char *) maildir + 1); /* hurl the '$' */
X nameptr = (char *) name;
X while (*nameptr != '/' && *nameptr) nameptr++;
X *nameptr = '\0'; /* null terminate */
X
X /** got word "name" for expansion **/
X
X if ((value = getenv(name)) == NULL) {
X printf("Couldn't expand shell variable $%s in .elmrc!\n", name);
X exit(1);
X }
X sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1);
X }
X else
X strcpy(buffer, maildir);
X
X return( ( char *) buffer);
X}
X
END_OF_utils/readmsg.c
if test 13084 -ne `wc -c <utils/readmsg.c`; then
echo shar: \"utils/readmsg.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 12 \(of 19\).
cp /dev/null ark12isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
if test ! -f ark${I}isdone ; then
echo shar: You still need to run archive ${I}.
DONE=false
fi
done
if test "$DONE" = "true" ; then
echo You have unpacked all 19 archives.
echo "See the Instructions file"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
fi
## End of shell archive.
exit 0