home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume6
/
elm
/
part09
< prev
next >
Wrap
Text File
|
1986-11-30
|
56KB
|
2,271 lines
Subject: v06i034: Elm mail system (elm), Part09/14
Newsgroups: mod.sources
Approved: rs@mirror.UUCP
Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
Mod.sources: Volume 6, Issue 34
Archive-name: elm/Part09
# Continuation of Shell Archive, created by hpldat!taylor
# This is part 9
# 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/output_utils.c ----------
filename="src/output_utils.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/output_utils.c...
fi
cat << 'END-OF-FILE' > $filename
/** output_utils.c **/
/** This file contains routines used for output in the ELM program.
These routines (C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
static char err_buffer[SLEN]; /* store last error message */
static char central_message_buffer[SLEN];
show_last_error()
{
/** rewrite last error message! **/
error(err_buffer);
}
clear_error()
{
MoveCursor(LINES,0);
CleartoEOLN();
err_buffer[0] = '\0';
}
set_error(s)
char *s;
{
strcpy(err_buffer, s);
}
error(s)
char *s;
{
/** outputs error 's' to screen at line 22, centered! **/
MoveCursor(LINES,0);
CleartoEOLN();
PutLine0(LINES,(COLUMNS-strlen(s))/2,s);
fflush(stdout);
strcpy(err_buffer, s); /* save it too! */
}
error1(s, a)
char *s, *a;
{
/** same as error, but with a 'printf' argument **/
char buffer[SLEN];
sprintf(buffer,s,a);
error(buffer);
}
error2(s, a1, a2)
char *s, *a1, *a2;
{
/** same as error, but with two 'printf' arguments **/
char buffer[SLEN];
sprintf(buffer,s, a1, a2);
error(buffer);
}
error3(s, a1, a2, a3)
char *s, *a1, *a2, *a3;
{
/** same as error, but with three 'printf' arguments **/
char buffer[SLEN];
sprintf(buffer,s, a1, a2, a3);
error(buffer);
}
prompt(s)
char *s;
{
/** prompt user for input on LINES-3 line, left justified **/
PutLine0(LINES-3,0,s);
CleartoEOLN();
}
prompt1(s,a)
char *s, *a;
{
/** same as prompt, but with a 'printf' argument **/
char buffer[SLEN];
sprintf(buffer,s,a);
prompt(buffer);
}
set_central_message(string, arg)
char *string, *arg;
{
/** set up the given message to be displayed in the center of
the current window **/
sprintf(central_message_buffer, string, arg);
}
display_central_message()
{
/** display the message if set... **/
if (central_message_buffer[0] != '\0') {
ClearLine(LINES-15);
Centerline(LINES-15, central_message_buffer);
fflush(stdout);
}
}
clear_central_message()
{
/** clear the central message buffer **/
central_message_buffer[0] = '\0';
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 1987 ]
then
echo $filename changed - should be 1987 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/mailtime.c ----------
filename="src/mailtime.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/mailtime.c...
fi
cat << 'END-OF-FILE' > $filename
/** mailtime.c **/
/** This set of routines is used to figure out when the user last read
their mail and to also figure out if a given message is new or not.
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef BSD
# include <sys/time.h>
#else
# include <time.h>
#endif
resolve_received(entry)
struct header_rec *entry;
{
/** Entry has the data for computing the time and date the
message was received. Fix it and return **/
switch (tolower(entry->month[0])) {
case 'j' : if (tolower(entry->month[1]) == 'a')
entry->received.month = JANUARY;
else if (tolower(entry->month[2]) == 'n')
entry->received.month = JUNE;
else
entry->received.month = JULY;
break;
case 'f' : entry->received.month = FEBRUARY;
break;
case 'm' : if (tolower(entry->month[2]) == 'r')
entry->received.month = MARCH;
else
entry->received.month = MAY;
break;
case 'a' : if (tolower(entry->month[1]) == 'p')
entry->received.month = APRIL;
else
entry->received.month = AUGUST;
break;
case 's' : entry->received.month = SEPTEMBER;
break;
case 'o' : entry->received.month = OCTOBER;
break;
case 'n' : entry->received.month = NOVEMBER;
break;
case 'd' : entry->received.month = DECEMBER;
break;
}
sscanf(entry->day, "%d", &(entry->received.day));
sscanf(entry->year, "%d", &(entry->received.year));
if (entry->received.year > 100) entry->received.year -= 1900;
sscanf(entry->time, "%d:%d", &(entry->received.hour),
&(entry->received.minute));
}
get_mailtime()
{
/** Instantiate the values of the last_read_mail stat
variable based on the file access time/date of the
file mailtime_file. IF the file doesn't exist,
then assume all mail is new. **/
struct stat buffer;
struct tm *timebuf;
char filename[SLEN];
sprintf(filename, "%s/%s", home, mailtime_file);
if (stat(filename, &buffer) == -1) {
last_read_mail.month = 0;
last_read_mail.day = 0;
last_read_mail.year = 0;
last_read_mail.hour = 0;
last_read_mail.minute = 0;
}
else { /* stat okay... */
timebuf = (struct tm *) localtime(&(buffer.st_mtime));
last_read_mail.month = timebuf->tm_mon;
last_read_mail.day = timebuf->tm_mday;
last_read_mail.year = timebuf->tm_year;
last_read_mail.hour = timebuf->tm_hour;
last_read_mail.minute = timebuf->tm_min;
}
}
update_mailtime()
{
/** This routine updates the last modified time of the
.last_read_mail file in the users home directory.
If the file doesn't exist, it creates it!! **/
char filename[SLEN];
#ifdef BSD
struct timeval tval[2];
struct timezone tzone;
#endif
sprintf(filename, "%s/%s", home, mailtime_file);
#ifdef BSD
gettimeofday(&tval[0], &tzone);
gettimeofday(&tval[1], &tzone);
if (utime(filename, &tval) == -1)
#else
if (utime(filename, NULL) == -1)
#endif
(void) creat(filename, 0777);
}
new_msg(entry)
struct header_rec entry;
{
/** Return true if the current message is NEW. This can be
easily tested by seeing 1) if we're reading the incoming
mailbox and then, if so, 2) if the received_on_machine
date is more recent than the last_read_mail date.
**/
if (mbox_specified != 0) return(FALSE); /* not incoming */
/** Two tests - if received is OLDER than last read mail, then
immediately return FALSE. If received is NEWER than last
read mail then immediately return TRUE **/
if (entry.received.year < last_read_mail.year)
return(FALSE);
if (entry.received.year > last_read_mail.year)
return(TRUE);
if (entry.received.month < last_read_mail.month)
return(FALSE);
if (entry.received.month > last_read_mail.month)
return(TRUE);
if (entry.received.day < last_read_mail.day)
return(FALSE);
if (entry.received.day > last_read_mail.day)
return(TRUE);
if (entry.received.hour < last_read_mail.hour)
return(FALSE);
if (entry.received.hour > last_read_mail.hour)
return(TRUE);
if (entry.received.minute < last_read_mail.minute)
return(FALSE);
return(TRUE);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 4271 ]
then
echo $filename changed - should be 4271 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/encode.c ----------
filename="src/encode.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/encode.c...
fi
cat << 'END-OF-FILE' > $filename
/** encode.c **/
/** This is a heavily mangled version of the 'cypher' program written by
person or persons unknown.
(C) Copyright 1986, Dave Taylor
**/
#include <stdio.h>
#include "curses.h"
#include "headers.h"
#define RS 94
#define RN 4
#define RMASK 0x7fff /* use only 15 bits */
static char r[RS][RN]; /* rotors */
static char ir[RS][RN]; /* inverse rotors */
static char h[RS]; /* half rotor */
static char s[RS]; /* shuffle vector */
static int p[RN]; /* rotor indices */
static char the_key[SLEN]; /* unencrypted key */
static char *encrypted_key; /* encrypted key */
getkey(send)
int send;
{
/** this routine prompts for and returns an encode/decode
key for use in the rest of the program. If send == 1
then need to mess with rawmode. **/
char buffer[NLEN];
int gotkey = 0;
ClearLine(21);
if (send) Raw(OFF);
while ( !gotkey ) {
MoveCursor(LINES-1,0);
ClearLine(LINES-1);
if (send)
strcpy( buffer, getpass( "Enter encryption key: "));
else
strcpy( buffer, getpass( "Enter decryption key: "));
MoveCursor(LINES-1,0);
if ( strcmp( buffer, getpass( "Please enter it again: "))) {
error("Your keys were not the same!");
sleep(1);
clear_error();
continue;
}
strcpy(the_key, buffer); /* save unencrypted key */
makekey( buffer );
gotkey = 1;
}
if (send) Raw(ON);
setup(); /** initialize the rotors etc. **/
ClearLine(LINES-1);
clear_error();
}
get_key_no_prompt()
{
/** This performs the same action as get_key, but assumes that
the current value of 'the_key' is acceptable. This is used
when a message is encrypted twice... **/
char buffer[SLEN];
strcpy(buffer, the_key);
makekey( buffer );
setup();
}
encode(line)
char *line;
{
/** encrypt or decrypt the specified line. Uses the previously
entered key... **/
register int i, index, j, ph = 0;
for (index=0; index < strlen(line); index++) {
i = (int) line[index];
if ( (i >= ' ') && (i < '~') ) {
i -= ' ';
for ( j = 0; j < RN; j++ ) /* rotor forwards */
i = r[(i+p[j])%RS][j];
i = ((h[(i+ph)%RS])-ph+RS)%RS; /* half rotor */
for ( j-- ; j >= 0; j-- ) /* rotor backwards */
i = (ir[i][j]+RS-p[j])%RS;
j = 0; /* rotate rotors */
p[0]++;
while ( p[j] == RS ) {
p[j] = 0;
j++;
if ( j == RN ) break;
p[j]++;
}
if ( ++ph == RS )
ph = 0;
i += ' ';
}
line[index] = (char) i; /* replace with altered one */
}
}
makekey( rkey)
char *rkey;
{
/** encrypt the key using the system routine 'crypt' **/
char key[8], salt[2], *crypt();
strncpy( key, rkey, 8);
salt[0] = key[0];
salt[1] = key[1];
encrypted_key = crypt( key, salt);
}
/*
* shuffle rotors.
* shuffle each of the rotors indiscriminately. shuffle the half-rotor
* using a special obvious and not very tricky algorithm which is not as
* sophisticated as the one in crypt(1) and Oh God, I'm so depressed.
* After all this is done build the inverses of the rotors.
*/
setup()
{
register long i, j, k, temp;
long seed;
for ( j = 0; j < RN; j++ ) {
p[j] = 0;
for ( i = 0; i < RS; i++ )
r[i][j] = i;
}
seed = 123;
for ( i = 0; i < 13; i++) /* now personalize the seed */
seed = (seed*encrypted_key[i] + i) & RMASK;
for ( i = 0; i < RS; i++ ) /* initialize shuffle vector */
h[i] = s[i] = i;
for ( i = 0; i < RS; i++) { /* shuffle the vector */
seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
k = ((seed % 65521) & RMASK) % RS;
temp = s[k];
s[k] = s[i];
s[i] = temp;
}
for ( i = 0; i < RS; i += 2 ) { /* scramble the half-rotor */
temp = h[s[i]]; /* swap rotor elements ONCE */
h[s[i]] = h[s[i+1]];
h[s[i+1]] = temp;
}
for ( j = 0; j < RN; j++) { /* select a rotor */
for ( i = 0; i < RS; i++) { /* shuffle the vector */
seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
k = ((seed % 65521) & RMASK) % RS;
temp = r[i][j];
r[i][j] = r[k][j];
r[k][j] = temp;
}
for ( i = 0; i < RS; i++) /* create inverse rotors */
ir[r[i][j]][j] = i;
}
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 4156 ]
then
echo $filename changed - should be 4156 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/leavembox.c ----------
filename="src/leavembox.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/leavembox.c...
fi
cat << 'END-OF-FILE' > $filename
/** leavembox.c **/
/** leave current mailbox, updating etc. as needed...
(C) Copyright 1985, Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#define ECHOIT 1 /* echo on for prompting! */
/** added due to a bug in the 2.1 OS **/
struct utimbuf {
time_t actime; /** access time **/
time_t modtime; /** modification */
};
extern int errno;
char *error_name(), *error_description();
int
leave_mbox(quitting)
int quitting;
{
/** Exit, saving files into mbox and deleting specified, or simply
delete specified mail... If "quitting" is true, then output status
regardless of what happens. Returns 1 iff mailfile was
changed (ie messages deleted from file), 0 if not, and -1 if new
mail has arrived in the meantime...
**/
FILE *temp;
char outfile[SLEN], buffer[SLEN];
struct stat buf; /* stat command */
struct utimbuf times; /* utime command */
register int to_delete = 0, to_save = 0, i, mode = 00644,
pending = 0, number_saved = 0, last_sortby;
char dflt;
long bytes();
dprint0(1,"\n\n-- leaving_mailbox --\n\n");
if (message_count == 0)
return(FALSE); /* nothing changed */
for (i = 0; i < message_count; i++)
if (ison(header_table[i].status, DELETED)) to_delete++;
else to_save++;
dprint2(2,"Count: %d to delete and %d to save\n", to_delete, to_save);
if (mbox_specified == 0)
update_mailtime();
if (hp_softkeys) {
define_softkeys(YESNO); /* YES or NO on softkeys */
softkeys_on();
}
if (always_del) /* set up the default answer... */
dflt = 'y';
else
dflt = 'n';
if (to_delete)
if (to_save) {
sprintf(buffer, "Delete message%s? (y/n) ", plural(to_delete));
if (want_to(buffer, dflt, ECHOIT) != 'y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint1(3,"\tDelete message%s? - answer was NO\n",
plural(to_delete));
error("Nothing deleted");
return(FALSE); /* nothing was deleted! */
}
}
else if (! to_save) { /* nothing to save!! */
if (want_to("Delete all mail? (y/n) ", dflt, ECHOIT)!='y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint0(3,"Delete all mail? - answer was NO\n");
error("Nothing deleted");
return(FALSE); /* nothing was deleted */
}
}
if (always_leave)
dflt = 'y';
else
dflt = 'n';
/** we have to check to see what the sorting order was...so that
the order of saved messages is the same as the order of the
messages originally (a subtle point...) **/
if (sortby != RECEIVED_DATE) { /* what we want anyway! */
last_sortby = sortby;
sortby = RECEIVED_DATE;
sort_mailbox(message_count, FALSE);
sortby = last_sortby;
}
if (to_save && mbox_specified == 0)
if (want_to("Keep mail in incoming mailbox? (y/n) ",dflt, ECHOIT)
== 'y')
if (to_delete) /* okay - keep undeleted as pending! */
pending++;
else { /* gag! nothing to delete, don't save! */
unlock(); /* remove mailfile lock! */
dprint0(3,"Keep mail in incoming mailbox? -- answer was YES\n");
error("Mailbox unchanged");
return(FALSE); /* nothing changed! */
}
/** okay...now lets do it! **/
if (to_save > 0) {
if (to_delete > 0)
sprintf(buffer ,"[%s %d message%s, and deleting %d]",
pending? "keeping" : "storing",
to_save, plural(to_save), to_delete);
else if (quitting)
sprintf(buffer,"[%s %s]",
pending? "keeping" : "storing",
to_save > 1? "all messages" : "message");
else
buffer[0] = '\0'; /* no string! */
}
else {
if (to_delete > 0)
sprintf(buffer, "[deleting all messages]");
else if (quitting)
sprintf(buffer, "[no messages to %s, and none to delete]",
pending? "keep" : "save");
else
buffer[0] = '\0';
}
dprint1(2,"Action: %s\n", buffer);
error(buffer);
if (! mbox_specified) {
if (pending) { /* keep some messages pending! */
sprintf(outfile,"%s%d", temp_mbox, getpid());
unlink(outfile);
}
else if (mailbox_defined) /* save to specified mailbox */
strcpy(outfile, mailbox);
else /* save to $home/mbox */
sprintf(outfile,"%s/mbox", home);
}
else {
if (! to_delete) return(FALSE); /* no work to do! */
sprintf(outfile, "%s%d", temp_file, getpid());
unlink(outfile); /* ensure it's empty! */
}
if (to_save) {
if ((errno = can_open(outfile, "a"))) {
error1(
"Permission to append to %s denied! Leaving mailbox intact\n",
outfile);
dprint2(1,
"Error: Permission to append to outfile %s denied!! (%s)\n",
outfile, "leavembox");
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
unlock();
return(0);
}
if ((temp = fopen(outfile,"a")) == NULL) {
if (mbox_specified == 0)
unlock(); /* remove mailfile lock! */
dprint1(1,"Error: could not append to file %s\n",
outfile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
sprintf(buffer, " Could not append to file %s! ",
outfile);
emergency_exit(Centerline(LINES-1, buffer));
}
for (i = 0; i < message_count; i++)
if (! (header_table[i].status & DELETED)) {
current = i+1;
if (! number_saved++) {
dprint2(2,"Saving message%s #%d, ", plural(to_save), current);
}
else {
dprint1(2,"#%d, ", current);
}
copy_message("", temp, FALSE, FALSE);
}
fclose(temp);
dprint0(2,"\n\n");
}
/* remove source file...either default mailbox or original copy of
specified one! */
if (mbox_specified == 0) {
/** let's grab the original mode and date/time of the mailfile
before removing it **/
if (stat(infile, &buf) == 0)
mode = buf.st_mode & 00777;
else {
dprint2(1,"Error: errno %s attempting to stat file %s\n",
error_name(errno), infile);
error2("Error %s (%s) on stat(%s)", error_name(errno),
error_description(errno), infile);
}
}
fclose(mailfile); /* close the baby... */
if (mailfile_size != bytes(infile)) {
sort_mailbox(message_count, FALSE); /* display sorting order! */
unlock();
error("New mail has just arrived - resyncing...");
return(-1);
}
unlink(infile); /* and BLAMO! */
if (to_save && (mbox_specified || pending)) {
if (link(outfile, infile) != 0)
if (errno == EXDEV) { /** different file devices! Use copy! **/
if (copy(outfile, infile) != 0) {
dprint2(1,"leavembox: copy(%s, %s) failed;",
outfile, infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error("couldn't modify mail file!");
sleep(1);
sprintf(infile,"%s/%s", home, unedited_mail);
if (copy(outfile, infile) != 0) {
dprint1(1,"leavembox: couldn't copy to %s either!! Help;",
infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error("something godawful is happening to me!!!");
emergency_exit();
}
else {
dprint1(1,"\nWoah! Confused - Saved mail in %s (leavembox)\n",
infile);
error1("saved mail in %s", infile);
}
}
}
else {
dprint2(1,"link(%s, %s) failed (leavembox)\n", outfile, infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error2("link failed! %s - %s", error_name(errno),
error_description(errno));
emergency_exit();
}
unlink(outfile);
}
if (mbox_specified == 0) {
if (mode != 00644) { /* if not the default mail access mode... */
if (! pending) { /* if none still being saved */
temp = fopen(infile, "w");
fclose(temp);
}
chmod(infile,mode);
/* let's set the access times of the new mail file to be
the same as the OLD one (still sitting in 'buf') ! */
times.actime = buf.st_atime;
times.modtime= buf.st_mtime;
if (utime(infile, ×) != 0) {
dprint0(1,"Error: encountered error doing utime (leavmbox)\n");
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error2("Error %s trying to change file %s access time",
error_name(errno), infile);
}
}
unlock(); /* remove the lock on the file ASAP! */
/** finally, let's change the ownership of the default
outgoing mailbox, if needed **/
if (to_save)
chown(outfile, userid, groupid);
}
#ifdef SAVE_GROUP_MAILBOX_ID
chown(infile, userid, getegid()); /** see the Config Guide **/
#else
chown(infile, userid, groupid); /** file owned by user **/
#endif
return(to_delete);
}
char lock_name[SLEN];
lock(direction)
int direction;
{
/** Create lock file to ensure that we don't get any mail
while altering the mailbox contents!
If it already exists sit and spin until
either the lock file is removed...indicating new mail
or
we have iterated MAX_ATTEMPTS times, in which case we
either fail or remove it and make our own (determined
by if REMOVE_AT_LAST is defined in header file
If direction == INCOMING then DON'T remove the lock file
on the way out! (It'd mess up whatever created it!).
**/
register int iteration = 0, access_val;
sprintf(lock_name,"%s%s.lock", mailhome, username);
access_val = access(lock_name, ACCESS_EXISTS);
while (access_val != -1 && iteration++ < MAX_ATTEMPTS) {
dprint1(2,"File '%s' currently exists! Waiting...(lock)\n",
lock_name);
if (direction == INCOMING)
PutLine0(LINES, 0, "\nMail being received!\twaiting...");
else
error1("Attempt %d: Mail being received...waiting",
iteration);
sleep(5);
access_val = access(lock_name, ACCESS_EXISTS);
}
if (access_val != -1) {
#ifdef REMOVE_AT_LAST
/** time to waste the lock file! Must be there in error! **/
dprint0(2,
"Warning: I'm giving up waiting - removing lock file(lock)\n");
if (direction == INCOMING)
PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
else
error("Throwing away the current lock file!");
if (unlink(lock_name) != 0) {
dprint3(1,"Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
error_name(errno), error_description(errno), lock_name);
PutLine1(LINES, 0,
"\n\rI couldn't remove the current lock file %s\n\r",
lock_name);
PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
error_description(errno));
if (direction == INCOMING)
leave();
else
emergency_exit();
}
/* everything is okay, so lets act as if nothing had happened... */
#else
/* okay...we die and leave, not updating the mailfile mbox or
any of those! */
if (direction == INCOMING) {
PutLine1(LINES, 0, "\nGiving up after %d iterations...", iteration);
PutLine0(LINES, 0,
"Please try to read your mail again in a few minutes.\n");
dprint1(2,"Warning:bailing out after %d iterations...(lock)\n",
iteration);
leave_locked();
}
else {
dprint1(2,"Warning: after %d iterations, timed out! (lock)\n",
iteration);
leave(error("Timed out on lock file reads. Leaving program"));
}
#endif
}
/* if we get here we can create the lock file, so lets do it! */
if (creat(lock_name, 0) == -1) {
dprint2(1,"Can't create lock file: creat(%s) raises error %s (lock)\n",
lock_name, error_name(errno));
if (errno == EACCES)
leave(error1(
"Can't create lock file! I need write permission in %s!\n\r",
mailhome));
else {
dprint1(1,"Error encountered attempting to create lock %s\n",
lock_name);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
PutLine1(LINES, 0,
"\n\rError encountered while attempting to create lock file %s;\n\r",
lock_name);
PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
error_description(errno));
leave();
}
}
}
unlock()
{
/** Remove the lock file! This must be part of the interrupt
processing routine to ensure that the lock file is NEVER
left sitting in the mailhome directory! **/
(void) unlink(lock_name);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 12538 ]
then
echo $filename changed - should be 12538 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/bounceback.c ----------
filename="src/bounceback.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/bounceback.c...
fi
cat << 'END-OF-FILE' > $filename
/** bounceback.c **/
/** This set of routines implement the bounceback feature of the mailer.
This feature allows mail greater than 'n' hops away (n specified by
the user) to have a 'cc' to the user through the remote machine.
Due to the vagaries of the Internet addressing (uucp -> internet -> uucp)
this will NOT generate bounceback copies with mail to an internet host!
(C) Copyright 1986 by Dave Taylor
**/
#include "headers.h"
char *bounce_off_remote(); /* forward declaration */
int
uucp_hops(to)
char *to;
{
/** Given the entire "To:" list, return the number of hops in the
first address (a hop = a '!') or ZERO iff the address is to a
non uucp address.
**/
register int hopcount = 0, index;
for (index = 0; ! whitespace(to[index]) && to[index] != '\0'; index++) {
if (to[index] == '!')
hopcount++;
else if (to[index] == '@' || to[index] == '%' || to[index] == ':')
return(0); /* don't continue! */
}
return(hopcount);
}
char *bounce_off_remote(to)
char *to;
{
/** Return an address suitable for framing (no, that's not it...)
Er, suitable for including in a 'cc' line so that it ends up
with the bounceback address. The method is to take the first
address in the To: entry and break it into machines, then
build a message up from that. For example, consider the
following address:
a!b!c!d!e!joe
the bounceback address would be;
a!b!c!d!e!d!c!b!a!ourmachine!ourname
simple, eh?
**/
static char address[LONG_STRING]; /* BEEG address buffer! */
char host[MAX_HOPS][SHORT_SLEN]; /* for breaking up addr */
register int hostcount = 0, hindex = 0,
index;
for (index = 0; !whitespace(to[index]) && to[index] != '\0'; index++) {
if (to[index] == '!') {
host[hostcount][hindex] = '\0';
hostcount++;
hindex = 0;
}
else
host[hostcount][hindex++] = to[index];
}
/* we have hostcount hosts... */
strcpy(address, host[0]); /* initialize it! */
for (index=1; index < hostcount; index++) {
strcat(address, "!");
strcat(address, host[index]);
}
/* and now the same thing backwards... */
for (index = hostcount -2; index > -1; index--) {
strcat(address, "!");
strcat(address, host[index]);
}
/* and finally, let's tack on our machine and login name */
strcat(address, "!");
strcat(address, hostname);
strcat(address, "!");
strcat(address, username);
/* and we're done!! */
return( (char *) address );
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 2498 ]
then
echo $filename changed - should be 2498 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/opt_utils.c ----------
filename="src/opt_utils.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/opt_utils.c...
fi
cat << 'END-OF-FILE' > $filename
/** opt_utils.c **/
/** This file contains routines that might be needed for the various
machines that the mailer can run on. Please check the Makefile
for more help and/or information.
(C) Copyright 1986 Dave Taylor
**/
#include <stdio.h>
#ifdef BSD
# include <pwd.h>
#endif
#ifdef UTS
# include <sys/utsname.h>
# include <sys/tubio.h>
# define TTYIN 0 /* standard input */
gethostname(hostname,size) /* get name of current host */
int size;
char *hostname;
{
/** Return the name of the current host machine. UTS only **/
/** This routine compliments of Scott McGregor at the HP
Corporate Computing Center **/
int uname();
struct utsname name;
(void) uname(&name);
(void) strncpy(hostname,name.nodename,size-1);
hostname[size] = '\0';
}
int
isa3270()
{
/** Returns TRUE and sets LINES and COLUMNS to the correct values
for an Amdahl (IBM) tube screen, or returns FALSE if on a normal
terminal (of course, next to a 3270, ANYTHING is normal!!) **/
struct tubiocb tubecb;
dprint0(3,"Seeing if we're a 3270...");
if (ioctl(TTYIN, TUBGETMOD, &tubecb) == -1) {
dprint0(3,"We're not!\n");
return(FALSE); /* not a tube! */
}
LINES = tubecb->line_cnt - 1;
COLUMNS = tubecb->col_cnt;
dprint2(3,"We are! %d lines and %d columns!\n",
LINES, COLUMNS);
return(TRUE);
}
#endif /* def UTS */
#ifdef BSD
cuserid(uname)
char *uname;
{
/** Added for compatibility with Bell systems, this is the last-ditch
attempt to get the users login name, after getlogin() fails. It
instantiates "uname" to the name of the user...
**/
struct passwd *password_entry, *getpwuid();
password_entry = getpwuid(getuid());
strcpy(uname, password_entry->pw_name);
}
/** some supplementary string functions for Berkeley Unix systems **/
strspn(source, keys)
char *source, *keys;
{
/** This function returns the length of the substring of
'source' (starting at zero) that consists ENTIRELY of
characters from 'keys'. This is used to skip over a
defined set of characters with parsing, usually.
**/
register int loc = 0, key_index = 0;
while (source[loc] != '\0') {
key_index = 0;
while (keys[key_index] != source[loc])
if (keys[key_index++] == '\0')
return(loc);
loc++;
}
return(loc);
}
strcspn(source, keys)
char *source, *keys;
{
/** This function returns the length of the substring of
'source' (starting at zero) that consists entirely of
characters NOT from 'keys'. This is used to skip to a
defined set of characters with parsing, usually.
NOTE that this is the opposite of strspn() above
**/
register int loc = 0, key_index = 0;
while (source[loc] != '\0') {
key_index = 0;
while (keys[key_index] != '\0')
if (keys[key_index++] == source[loc])
return(loc);
loc++;
}
return(loc);
}
char *strtok(source, keys)
char *source, *keys;
{
/** This function returns a pointer to the next word in source
with the string considered broken up at the characters
contained in 'keys'. Source should be a character pointer
when this routine is first called, then NULL subsequently.
When strtok has exhausted the source string, it will
return NULL as the next word.
WARNING: This routine will DESTROY the string pointed to
by 'source' when first invoked. If you want to keep the
string, make a copy before using this routine!!
**/
register int last_ch;
static char *sourceptr;
char *return_value;
if (source != NULL)
sourceptr = source;
if (*sourceptr == '\0')
return(NULL); /* we hit end-of-string last time!? */
sourceptr += strspn(sourceptr, keys); /* skip leading crap */
if (*sourceptr == '\0')
return(NULL); /* we've hit end-of-string */
last_ch = strcspn(sourceptr, keys); /* end of good stuff */
return_value = sourceptr; /* and get the ret */
sourceptr += last_ch; /* ...value */
if (*sourceptr != '\0') /* don't forget if we're at END! */
sourceptr++; /* and skipping for next time */
return_value[last_ch] = '\0'; /* ..ending right */
return((char *) return_value); /* and we're outta here! */
}
char *strpbrk(source, keys)
char *source, *keys;
{
/** Returns a pointer to the first character of source that is any
of the specified keys, or NULL if none of the keys are present
in the source string.
**/
register int loc = 0, key_index = 0;
while (source[loc] != '\0') {
key_index = 0;
while (keys[key_index] != '\0')
if (keys[key_index++] == source[loc])
return((char *) (source + loc));
loc++;
}
return(NULL);
}
char *strchr(buffer, ch)
char *buffer, ch;
{
/** Returns a pointer to the first occurance of the character
'ch' in the specified string or NULL if it doesn't occur **/
char *address;
address = buffer;
while (*address != ch) {
if (*address == '\0')
return (NULL);
address++;
}
return ( (char *) address);
}
#endif
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 4997 ]
then
echo $filename changed - should be 4997 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/softkeys.c ----------
filename="src/softkeys.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/softkeys.c...
fi
cat << 'END-OF-FILE' > $filename
/** softkeys.c **/
/** This file and associated routines: (C) Copyright 1986, Dave Taylor **/
#include <stdio.h>
#include "headers.h"
define_softkeys(level)
int level;
{
if (! hp_softkeys) return;
if (level == MAIN) {
if (notesfile) {
define_key(f1, " Show Note", "\r");
define_key(f2, " Reply to Note", "r");
define_key(f3, " Change Mailbox", "c");
define_key(f4, " Save Note", "s");
define_key(f5, " Delete/Undelete", "^");
define_key(f6, " Print Note", "p");
define_key(f7, " HELP", "?");
define_key(f8, " Quit ELM", "q");
}
else {
define_key(f1, " Show Msg", "\r");
define_key(f2, " Mail Msg", "m");
define_key(f3, " Reply to Msg", "r");
define_key(f4, " Change Mailbox", "c");
define_key(f5, " Save Msg", "s");
define_key(f6, " Delete/Undelete", "^");
define_key(f7, " Print Msg", "p");
define_key(f8, " Quit ELM", "q");
}
}
else if (level == ALIAS) {
define_key(f1, " Alias Current", "a");
define_key(f2, " Check Alias", "c");
define_key(f3, " Make Alias", "m");
clear_key(f4);
clear_key(f5);
clear_key(f6);
clear_key(f7);
define_key(f8, " Return to ELM", "r");
}
else if (level == YESNO) {
define_key(f1, " Yes", "y");
clear_key(f2);
clear_key(f3);
clear_key(f4);
clear_key(f5);
clear_key(f6);
clear_key(f7);
define_key(f8, " No", "n");
}
else if (level == READ) {
define_key(f1, " Next Page ", " ");
clear_key(f2);
clear_key(f3);
clear_key(f4);
clear_key(f5);
clear_key(f6);
clear_key(f7);
define_key(f8, " Return to ELM", "\n");
}
else if (level == CHANGE) {
define_key(f1, " Mail Directry", "=/");
define_key(f2, " Home Directry", "~/");
clear_key(f3);
define_key(f4, "Incoming Mailbox", "!\n");
clear_key(f5);
clear_key(f6);
clear_key(f7);
define_key(f8, " Cancel", "\n");
}
softkeys_on();
}
define_key(key, display, send)
int key;
char *display, *send;
{
char buffer[30];
sprintf(buffer,"%s%s", display, send);
fprintf(stderr, "%c&f%dk%dd%dL%s", ESCAPE, key,
strlen(display), strlen(send), buffer);
fflush(stdout);
}
softkeys_on()
{
/* turn on softkeys (esc&jB) and turn on MENU and USER/SYSTEM */
if (hp_softkeys) {
fprintf(stderr, "%c&jB%c&jR", ESCAPE, ESCAPE);
fflush(stdout);
}
}
softkeys_off()
{
/* turn off softkeys (esc&j@) */
if (hp_softkeys) {
fprintf(stderr, "%c&j@", ESCAPE);
fflush(stdout);
}
}
clear_key(key)
{
/** set a key to nothing... **/
if (hp_softkeys)
define_key(key, " ", "");
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 2696 ]
then
echo $filename changed - should be 2696 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/mailmsg2.c ----------
filename="src/mailmsg2.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/mailmsg2.c...
fi
cat << 'END-OF-FILE' > $filename
/** mailmsg2.c **/
/** Interface to allow mail to be sent to users. Part of ELM **/
/** (C) Copyright 1986, Dave Taylor **/
#include "headers.h"
#include <errno.h>
extern int errno;
char *error_name(), *error_description();
char *format_long(), *strip_commas(), *tail_of_string();
FILE *write_header_info();
extern char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN],
priority[SLEN], to[VERY_LONG_STRING], cc[VERY_LONG_STRING],
in_reply_to[SLEN];
int gotten_key = 0;
char *bounce_off_remote();
mail(expanded_to, expanded_cc, copy_msg, edit_message, batch)
char *expanded_to, *expanded_cc;
int copy_msg, edit_message, batch;
{
/** Given the addresses and various other miscellany (specifically,
'copy-msg' indicates whether a copy of the current message should
be included, 'edit_message' indicates whether the message should
be edited and 'batch' indicates that the message should be read
from stdin) this routine will invoke an editor for the user and
then actually mail off the message.
**/
FILE *reply, *real_reply; /* second is post-input buffer */
char filename[SLEN], filename2[SLEN],
very_long_buffer[VERY_LONG_STRING];
char ret_ch, ch;
register int retransmit = FALSE;
static int cancelled_msg = 0;
dprint2(4,"\nMailing to '%s' (with%s editing)\n",
expanded_to, edit_message? "" : "out");
/** first generate the temporary filename **/
sprintf(filename,"%s%d",temp_file, getpid());
/** if possible, let's try to recall the last message? **/
if (! batch)
retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg);
/** if we're not retransmitting, create the file.. **/
if (! retransmit)
if ((reply = fopen(filename,"w")) == NULL) {
dprint2(1,
"Attempt to write to temp file %s failed with error %s (mail)\n",
filename, error_name(errno));
error2("Could not create file %s (%s)",filename,
error_name(errno));
return(1);
}
if (batch) {
Raw(OFF);
ret_ch = '\n';
if (isatty(fileno(stdin))) {
printf("To: %s\nSubject: %s\n", expanded_to, subject);
printf("\nPlease enter your message, ending with a ^D:\n\n");
ret_ch = '\0';
}
while (gets(very_long_buffer, VERY_LONG_STRING) != NULL)
fprintf(reply, "%s%c", very_long_buffer, ret_ch);
if (isatty(fileno(stdin)))
printf("<end-of-message>\n");
}
if (copy_msg && ! retransmit) /* if retransmit we ALREADY have it! */
if (edit_message)
copy_message(prefixchars, reply, noheader, FALSE);
else
copy_message("", reply, noheader, FALSE);
if (!batch && ! retransmit && signature) {
sprintf(filename2, "%s/%s", home, signature_file);
(void) append(reply, filename2);
}
if (! retransmit)
(void) fclose(reply); /* on replies, it won't be open! */
/** Edit the message **/
if (edit_message)
create_readmsg_file(); /* for "readmsg" routine */
ch = edit_message? 'e' : 'e'; /* drop through if needed... */
if (! batch) {
do {
switch (ch) {
case 'e' : if (edit_message) edit_the_message(filename);
/** now let's try reading it again... **/
(void) fclose(reply); /* make sure it's closed */
if ((reply = fopen(filename,"r")) == NULL) {
dprint2(1,
"Attempt to open file %s for reading failed with error %s (mail)\n",
filename, error_name(errno));
error1("Could not open reply file (%s)",
error_name(errno));
return(1);
}
break;
case 'h' : edit_headers();
break;
}
/** ask that silly question again... **/
if ((ch = verify_transmission()) == 'f') { /* cancelled it! */
cancelled_msg = TRUE;
return(1);
}
} while (ch != 's');
}
else if ((reply = fopen(filename,"r")) == NULL) {
dprint2(1,
"Attempt to open file %s for reading failed with error %s (mail)\n",
filename, error_name(errno));
error1("Could not open reply file (%s)", error_name(errno));
return(1);
}
cancelled_msg = FALSE; /* it ain't cancelled, is it? */
/** ask about bounceback if the user wants us to.... **/
if (uucp_hops(to) > bounceback && bounceback > 0)
if (verify_bounceback() == TRUE) {
if (strlen(cc) > 0) strcat(cc, ", ");
strcat(cc, bounce_off_remote(to));
}
/** grab a copy if the user so desires... **/
if (auto_cc && ! batch)
save_copy(subject, expanded_to, expanded_cc, filename, to);
/** write all header information into real_reply **/
sprintf(filename2,"%s%d",temp_file, getpid()+1);
/** try to write headers to new temp file **/
dprint2(5, "Composition file='%s' and mail buffer='%s'\n",
filename, filename2);
if ((real_reply=write_header_info(filename2, expanded_to, expanded_cc))
== NULL) {
/** IT FAILED!! MEIN GOTT! Use a dumb mailer instead! **/
dprint1(3,"** write_header failed: %s\n", error_name(errno));
if (cc[0] != '\0') /* copies! */
sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
mailx, subject, strip_commas(expanded_to),
remove, filename, filename);
error1("Message sent using dumb mailer - %s", mailx);
sleep(2); /* ensure time to see this prompt! */
}
else {
copy_message_across(reply, real_reply);
fclose(real_reply);
if (cc[0] != '\0') /* copies! */
sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
if (access(sendmail, EXECUTE_ACCESS) == 0) /* Yeah! Sendmail! */
sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s",
sendmail, smflags, strip_commas(expanded_to),
remove, filename2, filename2);
else /* oh well, use default mailer... */
sprintf(very_long_buffer,"( (%s %s ; %s %s) & ) < %s",
mailer, strip_commas(expanded_to),
remove, filename2, filename2);
}
fclose(reply);
if (mail_only) {
printf("sending mail...");
fflush(stdout);
}
else {
PutLine0(LINES,0,"sending mail...");
CleartoEOLN();
}
system_call(very_long_buffer, SH);
if (mail_only)
printf("\rmail sent! \n\r");
else
set_error("Mail sent!");
return(TRUE);
}
int
recall_last_msg(filename, copy_msg, cancelled_msg)
char *filename;
int copy_msg, *cancelled_msg;
{
/** If filename exists and we've recently cancelled a message,
the ask if the user wants to use that message instead! This
routine returns TRUE if the user wants to retransmit the last
message, FALSE otherwise...
**/
register int retransmit = FALSE;
if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
Raw(ON);
CleartoEOLN();
if (copy_msg)
PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
BACKSPACE);
else
PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c",
BACKSPACE);
fflush(stdout);
if (tolower(ReadCh()) != 'n') {
Write_to_screen("Yes",0);
retransmit++;
}
else
Write_to_screen("No",0);
fflush(stdout);
*cancelled_msg = 0;
}
return(retransmit);
}
edit_the_message(filename)
char *filename;
{
/** Invoke the users editor on the filename. Return when done. **/
char buffer[SLEN];
register int stat;
PutLine0(LINES, 0, "invoking editor..."); fflush(stdout);
sprintf(buffer,"%s %s", editor, filename);
Raw(OFF);
chown(filename, userid, groupid); /* file was owned by root! */
if (cursor_control)
transmit_functions(OFF); /* function keys are local */
if ((stat = system_call(buffer, SH)) != 0) {
dprint1(1,"System call failed with stat %d (edit_the_message)\n",
stat);
error1("Can't invoke editor '%s' for composition", editor);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
ClearLine(LINES-1);
sleep(2);
}
if (cursor_control)
transmit_functions(ON); /* function keys are local */
Raw(ON);
}
int
verify_transmission()
{
/** Ensure the user wants to send this. This routine returns
TRUE if everything is okay, FALSE if cancelled. **/
char ch;
if (mail_only) {
if (isatty(fileno(stdin))) {
printf("\n\rAre you sure you want to send this? (y/n) ");
CleartoEOLN();
printf("y%c", BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) == 'n') { /* >SIGH< */
printf("No\n\r\n\r\n\rMail not sent!!\n\r");
return('f'); /* forget it! */
}
else
printf("Yes\n\r\n\r");
return('s'); /* send this baby! */
}
else
return('s'); /* ditto */
}
else if (check_first) { /* used to check strlen(infile) > 0 too? */
reprompt:
MoveCursor(LINES,0);
CleartoEOLN();
ClearLine(LINES-1);
PutLine1(LINES-1, 0,
"Please choose: E)dit msg, edit H)eaders, S)end, or F)orget : s%c",
BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
ch = tolower(ReadCh());
switch (ch) {
case 'f': Write_to_screen("Forget",0);
set_error(
"Message kept - Can be restored at next F)orward, M)ail or R)eply ");
break;
case '\n' :
case '\r' :
case 's' : Write_to_screen("Send",0);
ch = 's'; /* make sure! */
break;
case 'e' : Write_to_screen("Edit",0);
break;
case 'h' : Write_to_screen("Headers",0);
break;
default : Write_to_screen("%c??", 1, 07); /* BEEP */
sleep(1);
goto reprompt; /* yech */
}
return(ch);
}
}
FILE *
write_header_info(filename, long_to, long_cc)
char *filename, *long_to, *long_cc;
{
/** Try to open filedesc as the specified filename. If we can,
then write all the headers into the file. The routine returns
'filedesc' if it succeeded, NULL otherwise **/
static FILE *filedesc; /* our friendly file descriptor */
FILE *headerfdesc; /* file descriptor for .elmheaders */
char fnamebuffer[SLEN]; /* buffer for filename creation */
char buffer[LONG_SLEN]; /* .elmheader file reading buffer */
char *get_arpa_date();
if ((filedesc = fopen(filename, "w")) == NULL) {
dprint1(1,
"Attempt to open file %s for writing failed! (write_header_info)\n",
filename);
dprint2(1,"** %s - %s **\n\n", error_name(errno),
error_description(errno));
error2("Error %s encountered trying to write to %s",
error_name(errno), filename);
sleep(2);
return(NULL); /* couldn't open it!! */
}
fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
fprintf(filedesc,"Date: %s\n", get_arpa_date());
#ifndef DONT_ADD_FROM
# ifdef INTERNET_ADDRESS_FORMAT
# ifdef USE_DOMAIN
fprintf(filedesc,"From: %s@%s%s (%s)\n", username, hostname,
DOMAIN, full_username);
# else
fprintf(filedesc,"From: %s@%s (%s)\n", username, hostname,
full_username);
# endif
# else
fprintf(filedesc,"From: %s!%s (%s)\n", hostname, username,
full_username);
# endif
#endif
fprintf(filedesc, "Subject: %s\n", subject);
if (cc[0] != '\0')
fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
if (strlen(action) > 0)
fprintf(filedesc, "Action: %s\n", action);
if (strlen(priority) > 0)
fprintf(filedesc, "Priority: %s\n", priority);
if (strlen(expires) > 0)
fprintf(filedesc, "Expiration-Date: %s\n", expires);
if (strlen(reply_to) > 0)
fprintf(filedesc, "Reply-To: %s\n", reply_to);
if (strlen(in_reply_to) > 0)
fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
/*** add the users .mailheaders file if available ***/
sprintf(fnamebuffer, "%s/%s", home, mailheaders);
if ((headerfdesc = fopen(fnamebuffer, "r")) != NULL) {
while (fgets(buffer, LONG_SLEN, headerfdesc) != NULL)
if (strlen(buffer) < 2) {
dprint0(2,
"Strlen of line from .elmheaders is < 2 (write_header_info)");
error1("Warning: blank line in %s ignored!", fnamebuffer);
sleep(2);
}
else
fprintf(filedesc, "%s", buffer);
fclose(headerfdesc);
}
fprintf(filedesc, "X-Mailer: ELM [version %s]\n\n", VERSION);
return((FILE *) filedesc);
}
copy_message_across(source, dest)
FILE *source, *dest;
{
/** copy the message in the file pointed to by source to the
file pointed to by dest. **/
int crypted = FALSE; /* are we encrypting? */
int encoded_lines = 0; /* # lines encoded */
char buffer[LONG_SLEN]; /* file reading buffer */
while (fgets(buffer, LONG_SLEN, source) != NULL) {
if (buffer[0] == '[') {
if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
crypted = TRUE;
else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
crypted = FALSE;
else if (strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
continue; /* next line? */
}
else if (crypted) {
if (! gotten_key++)
getkey(ON);
else if (! encoded_lines++)
get_key_no_prompt(); /* reinitialize.. */
encode(buffer);
}
fputs(buffer, dest);
}
}
int
verify_bounceback()
{
/** Ensure the user wants to have a bounceback copy too. (This is
only called on messages that are greater than the specified
threshold hops and NEVER for non-uucp addresses.... Returns
TRUE iff the user wants to bounce a copy back....
**/
if (mail_only) {
printf("Would you like a copy \"bounced\" off the remote? (y/n) ");
CleartoEOLN();
printf("n%c", BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) != 'y') {
printf("No\n\r");
return(FALSE);
}
else
printf("Yes - Bounceback included\n\r");
}
else {
MoveCursor(LINES,0);
CleartoEOLN();
PutLine1(LINES,0,
"\"Bounce\" a copy off the remote machine? (y/n) y%c",
BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) != 'y') {
Write_to_screen("No", 0);
fflush(stdout);
return(FALSE);
}
Write_to_screen("Yes!", 0);
fflush(stdout);
}
return(TRUE);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 14200 ]
then
echo $filename changed - should be 14200 bytes, not $size bytes
fi
chmod 644 $filename
fi
# ---------- file src/savecopy.c ----------
filename="src/savecopy.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file src/savecopy.c...
fi
cat << 'END-OF-FILE' > $filename
/** savecopy.c **/
/** Save a copy of the specified message in the users savemail mailbox.
(C) Copyright 1986, Dave Taylor
**/
#include "headers.h"
#ifdef BSD
# include <sys/time.h>
#else
# include <time.h>
#endif
#include <errno.h>
char *format_long(), *get_arpa_date();
char *error_name(), *error_description();
char *ctime();
extern char in_reply_to[SLEN]; /* In-Reply-To: string */
extern int gotten_key; /* for encryption */
extern int errno;
save_copy(subject, to, cc, filename, original_to)
char *subject, *to, *cc, *filename, *original_to;
{
/** This routine appends a copy of the outgoing message to the
file specified by the SAVEFILE environment variable. **/
FILE *save, /* file id for file to save to */
*message; /* the actual message body */
long thetime; /* variable holder for time */
char buffer[SLEN], /* read buffer */
savename[SLEN], /* name of file saving into */
newbuffer[SLEN]; /* first name in 'to' line */
register int i; /* for chopping 'to' line up */
int crypted=0; /* are we encrypting? */
savename[0] = '\0';
if (save_by_name) {
get_return_name(to, buffer, FALSE);
if (strlen(buffer) == 0) {
dprint1(3,"Warning: get_return_name couldn't break down %s\n", to);
savename[0] = '\0';
}
else {
sprintf(savename, "%s%s%s", folders,
lastch(folders) == '/'? "" : "/", buffer);
if ((errno = can_access(savename, READ_ACCESS)))
savename[0] = '\0';
}
}
if (strlen(savename) == 0) {
if (strlen(savefile) == 0)
return(error("variable 'SAVEFILE' not defined!"));
strcpy(savename, savefile);
}
if ((errno = can_access(savename, WRITE_ACCESS))) {
dprint0(2,"Error: attempt to autosave to a file that can't...\n");
dprint1(2,"\tbe appended to: %s (save_copy)\n", savename);
dprint2(2,"** %s - %s **\n", error_name(errno),
error_description(errno));
error1("permission to append to %s denied!", savename);
sleep(2);
return(FALSE);
}
if ((save = fopen(savename, "a")) == NULL) {
dprint2(1,"Error: Couldn't append message to file %s (%s)\n",
savename, "save_copy");
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error1("couldn't append to %s", savename);
sleep(2);
return(FALSE);
}
if ((message = fopen(filename, "r")) == NULL) {
fclose(save);
dprint1(1,"Error: Couldn't read file %s (save_copy)\n", filename);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error1("couldn't read file %s!", filename);
sleep(2);
return(FALSE);
}
for (i=0; original_to[i] != '\0' && ! whitespace(original_to[i]); i++)
newbuffer[i] = original_to[i];
newbuffer[i] = '\0';
tail_of(newbuffer, buffer, FALSE);
thetime = (long) time(0); /* this must be here for it to work! */
fprintf(save,"\nFrom To:%s %s", buffer, ctime(&thetime));
fprintf(save, "Date: %s\n", get_arpa_date());
fprintf(save,"To: %s\nSubject: %s\n",
format_long(to,strlen("To: ")), subject);
if (strlen(cc) > 0)
fprintf(save,"Cc: %s\n",
format_long(cc, strlen("Cc:")));
if (strlen(in_reply_to) > 0)
fprintf(save, "In-Reply-To: %s\n", in_reply_to);
(void) putc('\n', save); /* put another return, please! */
/** now copy over the message... **/
while (fgets(buffer, SLEN, message) != NULL) {
if (buffer[0] == '[') {
if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
crypted = 1;
else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
crypted = 0;
else if (strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0) {
fclose(message);
fclose(save);
chown(savename, userid, groupid);
return(TRUE);
}
}
else if (crypted) {
if (! gotten_key++)
getkey(ON);
encode(buffer);
}
fputs(buffer, save);
}
fclose(message);
fclose(save);
/* make sure save file isn't owned by root! */
chown(savename, userid, groupid);
return(TRUE);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 4059 ]
then
echo $filename changed - should be 4059 bytes, not $size bytes
fi
chmod 644 $filename
fi
echo end of this archive file....
exit 0