v06i030: Elm mail system (elm), Part05/14
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Mon Jun 30 10:46:11 AEST 1986
Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
Mod.sources: Volume 6, Issue 30
Archive-name: elm/Part05
# Continuation of Shell Archive, created by hpldat!taylor
# This is part 5
# To unpack the enclosed files, please use this file as input to the
# Bourne (sh) shell. This can be most easily done by the command;
# sh < thisfilename
if [ ! -d src ]
then
echo creating directory src
mkdir src
fi
# ---------- file src/Makefile ----------
filename="src/Makefile"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/Makefile...
fi
cat << 'END-OF-FILE' > $filename
#
# Makefile for the ELM mail program.
#
# (C) Copyright 1986, Dave Taylor
#
# Last modification: March 7th, 1986
SHELL=/bin/sh
##############################
#
# if on a BSD system;
# DEFINE=-DBSD
# LIB2 = -lcurses
# else if on a UTS system;
# DEFINE=-DUTS
# LIB2 = -la -lq
# else if on a SUN system;
# DEFINE=-DBSD -DSUN
# LIB2 = -lcurses
# else if on a Pyramid system;
# DEFINE=-DBSD -DNO_VAR_ARGS
# LIB2 = -lcurses
# else
DEFINE=
LIB2 =
# IF you're on an ACSnet system (Australia) then
# you'll want to uncomment the following;
# DEFINE= ${DEFINE} -DACSNET
##############################
CFILES= addr_utils.c alias.c aliasdb.c aliaslib.c args.c bounceback.c \
calendar.c connect_to.c curses.c date.c delete.c domains.c edit.c \
encode.c errno.c file.c file_utils.c fileio.c hdrconfg.c help.c \
initialize.c input_utils.c leavembox.c mailmsg1.c mailmsg2.c \
mailtime.c mkhdrs.c elm.c newmbox.c notesfile.c options.c opt_utils.c \
output_utils.c pattern.c quit.c read_rc.c remail.c reply.c \
return_addr.c savecopy.c screen.c showmsg.c signals.c softkeys.c \
sort.c strings.c syscall.c utils.c validname.c getopt.c string2.c
HEADERS=../hdrs/curses.h ../hdrs/defs.h ../hdrs/headers.h ../hdrs/sysdefs.h
OBJS= addr_utils.o alias.o aliasdb.o aliaslib.o args.o bounceback.o \
calendar.o connect_to.o curses.o date.o delete.o domains.o edit.o \
encode.o errno.o file.o file_utils.o fileio.o hdrconfg.o help.o \
initialize.o input_utils.o leavembox.o mailmsg1.o mailmsg2.o \
mailtime.o mkhdrs.o elm.o newmbox.o notesfile.o options.o opt_utils.o \
output_utils.o pattern.o quit.o read_rc.o remail.o reply.o \
return_addr.o savecopy.o screen.o showmsg.o signals.o softkeys.o \
sort.o strings.o syscall.o utils.o validname.o getopt.o string2.o
BIN= ../bin
LIBS= -ltermcap
CFLAGS= -O -I../hdrs
CC= /bin/cc
RM= /bin/rm -f
../bin/elm: ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/elm.h
${CC} -o ${BIN}/elm -n ${OBJS} ${LIBS} ${LIB2}
.c.o: ${HEADERS}
${CC} -c ${CFLAGS} ${DEFINE} $*.c
curses.o: curses.c ../hdrs/curses.h
${CC} -c ${CFLAGS} -DRAWMODE ${DEFINE} curses.c
# curses.c : curses.q
# @../bin/quickscreen curses.q
#
# curses.q :
# @cp curses.c curses.q
clean:
${RM} ${OBJS} LINT.OUT
lint: LINT.OUT
LINT.OUT: ${CFILES}
lint -p -I../hdrs ${CFILES} > LINT.OUT
listing: LISTING
LISTING: Makefile INDEX ${HEADERS} ${CFILES}
@echo adding file 'Makefile'...
@/bin/echo \\f > LISTING
@cat Makefile >> LISTING
@echo adding file 'INDEX'...
@/bin/echo \\f >> LISTING
@cat INDEX >> LISTING
@../bin/makelisting ${HEADERS} ${CFILES}
@echo LISTING generated.
index: INDEX
INDEX: ${CFILES} ${HEADERS}
@echo Creating function definition index
@index *.c | sort > INDEX
@echo File INDEX generated
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 2822 ]
then
echo $filename changed - should be 2822 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/alias.c ----------
filename="src/alias.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/alias.c...
fi
cat << 'END-OF-FILE' > $filename
/** alias.c **/
/** This file contains alias stuff
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <errno.h>
char *expand_group(), *get_alias_address(), *expand_system(), *get_token();
char *error_name(), *error_description();
extern int errno;
read_alias_files()
{
/** read the system and user alias files, if present.
Set the flags 'systemfiles' and 'userfiles' accordingly.
**/
char fname[SLEN];
int hash;
if ((hash = open(system_hash_file, O_RDONLY)) == -1) {
dprint1(1,
"Warning: Can't read system hash file %s (read_alias_files)\n",
system_hash_file);
goto user;
}
read(hash, system_hash_table, sizeof system_hash_table);
close(hash);
/* and data file opened.. */
if ((system_data = open(system_data_file, O_RDONLY)) == -1) {
dprint1(1,
"Warning: Can't read system data file %s (read_alias_files)\n",
system_data_file);
goto user;
}
system_files++; /* got the system files! */
user: sprintf(fname, "%s/.alias_hash", home);
if ((hash = open(fname, O_RDONLY)) == -1) {
dprint1(1,"Warning: Can't read user hash file %s (read_alias_files)\n",
fname);
return;
}
read(hash, user_hash_table, sizeof user_hash_table);
close(hash);
sprintf(fname, "%s/.alias_data", home);
if ((user_data = open(fname, O_RDONLY)) == -1) {
dprint1(1,
"Warning: can't read user data file %s (read_alias_files)\n",
fname);
return;
}
user_files++; /* got user files too! */
}
int
add_alias()
{
/** add an alias to the user alias text file. Return zero
if alias not added in actuality **/
char name[SLEN], *address, address1[LONG_STRING];
char comment[SLEN];
PutLine0(LINES-2,0,"Enter alias name: ");
CleartoEOLN();
Raw(OFF);
gets(name, 20);
Raw(ON);
if (strlen(name) == 0)
return(0);
if ((address = get_alias_address(name, 0, 0)) != NULL) {
dprint1(2, "Attempt to add a duplicate alias [%s] (add_alias)\n",
address);
if (address[0] == '!') {
address[0] = ' ';
error1("already a group with that name:%s", address);
}
else
error1("already an alias for that: %s", address);
return(0);
}
PutLine1(LINES-2,0,"Full name for %s: ", name);
CleartoEOLN();
Raw(OFF);
gets(comment,SLEN);
Raw(ON);
if (strlen(comment) == 0) strcpy(comment, name);
PutLine1(LINES-2,0,"Enter address for %s: ",name);
CleartoEOLN();
Raw(OFF);
gets(address1,LONG_SLEN);
Raw(ON);
if (strlen(address1) == 0) {
error("No address specified!");
return(0);
}
add_to_alias_text(name, comment, address1);
return(1);
}
int
add_current_alias()
{
/** alias the current message to the specified name and
add it to the alias text file, for processing as
the user leaves the program. Returns non-zero iff
alias actually added to file **/
char name[SLEN], address1[LONG_STRING], *address;
char comment[SLEN];
if (current == 0) {
dprint0(3,"Add current alias called without any current message!\n");
error("No message to alias to!");
return(0);
}
PutLine0(LINES-2,0,"Current message address aliased to: ");
CleartoEOLN();
Raw(OFF);
gets(name, 20);
Raw(ON);
if (strlen(name) == 0) /* cancelled... */
return(0);
if ((address = get_alias_address(name, 0, 0)) != NULL) {
dprint1(3,
"Attempt to add a duplicate alias [%s] (add_current_alias)\n",
address);
if (address[1] == '!') {
address[0] = ' ';
error1("already a group with that name:%s", address);
}
else
error1("already an alias for that: %s", address);
return(0);
}
PutLine1(LINES-2,0,"Full name of %s: ", name);
CleartoEOLN();
Raw(OFF);
gets(comment, 40);
Raw(ON);
get_return(address1); /* grab the return address of this message */
optimize_return(address1);
PutLine3(LINES-2,0,"%s (%s) = %s", comment, name, address1);
CleartoEOLN();
add_to_alias_text(name, comment, address1);
return(1);
}
add_to_alias_text(name, comment, address)
char *name, *comment, *address;
{
/** Add the data to the user alias text file. Return zero if we
succeeded, 1 if not **/
FILE *file;
char fname[SLEN];
sprintf(fname,"%s/.alias_text", home);
if ((file = fopen(fname, "a")) == NULL) {
dprint2(2, "FILE Failure attempting to add alias to file %s (%s)",
fname, "add_to_alias_text");
dprint2(2, "** %s - %s **\n", error_name(errno),
error_description(errno));
error1("couldn't open %s to add new alias!", fname);
return(1);
}
fprintf(file,"%s : %s : %s\n", name, comment, address);
fclose(file);
chown(fname, userid, groupid);
return(0);
}
show_alias_menu()
{
MoveCursor(LINES-7,0); CleartoEOLN();
MoveCursor(LINES-6,0); CleartoEOLN();
MoveCursor(LINES-5,0); CleartoEOLN();
PutLine0(LINES-7,COLUMNS-45, "Alias commands");
Centerline(LINES-5,
"A)lias current msg, Check a P)erson or S)ystem, M)ake new alias, or R)eturn"
);
}
alias()
{
/** work with alias commands... **/
char name[NLEN], *address, ch, buffer[SLEN];
int newaliases = 0;
if (mini_menu)
show_alias_menu();
define_softkeys(ALIAS);
while (1) {
PutLine0(LINES-3,0,"Alias: ");
CleartoEOLN();
ch = ReadCh();
MoveCursor(LINES-1,0); CleartoEOLN();
switch (tolower(ch)) {
case 'a': newaliases += add_current_alias(); break;
case 'm': newaliases += add_alias(); break;
case RETURN:
case 'q':
case 'x':
case 'r': if (newaliases) install_aliases();
return;
case 'p': if (newaliases)
error("Warning: new aliases not installed yet!");
PutLine0(LINES-2,0,"Check for person: ");
CleartoEOLN();
Raw(OFF);
gets(name,NLEN);
Raw(ON);
if ((address = get_alias_address(name, 0, 0))!=NULL) {
if (address[0] == '!') {
address[0] = ' ';
PutLine1(LINES-1,0,"Group alias:%-65.65s", address);
CleartoEOLN();
}
else
PutLine1(LINES-1,0,"Aliased addresss: %-65.65s",
address);
}
else
error("not found");
break;
case 's': PutLine0(LINES-2,0,"Check for system: ");
CleartoEOS();
Raw(OFF);
gets(name,NLEN);
Raw(ON);
if (talk_to(name))
#ifdef INTERNET_ADDRESS_FORMAT
PutLine1(LINES-1,0,
"You have a direct connection - the address is (user)@%s",
name);
#else
PutLine1(LINES-1,0,
"You have a direct connection - the address is %s!(user)",
name);
#endif
else {
sprintf(buffer, "(user)@%s", name);
address = expand_system(buffer, FALSE);
if (strlen(address) > strlen(name) + 7)
PutLine1(LINES-1,0,"Address is: %.65s", address);
else
error1("couldn't expand system '%s'", name);
}
break;
case '@': PutLine0(LINES-2,0,"Fully expand alias: ");
CleartoEOS();
Raw(OFF);
gets(name,NLEN);
Raw(ON);
if ((address = get_alias_address(name, 1, 0)) != NULL) {
ClearScreen();
PutLine1(3,0,"Aliased address:\n\r%s", address);
PutLine0(LINES-1,0,"Press <return> to continue: ");
(void) getchar();
}
else
error("not found");
break;
default : error("Invalid input!");
}
}
}
install_aliases()
{
/** run the 'newalias' program and install the newly
added aliases before going back to the main
program!
**/
error("Adding new aliases...");
sleep(2);
if (system_call(newalias, SH) == 0) {
error("Re-reading the database in...");
sleep(2);
read_alias_files();
set_error("New aliases installed successfully");
}
else
set_error("'newalias' failed. Please check alias_text");
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 7725 ]
then
echo $filename changed - should be 7725 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/curses.c ----------
filename="src/curses.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/curses.c...
fi
cat << 'END-OF-FILE' > $filename
/** curses.c **/
/** This library gives programs the ability to easily access the
termcap information and write screen oriented and raw input
programs. The routines can be called as needed, except that
to use the cursor / screen routines there must be a call to
InitScreen() first. The 'Raw' input routine can be used
independently, however.
Modified 2/86 to work (hopefully) on Berkeley systems. If
there are any problems with BSD Unix, please report them to
the author at taylor at hplabs (fixed, if possible!)
Modified 5/86 to add memory lock support, thanks to the
suggested code by Steve Wolf.
(C) Copyright 1985 Dave Taylor, HP Colorado Networks
**/
#ifdef BSD
# include "/usr/include/curses.h" /* don't ask! */
#endif
#include "headers.h"
#ifdef RAWMODE
# ifdef BSD
# include <sgtty.h>
# else
# include <termio.h>
# endif
#endif
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
#include "curses.h"
#ifdef RAWMODE
# define TTYIN 0
#endif
extern int debug;
#ifdef RAWMODE
# ifndef BSD
struct termio _raw_tty,
_original_tty;
# endif
static int _inraw = 0; /* are we IN rawmode? */
static int _memory_locked = 0; /* are we IN memlock?? */
static int _line = -1, /* initialize to "trash" */
_col = -1;
#ifdef UTS
static int _clear_screen = 0; /* Next i/o clear screen? */
static char _null_string[SLEN]; /* a string of nulls... */
#endif
#endif
static int _intransmit; /* are we transmitting keys? */
static
char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
*_setbold, *_clearbold, *_setunderline, *_clearunderline,
*_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
*_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off,
*_set_memlock, *_clear_memlock;
static
int _lines, _columns;
static char _terminal[1024]; /* Storage for terminal entry */
static char _capabilities[1024]; /* String for cursor motion */
static char *ptr = _capabilities; /* for buffering */
int outchar(); /* char output for tputs */
char *tgetstr(), /* Get termcap capability */
*tgoto(); /* and the goto stuff */
InitScreen()
{
/* Set up all this fun stuff: returns zero if all okay, or;
-1 indicating no terminal name associated with this shell,
-2..-n No termcap for this terminal type known
*/
int tgetent(), /* get termcap entry */
error;
char termname[40];
dprint0(8,"InitScreen()\n");
#ifdef SUN
if (getenv("TERM") == NULL)
return(-1);
#endif
#ifdef UTS
/* use _line for lack of a better variable, what the heck! */
for (_line = 0; _line < SLEN; _line++)
_null_string[_line] = '\0';
#endif
if (strcpy(termname, getenv("TERM")) == NULL)
return(-1);
if ((error = tgetent(_terminal, termname)) != 1)
return(error-2);
_line = 0; /* where are we right now?? */
_col = 0; /* assume zero, zero... */
/* load in all those pesky values */
_clearscreen = tgetstr("cl", &ptr);
_moveto = tgetstr("cm", &ptr);
_up = tgetstr("up", &ptr);
_down = tgetstr("do", &ptr);
_right = tgetstr("nd", &ptr);
_left = tgetstr("bs", &ptr);
_setbold = tgetstr("so", &ptr);
_clearbold = tgetstr("se", &ptr);
_setunderline = tgetstr("us", &ptr);
_clearunderline = tgetstr("ue", &ptr);
_setinverse = tgetstr("so", &ptr);
_clearinverse = tgetstr("se", &ptr);
_sethalfbright = tgetstr("hs", &ptr);
_clearhalfbright = tgetstr("he", &ptr);
_cleartoeoln = tgetstr("ce", &ptr);
_cleartoeos = tgetstr("cd", &ptr);
_lines = tgetnum("li");
_columns = tgetnum("co");
_transmit_on = tgetstr("ks", &ptr);
_transmit_off = tgetstr("ke", &ptr);
_set_memlock = tgetstr("ml", &ptr);
_clear_memlock = tgetstr("mu", &ptr);
if (!_left) {
_left = ptr;
*ptr++ = '\b';
*ptr++ = '\0';
}
#ifdef BSD
initscr(); /* initalize curses too! */
#endif
return(0);
}
char *return_value_of(termcap_label)
char *termcap_label;
{
/** This will return the string kept by termcap for the
specified capability. Modified to ensure that if
tgetstr returns a pointer to a transient address
that we won't bomb out with a later segmentation
fault (thanks to Dave at Infopro for this one!) **/
static char escape_sequence[20];
char *tgetstr(); /* Get termcap capability */
dprint1(9,"return_value_of(%s)\n", termcap_label);
strcpy(escape_sequence, tgetstr(termcap_label, &ptr));
return( (char *) escape_sequence);
}
transmit_functions(newstate)
int newstate;
{
/** turn function key transmission to ON | OFF **/
dprint1(9,"transmit_functions(%s)\n", onoff(newstate));
if (newstate != _intransmit) {
_intransmit = ! _intransmit;
if (newstate == ON)
tputs(_transmit_on, 1, outchar);
else
tputs(_transmit_off, 1, outchar);
fflush(stdout); /* clear the output buffer */
}
}
/****** now into the 'meat' of the routines...the cursor stuff ******/
ScreenSize(lines, columns)
int *lines, *columns;
{
/** returns the number of lines and columns on the display. **/
dprint2(9,"ScreenSize(_,_) returning %d, %d\n", _lines-1, _columns);
*lines = _lines - 1; /* assume index from zero */
*columns = _columns;
}
ClearScreen()
{
/* clear the screen: returns -1 if not capable */
dprint0(9,"ClearScreen()\n");
_line = 0; /* clear leaves us at top... */
_col = 0;
#ifdef UTS
if (isatube) {
_clear_screen++; /* queue up for clearing... */
return(0);
}
#endif
if (!_clearscreen)
return(-1);
tputs(_clearscreen, 1, outchar);
fflush(stdout); /* clear the output buffer */
return(0);
}
MoveCursor(row, col)
int row, col;
{
/** move cursor to the specified row column on the screen.
0,0 is the top left! **/
char *stuff;
/* we don't want to change "rows" or we'll mangle scrolling... */
if (col > COLUMNS) col = COLUMNS;
if (col < 0) col = 0;
#ifdef UTS
if (isatube) {
at row+1, col+1;
_line = row;
_col = col;
return(0);
}
#endif
if (!_moveto)
return(-1);
if (row == _line) {
if (col == _col)
return(0);
else if (abs(col - _col) < 5) {
if (col > _col)
CursorRight(col - _col);
else
CursorLeft(_col - col);
}
else {
stuff = tgoto(_moveto, col, row);
tputs(stuff, 1, outchar);
fflush(stdout);
}
}
else if (col == _col && abs(row - _line) < 5) {
if (row < _line)
CursorUp(_line - row);
else
CursorDown(row - _line);
}
else if (_line == row-1 && col == 0) {
putchar('\n'); /* that's */
putchar('\r'); /* easy! */
fflush(stdout);
}
else {
stuff = tgoto(_moveto, col, row);
tputs(stuff, 1, outchar);
fflush(stdout);
}
_line = row; /* to ensure we're really there... */
_col = col;
return(0);
}
CursorUp(n)
int n;
{
/** move the cursor up 'n' lines **/
dprint1(9,"CursorUp(%d)\n", n);
_line = (_line-n > 0? _line - n: 0); /* up 'n' lines... */
#ifdef UTS
if (isatube) {
at _line+1, _col+1;
return(0);
}
#endif
if (!_up)
return(-1);
while (n-- > 0)
tputs(_up, 1, outchar);
fflush(stdout);
return(0);
}
CursorDown(n)
int n;
{
/** move the cursor down 'n' lines **/
dprint1(9,"CursorDown(%d)\n", n);
_line = (_line+n < LINES? _line + n: LINES); /* down 'n' lines... */
#ifdef UTS
if (isatube) {
at _line+1, _col+1 ;
return(0);
}
#endif
if (!_down)
return(-1);
while (n-- > 0)
tputs(_down, 1, outchar);
fflush(stdout);
return(0);
}
CursorLeft(n)
int n;
{
/** move the cursor 'n' characters to the left **/
dprint1(9,"CursorLeft(%d)\n", n);
_col = (_col - n> 0? _col - n: 0); /* left 'n' chars... */
#ifdef UTS
if (isatube) {
at _line+1, _col+1;
return(0);
}
#endif
if (!_left)
return(-1);
while (n-- > 0)
tputs(_left, 1, outchar);
fflush(stdout);
return(0);
}
CursorRight(n)
int n;
{
/** move the cursor 'n' characters to the right (nondestructive) **/
dprint1(9,"CursorRight(%d)\n", n);
_col = (_col+n < COLUMNS? _col + n: COLUMNS); /* right 'n' chars... */
#ifdef UTS
if (isatube) {
at _line+1, _col+1;
return(0);
}
#endif
if (!_right)
return(-1);
while (n-- > 0)
tputs(_right, 1, outchar);
fflush(stdout);
return(0);
}
StartBold()
{
/** start boldface/standout mode **/
if (!_setbold)
return(-1);
tputs(_setbold, 1, outchar);
fflush(stdout);
return(0);
}
EndBold()
{
/** compliment of startbold **/
if (!_clearbold)
return(-1);
tputs(_clearbold, 1, outchar);
fflush(stdout);
return(0);
}
StartUnderline()
{
/** start underline mode **/
if (!_setunderline)
return(-1);
tputs(_setunderline, 1, outchar);
fflush(stdout);
return(0);
}
EndUnderline()
{
/** the compliment of start underline mode **/
if (!_clearunderline)
return(-1);
tputs(_clearunderline, 1, outchar);
fflush(stdout);
return(0);
}
StartHalfbright()
{
/** start half intensity mode **/
if (!_sethalfbright)
return(-1);
tputs(_sethalfbright, 1, outchar);
fflush(stdout);
return(0);
}
EndHalfbright()
{
/** compliment of starthalfbright **/
if (!_clearhalfbright)
return(-1);
tputs(_clearhalfbright, 1, outchar);
fflush(stdout);
return(0);
}
StartInverse()
{
/** set inverse video mode **/
if (!_setinverse)
return(-1);
tputs(_setinverse, 1, outchar);
fflush(stdout);
return(0);
}
EndInverse()
{
/** compliment of startinverse **/
if (!_clearinverse)
return(-1);
tputs(_clearinverse, 1, outchar);
fflush(stdout);
return(0);
}
int
HasMemlock()
{
/** returns TRUE iff memory locking is available (a terminal
feature that allows a specified portion of the screen to
be "locked" & not cleared/scrolled... **/
return ( _set_memlock && _clear_memlock );
}
static int _old_LINES;
int
StartMemlock()
{
/** mark the current line as the "last" line of the portion to
be memory locked (always relative to the top line of the
screen) Note that this will alter LINES so that it knows
the top is locked. This means that (plus) the program
will scroll nicely but (minus) End memlock MUST be called
whenever we leave the locked-memory part of the program! **/
if (! _set_memlock)
return(-1);
if (! _memory_locked) {
_old_LINES = LINES;
LINES -= _line; /* we can't use this for scrolling */
tputs(_set_memlock, 1, outchar);
fflush(stdout);
_memory_locked = TRUE;
}
return(0);
}
int
EndMemlock()
{
/** Clear the locked memory condition... **/
if (! _set_memlock)
return(-1);
if (_memory_locked) {
LINES = _old_LINES; /* back to old setting */
tputs(_clear_memlock, 1, outchar);
fflush(stdout);
_memory_locked = FALSE;
}
return(0);
}
Writechar(ch)
char ch;
{
/** write a character to the current screen location. **/
#ifdef UTS
char buffer[2]; /* can't output characters! */
#endif
dprint1(9,ch >= ' ' ? "Writechar(%c)\n" : "Writechar(^%c)\n",
ch >= ' ' ? ch : ch + 'A' - 1);
#ifdef UTS
if (isatube) {
buffer[0] = ch;
buffer[1] = '\0';
at _line+1, _col+1;
panel (noerase, noinit, noread) {
#ON, buffer, 1#
}
}
else
#endif
putchar(ch);
if (ch == BACKSPACE) /* moved BACK one! */
_col--;
else if (ch >= ' ') /* moved FORWARD one! */
_col++;
}
Write_to_screen(line, argcount, arg1, arg2, arg3)
char *line;
int argcount, arg1, arg2, arg3;
{
/** This routine writes to the screen at the current location.
when done, it increments lines & columns accordingly by
looking for "\n" sequences... **/
dprint2(9,"Write_to_screen(%s) [%d args]\n", line, argcount);
switch (argcount) {
case 0 :
PutLine0(_line, _col, line);
break;
case 1 :
PutLine1(_line, _col, line, arg1);
break;
case 2 :
PutLine2(_line, _col, line, arg1, arg2);
break;
case 3 :
PutLine3(_line, _col, line, arg1, arg2, arg3);
break;
}
}
PutLine0(x, y, line)
int x,y;
char *line;
{
/** Write a zero argument line at location x,y **/
register int i;
dprint3(8,"PutLine0(%d, %d, %s.30...)\n", x, y, line);
#ifdef UTS
if (isatube) {
at x+1, y+1;
panel (init=_clear_screen, noread, erase=_clear_screen) {
#ON, line, strlen(line)-1#
}
_clear_screen = 0;
_col += printable_chars(line);
/* line wrapped around?? */
while (_col > COLUMNS) {
_col -= COLUMNS;
_line += 1;
}
/* now let's figure out if we're supposed to do a "<return>" */
for (i=0; i < strlen(line); i++)
if (line[i] == '\n') {
_line++;
_col = 0; /* on new line! */
}
return(0);
}
#endif
MoveCursor(x,y);
printf("%s", line); /* to avoid '%' problems */
fflush(stdout);
_col += printable_chars(line);
while (_col > COLUMNS) { /* line wrapped around?? */
_col -= COLUMNS;
_line += 1;
}
/** now let's figure out if we're supposed to do a "<return>" **/
for (i=0; i < strlen(line); i++)
if (line[i] == '\n') {
_line++;
_col = 0; /* on new line! */
}
}
PutLine1(x,y, line, arg1)
int x,y;
char *line;
char *arg1;
{
/** write line at location x,y - one argument... **/
char buffer[SLEN];
dprint0(9, "PutLine1(...)\n");
sprintf(buffer, line, arg1);
PutLine0(x, y, buffer);
}
PutLine2(x,y, line, arg1, arg2)
int x,y;
char *line;
char *arg1, *arg2;
{
/** write line at location x,y - one argument... **/
char buffer[SLEN];
dprint0(9, "PutLine2(...)\n");
sprintf(buffer, line, arg1, arg2);
PutLine0(x, y, buffer);
}
PutLine3(x,y, line, arg1, arg2, arg3)
int x,y;
char *line;
char *arg1, *arg2, *arg3;
{
/** write line at location x,y - one argument... **/
char buffer[SLEN];
dprint0(9, "PutLine3(...)\n");
sprintf(buffer, line, arg1, arg2, arg3);
PutLine0(x, y, buffer);
}
CleartoEOLN()
{
/** clear to end of line **/
#ifdef UTS
char buffer[SLEN];
register int cols, i = 0;
if (isatube) {
dprint0(9, "CleartoEOLN()\n");
for (cols = _col; cols < COLUMNS; cols++)
buffer[i++] = ' ';
buffer[i] = '\0';
at _line+1, _col+1;
panel (noerase, noinit, noread) {
#ON, buffer, strlen(buffer)-1#
}
return(0);
}
#endif
dprint0(9, "CleartoEOLN()\n");
if (!_cleartoeoln)
return(-1);
tputs(_cleartoeoln, 1, outchar);
fflush(stdout); /* clear the output buffer */
return(0);
}
CleartoEOS()
{
/** clear to end of screen **/
#ifdef UTS
register int line_at;
if (isatube) {
dprint0(9,"CleartoEOS()\n");
for (line_at = _line; line_at < LINES-1; line_at++) {
panel (noread, noinit, noread) {
#@ line_at, 1# #ON, _null_string, COLUMNS#
}
}
return(0);
}
#endif
dprint0(9,"CleartoEOS()\n");
if (!_cleartoeos)
return(-1);
tputs(_cleartoeos, 1, outchar);
fflush(stdout); /* clear the output buffer */
return(0);
}
#ifdef RAWMODE
Raw(state)
int state;
{
/** state is either ON or OFF, as indicated by call **/
dprint1(8,"Raw(%s)\n", onoff(state));
if (state == OFF && _inraw) {
#ifdef BSD
echo();
nocrmode();
#else
(void) ioctl(TTYIN, TCSETAW, &_original_tty);
#endif
_inraw = 0;
}
else if (state == ON && ! _inraw) {
#ifdef BSD
noecho();
crmode();
#else
(void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/
(void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/
_raw_tty.c_iflag &= ~(INLCR | ICRNL |BRKINT);
_raw_tty.c_iflag |= IXON;
_raw_tty.c_oflag |= OPOST;
_raw_tty.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET);
_raw_tty.c_lflag &= ~(ICANON | ECHO);
_raw_tty.c_cc[VMIN] = '\01';
_raw_tty.c_cc[VTIME] = '\0';
(void) ioctl(TTYIN, TCSETAW, &_raw_tty);
#endif
_inraw = 1;
}
}
int
ReadCh()
{
/** read a character with Raw mode set! **/
register int result;
char ch;
dprint0(9,"ReadCh()\n");
result = read(0, &ch, 1);
return(result == 0? EOF : ch);
}
#endif
outchar(c)
char c;
{
/** output the given character. From tputs... **/
/** Note: this CANNOT be a macro! **/
putc(c, stdout);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 15951 ]
then
echo $filename changed - should be 15951 bytes, not $size bytes
fi
chmod 666 $filename
fi
# ---------- file src/date.c ----------
filename="src/date.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/date.c...
fi
cat << 'END-OF-FILE' > $filename
/** date.c **/
/** return the current date and time in a readable format! **/
/** also returns an ARPA RFC-822 format date... **/
/** (C) Copyright 1985, Dave Taylor **/
#include "headers.h"
#ifdef BSD
# include <sys/time.h>
#else
# include <time.h>
#endif
#include <ctype.h>
#ifdef BSD
#undef toupper
#endif
#define MONTHS_IN_YEAR 11 /* 0-11 equals 12 months! */
#define FEB 1 /* 0 = January */
#define DAYS_IN_LEAP_FEB 29 /* leap year only */
#define ampm(n) (n > 12? n - 12 : n)
#define am_or_pm(n) (n > 11? (n > 23? "am" : "pm") : "am")
#define leapyear(year) ((year % 4 == 0) && (year % 100 != 0))
char *dayname[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "" };
char *monname[] = { "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November",
"December", ""};
char *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
"Fri", "Sat", "" };
char *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
int days_in_month[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31, -1};
#ifdef BSD
char *timezone();
#else
extern char *tzname[];
#endif
char *get_date()
{
/** Return the date in the format exemplified by;
Thursday, April 18th 1985 at 8:35 pm
*************************************
** This routine is not used by ELM **
*************************************
**/
static char buffer[SLEN]; /* static character buffer */
struct tm *the_time, /* Time structure, see CTIME(3C) */
*localtime();
char *suffix(); /* digit suffix for date */
long junk; /* time in seconds.... */
junk = (long) time(0); /* this must be here for it to work! */
the_time = localtime(&junk);
sprintf(buffer, "%s, %s %d%s %d at %d:%02d %s",
dayname[the_time->tm_wday], /* weekday */
monname[the_time->tm_mon], /* month */
the_time->tm_mday, /* day */
suffix(the_time->tm_mday), /* suffix */
the_time->tm_year + 1900, /* year */
ampm(the_time->tm_hour), /* hour */
the_time->tm_min, /* minute */
((the_time->tm_hour == 12 || the_time->tm_hour == 24)
&& the_time->tm_min == 0) ? (the_time->tm_hour == 12? "noon" :
"midnight") : am_or_pm(the_time->tm_hour)); /* am | pm */
return( (char *) buffer);
}
char *suffix(day)
int day;
{
/** this routine returns the suffix appropriate for the
specified number to make it an ordinal number. ie,
if given '1' it would return 'st', and '2' => 'nd'
**/
static char buffer[10];
register int digit;
digit = day % 10;
if (digit == 0 || digit > 3)
strcpy(buffer,"th");
else if (digit == 1)
strcpy(buffer,"st");
else if (digit == 2)
strcpy(buffer, "nd");
else
strcpy(buffer, "rd");
return( (char *) buffer);
}
char *get_arpa_date()
{
/** returns an ARPA standard date. The format for the date
according to DARPA document RFC-822 is exemplified by;
Mon, 12 Aug 85 6:29:08 MST
**/
static char buffer[SLEN]; /* static character buffer */
struct tm *the_time, /* Time structure, see CTIME(3C) */
*localtime();
long junk; /* time in seconds.... */
#ifdef BSD
struct timeval time_val;
struct timezone time_zone;
#endif
#ifdef BSD
gettimeofday(&time_val, &time_zone);
junk = time_val.tv_sec;
#else
junk = (long) time(0); /* this must be here for it to work! */
#endif
the_time = localtime(&junk);
sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
arpa_dayname[the_time->tm_wday],
the_time->tm_mday % 32,
arpa_monname[the_time->tm_mon],
the_time->tm_year % 100,
the_time->tm_hour % 24,
the_time->tm_min % 61,
the_time->tm_sec % 61,
#ifdef BSD
timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
#else
tzname[the_time->tm_isdst]);
#endif
return( (char *) buffer);
}
char *full_month(month)
char *month;
{
/** Given a three letter month abbreviation, return the
full name of the month. If can't figure it out, just
return the given argument. **/
char name[4];
register int i;
/** ensure name in correct case... **/
strncpy(name, shift_lower(month), 3);
name[0] = toupper(name[0]);
/** now simply step through arpa_monname table to find a match **/
for (i=0; i < 12; i++)
if (strncmp(name, arpa_monname[i], 3) == 0)
return((char *) monname[i]);
dprint1(2, "Warning: Couldn't expand monthname %s (full_month)\n",
month);
return( (char *) month);
}
days_ahead(days, buffer)
int days;
char *buffer;
{
/** return in buffer the date (Day, Mon Day, Year) of the date
'days' days after today. **/
struct tm *the_time, /* Time structure, see CTIME(3C) */
*localtime();
long junk; /* time in seconds.... */
junk = (long) time(0); /* this must be here for it to work! */
the_time = localtime(&junk);
/* increment the day of the week */
the_time->tm_wday = (the_time->tm_wday + days) % 7;
/* the day of the month... */
the_time->tm_mday += days;
if (the_time->tm_mday > days_in_month[the_time->tm_mon]) {
if (the_time->tm_mon == FEB && leapyear(the_time->tm_year)) {
if (the_time->tm_mday > DAYS_IN_LEAP_FEB) {
the_time->tm_mday -= days_in_month[the_time->tm_mon];
the_time->tm_mon += 1;
}
}
else {
the_time->tm_mday -= days_in_month[the_time->tm_mon];
the_time->tm_mon += 1;
}
}
/* check the month of the year */
if (the_time->tm_mon > MONTHS_IN_YEAR) {
the_time->tm_mon -= MONTHS_IN_YEAR;
the_time->tm_year += 1;
}
/* now, finally, build the actual date string */
sprintf(buffer, "%s, %d %s %d",
arpa_dayname[the_time->tm_wday],
the_time->tm_mday % 32,
arpa_monname[the_time->tm_mon],
the_time->tm_year % 100);
}
int
valid_date(day, mon, year)
char *day, *mon, *year;
{
/** validate the given date - returns TRUE iff the date
handed is reasonable and valid. **/
register int daynum, yearnum;
daynum = atoi(day);
yearnum = atoi(year);
if (daynum < 1 || daynum > 31) {
dprint1(3, "Error: day %d is obviously wrong! (valid_date)\n",
daynum);
return(0);
}
if (yearnum < 1 || (yearnum > 100 && yearnum < 1900) ||
yearnum > 2000) {
dprint1(3, "Error: year %d is obviously wrong! (valid_date)\n",
yearnum);
return(0);
}
return(1);
}
fix_date(entry)
struct header_rec *entry;
{
/** This routine will 'fix' the date entry for the specified
message. This consists of 1) adjusting the year to 0-99
and 2) altering time from HH:MM:SS to HH:MM am|pm **/
if (atoi(entry->year) > 99)
sprintf(entry->year,"%d", atoi(entry->year) - 1900);
fix_time(entry->time);
}
fix_time(timestring)
char *timestring;
{
/** Timestring in format HH:MM:SS (24 hour time). This routine
will fix it to display as: HH:MM [am|pm] **/
int hour, minute;
sscanf(timestring, "%d:%d", &hour, &minute);
if (hour < 1 || hour == 24)
sprintf(timestring, "12:%2d (midnight)", minute);
else if (hour < 12)
sprintf(timestring, "%d:%2.2d am", hour, minute);
else if (hour == 12)
sprintf(timestring, "%d:%2.2d (noon)", hour, minute);
else if (hour < 24)
sprintf(timestring, "%d:%2.2d pm", hour-12, minute);
}
int
compare_dates(rec1, rec2)
struct header_rec *rec1, *rec2;
{
/** This function works similarly to the "strcmp" function, but
has lots of knowledge about the internal date format...
Apologies to those who "know a better way"...
**/
int month1, day1, year1, hour1, minute1,
month2, day2, year2, hour2, minute2;
year1 = atoi(rec1->year);
year2 = atoi(rec2->year);
if (year1 != year2)
return( year1 - year2 );
/* And HERE's where the performance of this sort dies... */
month1 = month_number(rec1->month); /* retch... gag.... */
month2 = month_number(rec2->month); /* puke... */
if (month1 == -1)
dprint1(2,"month_number failed on month '%s'\n", rec1->month);
if (month2 == -1)
dprint1(2,"month_number failed on month '%s'\n", rec2->month);
if (month1 != month2)
return( month1 - month2 );
/* back and cruisin' now, though... */
day1 = atoi(rec1->day); /* unfortunately, 2 is greater than 19 */
day2 = atoi(rec2->day); /* on a dump string-only compare... */
if (day1 != day2)
return( day1 - day2 );
/* we're really slowing down now... */
sscanf(rec1->time, "%d:%d", &hour1, &minute1);
sscanf(rec2->time, "%d:%d", &hour2, &minute2);
if (hour1 != hour2)
return( hour1 - hour2 );
return( day1 - day2 ); /* ignore seconds... */
}
int
month_number(name)
char *name;
{
/** return the month number given the month name... **/
char ch;
switch (tolower(name[0])) {
case 'a' : if ((ch = tolower(name[1])) == 'p') return(APRIL);
else if (ch == 'u') return(AUGUST);
else return(-1); /* error! */
case 'd' : return(DECEMBER);
case 'f' : return(FEBRUARY);
case 'j' : if ((ch = tolower(name[1])) == 'a') return(JANUARY);
else if (ch == 'u') {
if ((ch = tolower(name[2])) == 'n') return(JUNE);
else if (ch == 'l') return(JULY);
else return(-1); /* error! */
}
else return(-1); /* error */
case 'm' : if ((ch = tolower(name[2])) == 'r') return(MARCH);
else if (ch == 'y') return(MAY);
else return(-1); /* error! */
case 'n' : return(NOVEMBER);
case 'o' : return(OCTOBER);
case 's' : return(SEPTEMBER);
default : return(-1);
}
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 9538 ]
then
echo $filename changed - should be 9538 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/delete.c ----------
filename="src/delete.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/delete.c...
fi
cat << 'END-OF-FILE' > $filename
/** delete.c **/
/** Delete or undelete files: just set flag in header record!
Also tags specified message(s)...
(C) Copyright 1985 Dave Taylor
**/
#include "headers.h"
delete(real_del)
int real_del;
{
/** Delete current message. If real-del is false, then we're
actually requested to toggle the state of the current
message... **/
if (real_del)
header_table[current-1].status |= DELETED;
else if (ison(header_table[current-1].status, DELETED))
clearit(header_table[current-1].status, DELETED);
else
setit(header_table[current-1].status, DELETED);
show_msg_status(current-1);
}
undelete()
{
/** clear the deleted message flag **/
clearit(header_table[current-1].status, DELETED);
show_msg_status(current-1);
}
show_msg_status(msg)
int msg;
{
/** show the status of the current message only. **/
if (on_page(msg)) {
MoveCursor((msg % headers_per_page) + 4, 3);
Writechar( ison(header_table[msg].status, DELETED)? 'D' : ' ');
}
}
tag_message()
{
/** Tag current message. If already tagged, untag it. **/
if (ison(header_table[current-1].status, TAGGED))
clearit(header_table[current-1].status, TAGGED);
else
setit(header_table[current-1].status, TAGGED);
show_msg_tag(current-1);
}
show_msg_tag(msg)
int msg;
{
/** show the tag status of the current message only. **/
if (on_page(msg)) {
MoveCursor((msg % headers_per_page) + 4, 4);
Writechar( ison(header_table[msg].status, TAGGED)? '+' : ' ');
}
}
show_new_status(msg)
int msg;
{
/** If the specified message is on this screen, show
the new status (could be marked for deletion now,
and could have tag removed...)
**/
if (on_page(msg))
PutLine2((msg % headers_per_page) + 4, 3, "%c%c",
ison(header_table[msg].status, DELETED)? 'D' : ' ',
ison(header_table[msg].status, TAGGED )? '+' : ' ');
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 1863 ]
then
echo $filename changed - should be 1863 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/aliasdb.c ----------
filename="src/aliasdb.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/aliasdb.c...
fi
cat << 'END-OF-FILE' > $filename
/** aliasdb.c **/
/** Alias database files...
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
char *shift_lower(), *find_path_to();
findnode(name, display_error)
char *name;
int display_error;
{
/** break 'name' into machine!user or user at machine and then
see if you can find 'machine' in the path database..
If so, return name as the expanded address. If not,
return what was given to us! If display_error, then
do so...
**/
char old_name[SLEN];
char address[SLEN];
if (strlen(name) == 0)
return;
strcpy(old_name, name); /* save what we were given */
if (expand_site(name, address) == -1) {
if (display_error && name[0] != '!') {
dprint2(2,"Couldn't expand host %s in address. (%s)\n",
name, "findnode");
if (! check_only) { /* be silent if just checking */
error1("Warning: couldn't expand %s...", name);
sleep(1);
}
}
strcpy(name, old_name); /* and restore... */
}
else
strcpy(name, address);
return;
}
int
expand_site(cryptic, expanded)
char *cryptic, *expanded;
{
/** Given an address of the form 'xyz at site' or 'site!xyz'
return an address of the form <expanded address for site>
with 'xyz' embedded according to the path database entry.
Note that 'xyz' can be eiher a simple address (as in "joe")
or a complex address (as in "joe%xerox.parc at Xerox.ARPA")!
0 = found, -1 return means unknown site code **/
#ifdef ACSNET
strcpy(expanded, cryptic); /* fast and simple */
return(0);
#else
char name[VERY_LONG_STRING], sitename[VERY_LONG_STRING],
temp[VERY_LONG_STRING], old_name[VERY_LONG_STRING];
char *expand_domain(), *addr;
register int i = 0, j = 0, domain_name;
strcpy(old_name, cryptic); /* remember what we were given */
/** break down **/
while (cryptic[i] != AT_SIGN && cryptic[i] != BANG &&
cryptic[i] != '\0')
sitename[j++] = cryptic[i++];
sitename[j++] = '\0';
j = 0;
if (cryptic[i] == '\0') return(-1); /* nothing to expand! */
domain_name = (cryptic[i] == AT_SIGN);
i++;
while (cryptic[i] != '\0')
name[j++] = cryptic[i++];
name[j] = '\0';
if (domain_name) {
strcpy(temp, name);
strcpy(name, sitename);
strcpy(sitename, temp);
}
#ifndef LOOK_CLOSE_AFTER_SEARCH
if (talk_to(sitename)) {
strcpy(expanded, old_name); /* restore! */
return(0);
}
#endif
if ((addr = find_path_to(sitename, TRUE)) == NULL) {
#ifdef LOOK_CLOSE_AFTER_SEARCH
if (talk_to(sitename)) {
strcpy(expanded, old_name); /* restore! */
return(0);
}
else
#endif
if ((addr = expand_domain(cryptic)) != NULL) {
strcpy(expanded, addr); /* into THIS buffer */
return(0);
}
else if (size_of_pathfd == 0) { /* no path database! */
strcpy(expanded, old_name); /* restore! */
return(0);
}
else /* We just can't get there! */
return(-1);
}
else { /* search succeeded */
sprintf(expanded, addr, name);
return(0);
}
#endif
}
int
binary_search(name, address)
char *name, *address;
{
/* binary search file for name. Return 0 if found, -1 if not */
char machine[40];
register long first = 0, last, middle;
register int compare;
address[0] = '\0';
last = size_of_pathfd;
do {
middle = (long) ((first+last) / 2);
get_entry(machine, address, pathfd, middle);
compare = strcmp(name, machine);
if (compare < 0)
last = middle - 1;
else if (compare == 0)
return(0);
else /* greater */
first = middle + 1;
} while (abs(last) - abs(first) > FIND_DELTA);
return(-1);
}
get_entry(machine, address, fileid, offset)
char *machine, *address;
FILE *fileid;
long offset;
{
/** get entry...return machine and address immediately
following given offset in fileid. **/
fseek(fileid, offset, 0);
/* read until we hit an end-of-line */
while (getc(fileid) != '\n')
;
fscanf(fileid, "%s\t%s", machine, address);
}
init_findnode()
{
/** Initialize the FILE and 'size_of_file' values for the
findnode procedure **/
struct stat buffer;
if (stat(pathfile, &buffer) == -1) {
dprint2(1, "Warning: No pathalias file [filename %s] found! (%s)\n",
pathfile, "init_findnode");
size_of_pathfd = 0;
return;
}
size_of_pathfd = (long) buffer.st_size;
if ((pathfd = fopen(pathfile,"r")) == NULL) {
dprint2(1, "Warning: Can't read pathalias file [filename %s] (%s)\n",
pathfile, "init_findnode");
size_of_pathfd = 0;
}
else
dprint2(2, "\nOpened file '%s' as path alias database. (%s)\n\n",
pathfile, "init_findnode");
}
char *find_path_to(machine, printf_format)
char *machine;
int printf_format;
{
/** Returns either the path to the specified machine or NULL if
not found. If "printf_format" is TRUE, then it leaves the
'%s' intact, otherwise it assumes that the address is a uucp
address for the domain expansion program and removes the
last three characters of the expanded name ("!%s") since
they're redundant with the expansion!
**/
static char buffer[LONG_SLEN]; /* space for path */
if (size_of_pathfd > 0)
if (binary_search(machine, buffer) != -1) { /* found it! */
if (! printf_format && strlen(buffer) > 3)
buffer[strlen(buffer)-3] = '\0';
return( (char *) buffer);
}
return(NULL); /* failed if it's here! */
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 5484 ]
then
echo $filename changed - should be 5484 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/file.c ----------
filename="src/file.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/file.c...
fi
cat << 'END-OF-FILE' > $filename
/** file.c **/
/** File I/O routines, mostly the save to file command...
(C) Copyright 1986, Dave Taylor
**/
#include "headers.h"
#include <ctype.h>
#include <errno.h>
#ifdef BSD
#undef tolower
#endif
extern int errno;
char *error_name(), *error_description();
int
save()
{
/** Save all tagged messages + current in a file. If no messages
are tagged, save the current message instead! This routine
will return ZERO if the operation failed.
**/
register int tagged = 0, i, oldstat, appending = 0;
char filename[SLEN], address[LONG_SLEN], buffer[SLEN];
FILE *save_file;
oldstat = header_table[current-1].status; /* remember */
for (i=0; i < message_count; i++)
if (ison(header_table[i].status, TAGGED))
tagged++;
if (tagged == 0) {
tagged = 1;
setit(header_table[current-1].status, TAGGED);
}
dprint2(4,"%d message%s tagged for saving (save)\n", tagged,
plural(tagged));
PutLine1(LINES-2, 0, "File message%s in: ", plural(tagged));
if (save_by_name) {
/** build default filename to save to **/
get_return(address);
get_return_name(address, buffer, FALSE);
sprintf(filename, "=%s", buffer);
}
else
filename[0] = '\0';
if (tagged > 1)
optionally_enter(filename, LINES-2, 19, FALSE);
else
optionally_enter(filename, LINES-2, 18, FALSE);
MoveCursor(LINES-1,0);
if (strlen(filename) == 0) { /** <return> means 'cancel', right? **/
header_table[current-1].status = oldstat; /* BACK! */
return(0);
}
if (! expand_filename(filename)) {
dprint1(2,"Error: Failed on expansion of filename %s (save)\n",
filename);
header_table[current-1].status = oldstat; /* BACK! */
return(0); /* failed expanding name! */
}
if (access(filename,ACCESS_EXISTS)) /* already there!! */
appending = 1;
if ((errno = can_open(filename, "a"))) {
error1("Wrong permissions to save message to file %s!", filename);
dprint2(2,"Error: access permission on file %s denied (%s)! (save)\n",
filename, error_name(errno));
header_table[current-1].status = oldstat; /* BACK! */
return(0);
}
dprint1(4,"Saving mail to file '%s'...\n", filename);
if ((save_file = fopen(filename,"a")) == NULL) {
dprint1(2, "Error: couldn't append to specified file %s (save)\n",
filename);
error1("Couldn't append to file %s!", filename);
header_table[current-1].status = oldstat; /* BACK! */
return(0);
}
for (i=0; i < message_count; i++) /* save each tagged msg */
if (header_table[i].status & TAGGED)
save_message(i, filename, save_file, (tagged > 1), appending++);
fclose(save_file);
chown(filename, userid, groupid); /* owned by user */
if (tagged > 1)
error1("Message%s saved", plural(tagged));
return(1);
}
int
save_message(number, filename, fd, pause, appending)
int number, pause, appending;
char *filename;
FILE *fd;
{
/** Save an actual message to a file. This is called by
"save()" only! The parameters are the message number,
and the name and file descriptor of the file to save to.
If 'pause' is true, a sleep(2) will be done after the
saved message appears on the screen...
'appending' is only true if the file already exists
**/
register int save_current;
dprint1(4, "\tSaving message %d to file...\n", number);
save_current = current;
current = number+1;
copy_message("", fd, FALSE, FALSE);
current = save_current;
if (resolve_mode)
setit(header_table[number].status, DELETED); /* deleted, but ... */
clearit(header_table[number].status, TAGGED); /* not tagged anymore */
clearit(header_table[number].status, NEW); /* it's not new now! */
if (! appending) /* don't ask */
error2("Message %d appended to file %s", number+1, filename);
else
error2("Message %d saved to file %s", number+1, filename);
show_new_status(number); /* update screen, if needed */
if (pause) sleep(2);
}
int
expand_filename(filename)
char *filename;
{
/** Expands '~' and '=' to specified file names, also will try to
expand shell variables if encountered.. '+' and '%' are synonymous
with '=' (folder dir)... **/
char buffer[SLEN], varname[SLEN], env_value[SLEN];
register int i = 1, index = 0;
/** new stuff - make sure no illegal char as last **/
if (lastch(filename) == '\n' || lastch(filename) == '\r')
lastch(filename) = '\0';
if (filename[0] == '~') {
sprintf(buffer, "%s%s%s", home,
(filename[1] != '/' && lastch(folders) != '/')? "/" : "",
(char *) filename + 1);
strcpy(filename, buffer);
}
else if (filename[0] == '=' || filename[0] == '+' ||
filename[0] == '%') {
if (strlen(folders) == 0) {
dprint2(3,"Error: maildir not defined - can't expand '%c' (%s)\n",
filename[0], "expand_filename");
error1("MAILDIR not defined. Can't expand '%c'", filename[0]);
return(0);
}
sprintf(buffer, "%s%s%s", folders,
(filename[1] != '/' && lastch(folders) != '/')? "/" : "",
(char *) filename + 1);
strcpy(filename, buffer);
}
else if (filename[0] == '$') { /* env variable! */
while (isalnum(filename[i]))
varname[index++] = filename[i++];
varname[index] = '\0';
#ifdef SUN
env_value[0] = '\0'; /* null string for strlen! */
if (getenv(varname) != NULL)
#endif
strcpy(env_value, getenv(varname));
if (strlen(env_value) == 0) {
dprint2(3,"Error: Can't expand environment variable $%s (%s)\n",
varname, "expand_filename");
error1("Don't know what the value of $%s is!", varname);
return(0);
}
sprintf(buffer, "%s%s%s", env_value,
(filename[i] != '/' && lastch(env_value) != '/')? "/" : "",
(char *) filename + i);
strcpy(filename, buffer);
}
return(1);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 5704 ]
then
echo $filename changed - should be 5704 bytes, not $size bytes
fi
chmod 644 $filename
fi
echo end of this archive file....
exit 0
More information about the Mod.sources
mailing list