Msg Shar.part.4
sources-request at panda.UUCP
sources-request at panda.UUCP
Sun Mar 2 23:37:42 AEST 1986
Mod.sources: Volume 4, Issue 8
Submitted by: decvax!hplabs!hpcnou!dat (Dave Taylor)
# Msg Shar part 4 of 7
# Shell Archive created by hpcnou!dat at Wed Feb 26 15:56:20 1986
# 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
# This archive contains;
# src/file_utils.c src/fileio.c src/hdrconfg.c src/help.c
# src/initialize.c src/input_utils.c src/leavembox.c src/mailout.c
# src/mailtime.c src/mkhdrs.c src/msg.c
if [ ! -d src ]
then
echo creating directory src
mkdir src
fi
# ---------- file src/file_utils.c ----------
if [ -f src/file_utils.c ]
then
echo File 'src/file_utils.c' already exists\!
exit 1
fi
echo extracting file src/file_utils.c...
cat << 'END-OF-FILE' > src/file_utils.c
/** file_utils.c **/
/** File oriented utility routines for MSG
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
#include <signal.h>
#include <errno.h>
long
bytes(name)
char *name;
{
/** return the number of bytes in the specified file. This
is to check to see if new mail has arrived.... **/
int ok = 1;
extern int errno; /* system error number! */
struct stat buffer;
if (stat(name, &buffer) != 0)
if (errno != 2) {
dprint2("\n\n*** bytes() Error %d on fstat(%s)\n\n", errno, name);
leave(error2("Error %d attempting fstat on %s", errno, name));
}
else
ok = 0;
return(ok ? (long) buffer.st_size : 0L);
}
int
can_access(file, mode)
char *file, *mode;
{
/** returns TRUE iff user can access file **/
int status, pid, w;
register int (*istat)(), (*qstat)();
if ((pid = fork()) == 0) {
setuid(userid); /** back to normal userid **/
exit(fopen(file, mode) != NULL);
_exit(127);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
while ((w = wait(&status)) != pid && w != -1)
;
if (w == -1) status = FALSE;
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
return(status);
}
int
copy(from, to)
char *from, *to;
{
/** this routine copies a specified file to the destination
specified. Non-zero return code indicates that something
dreadful happened! **/
FILE *from_file, *to_file;
char buffer[VERY_LONG_STRING];
dprint2("copy(from='%s', to='%s')\n", from, to);
if ((from_file = fopen(from, "r")) == NULL)
return(error1("could not open file %s", from));
if ((to_file = fopen(to, "w")) == NULL)
return(error1("could not open file %s", to));
while (fgets(buffer, VERY_LONG_STRING, from_file) != NULL)
fputs(buffer, to_file);
fclose(from_file);
fclose(to_file);
return(0);
}
check_mailfile_size()
{
/** Check to ensure we have mail. Only used with the '-z'
starting option. **/
char filename[SLEN], username[NLEN];
struct stat buffer;
strcpy(username,getlogin());
if (strlen(username) == 0)
cuserid(username);
sprintf(filename,"%s/%s", mailhome, username);
if (stat(filename, &buffer) == -1) {
printf(" You have no mail.\n");
exit(0);
}
else if (buffer.st_size < 2) { /* maybe one byte??? */
printf("You have no mail to read.\n");
exit(0);
}
}
END-OF-FILE
size=`wc -c < src/file_utils.c`
if [ $size != 2421 ]
then
echo Warning: src/file_utils.c changed - should be 2421 bytes, not $size bytes
fi
chmod 644 src/file_utils.c
# ---------- file src/fileio.c ----------
if [ -f src/fileio.c ]
then
echo File 'src/fileio.c' already exists\!
exit 1
fi
echo extracting file src/fileio.c...
cat << 'END-OF-FILE' > src/fileio.c
/** fileio.c **/
/** File I/O routines, including deletion from the mailbox!
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
copy_message(prefix, dest_file, remove_header)
char *prefix;
FILE *dest_file;
int remove_header;
{
/** Copy current message to destination file, with optional 'prefix'
as the prefix for each line. If remove_header is true, it will
skip lines in the message until it finds the end of header line...
then it will start copying into the file... **/
char buffer[LONG_SLEN];
int ok = 1, lines, in_header = 1;
dprint2("copy_message(prefix='%s', <file>, remove-header=%s)\n", prefix,
remove_header? "ON" : "OFF");
/** get to the first line of the message desired **/
if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
error1("msg [seek] failed trying to read %d bytes into file",
header_table[current-1].offset);
return;
}
/* how many lines in message? */
lines = header_table[current-1].lines;
dprint2("\tAbout to read %d lines from msg #%d\n",
lines, current);
/* now while not EOF & still in message... copy it! */
while (ok && lines--) {
ok = (int) (fgets(buffer, LONG_SLEN, mailfile) != NULL);
if (strlen(buffer) < 2) in_header = 0;
if (ok)
if (! (remove_header && in_header))
fprintf(dest_file, "%s%s", prefix, buffer);
}
}
END-OF-FILE
size=`wc -c < src/fileio.c`
if [ $size != 1472 ]
then
echo Warning: src/fileio.c changed - should be 1472 bytes, not $size bytes
fi
chmod 644 src/fileio.c
# ---------- file src/hdrconfg.c ----------
if [ -f src/hdrconfg.c ]
then
echo File 'src/hdrconfg.c' already exists\!
exit 1
fi
echo extracting file src/hdrconfg.c...
cat << 'END-OF-FILE' > src/hdrconfg.c
/** hdrconfg.c **/
/** This file contains the routines necessary to be able to modify
the mail headers of messages on the way off the machine. The
headers currently supported for modification are:
Subject:
To:
Cc:
Expiration-Date:
Priority:
In-Reply-To:
Action:
Security:
(C) Copyright 1985, Dave Taylor
**/
#include <stdio.h>
#include "headers.h"
#include <ctype.h>
#ifdef BSD
#undef toupper
#endif
/* these are all defined in the mailout file! */
extern char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN],
priority[SLEN];
extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING];
edit_headers(original_msg_num)
int original_msg_num;
{
/** edit headers, R)eturn to continue with mailing **/
int unexpanded_to = TRUE, unexpanded_cc = TRUE;
char c, expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING];
dprint1("edit_headers(original-msg-number=%d)\n", original_msg_num);
if (! edit_outbound || mail_only) goto outta_here;
display_headers();
do {
PutLine(LINES-1,0,"Choice: ");
CleartoEOLN();
c = toupper(getchar());
clear_error();
switch (c) {
case ctrl('M'):
case 'R' :
case 'Q' : goto outta_here;
case ctrl('L') : display_headers();
break;
case 'T' : if (optionally_enter(to, 2, 9, TRUE) == -1)
goto outta_here;
build_address(strip_commas(to), expanded_to);
unexpanded_to = FALSE;
break;
case 'S' : if (optionally_enter(subject, 3, 9, FALSE) == -1)
goto outta_here;
break;
case 'C' : if (optionally_enter(cc, 4, 9, TRUE) == -1)
goto outta_here;
build_address(strip_commas(cc), expanded_cc);
unexpanded_cc = FALSE;
break;
case 'A' : if (optionally_enter(action, 6, 9, FALSE) == -1)
goto outta_here;
break;
case 'E' : enter_date(7, 17, expires);
break;
case 'P' : if (optionally_enter(priority, 9,10, FALSE) == -1)
goto outta_here;
break;
case 'I' : if (original_msg_num != -1) {
if (optionally_enter(reply_to, 8,13, FALSE) == -1)
goto outta_here;
break;
}
/** else fall through as an error **/
default : error("Unknown header being specified!");
}
} while (TRUE);
outta_here: /* this section re-expands aliases before we leave... */
if (unexpanded_to)
build_address(strip_commas(to), expanded_to);
if (unexpanded_cc)
build_address(strip_commas(cc), expanded_cc);
strcpy(to, expanded_to);
strcpy(cc, expanded_cc);
return;
}
display_headers()
{
ClearScreen();
Centerline(0,"Message Header Edit Screen");
PutLine(2,0,"To : %s", to);
PutLine(3,0,"Subject: %s", subject);
PutLine(4,0,"Cc : %s", cc);
PutLine(6,0,"Action :");
PutLine(7,0,"Expiration-Date:");
if (strlen(reply_to) > 0)
PutLine(8,0,"In-Reply-To: %s", reply_to);
PutLine(9,0,"Priority:");
Centerline(LINES-5,
"Pick the First Letter of the Header or R)eturn from Editing");
}
enter_date(x, y, buffer)
int x, y;
char *buffer;
{
/** Enter the number of days this message is valid for, then
display at (x,y) the actual date of expiration. This
routine relies heavily on the routine 'days_ahead()' in
the file date.c
**/
int days;
PutLine(LINES-1,0, "How many days in the future should it expire? ");
CleartoEOLN();
Raw(OFF);
gets(buffer, SLEN);
Raw(ON);
sscanf(buffer, "%d", &days);
if (days < 1)
error("That doesn't make sense!");
else if (days > 14)
error("Expiration date must be within two weeks of today");
else {
error1("days_ahead(%d)", days);
days_ahead(days, buffer);
PutLine(x, y, buffer);
}
}
END-OF-FILE
size=`wc -c < src/hdrconfg.c`
if [ $size != 3711 ]
then
echo Warning: src/hdrconfg.c changed - should be 3711 bytes, not $size bytes
fi
chmod 644 src/hdrconfg.c
# ---------- file src/help.c ----------
if [ -f src/help.c ]
then
echo File 'src/help.c' already exists\!
exit 1
fi
echo extracting file src/help.c...
cat << 'END-OF-FILE' > src/help.c
/** help.c **/
/*** help routine for MSG program
(C) Copyright 1985, Dave Taylor
***/
#include "headers.h"
help()
{
/*** help me! Read file 'helpfile' and echo to screen ***/
FILE *hfile;
char buffer[SLEN];
int lines=0;
dprint0("help()\n");
sprintf(buffer, "%s/%s", helphome, helpfile);
if ((hfile = fopen(buffer,"r")) == NULL) {
error1("couldn't open helpfile %s",buffer);
return(FALSE);
}
ClearScreen();
while (fgets(buffer, SLEN, hfile) != NULL) {
if (lines > LINES-3) {
PutLine(LINES,0,"Press any key to continue: ");
(void) ReadCh();
lines = 0;
ClearScreen();
printf("%s\r", buffer);
}
else
printf("%s\r", buffer);
lines++;
}
PutLine(LINES,0,"Please type <space> to return: ");
(void) ReadCh();
clear_error();
return(TRUE);
}
END-OF-FILE
size=`wc -c < src/help.c`
if [ $size != 821 ]
then
echo Warning: src/help.c changed - should be 821 bytes, not $size bytes
fi
chmod 644 src/help.c
# ---------- file src/initialize.c ----------
if [ -f src/initialize.c ]
then
echo File 'src/initialize.c' already exists\!
exit 1
fi
echo extracting file src/initialize.c...
cat << 'END-OF-FILE' > src/initialize.c
/** initialize.c **/
/***** Initialize - read in all the defaults etc etc
(C) Copyright 1985 Dave Taylor
*****/
#include <stdio.h>
#ifndef BSD
# include <termio.h>
#endif
#include <pwd.h>
#ifdef BSD
# include <sys/time.h>
#else
# include <time.h>
#endif
#include <signal.h>
#include <errno.h>
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
#include "headers.h"
extern int errno; /* system error number on failure */
initialize()
{
struct passwd *pass, *getpwnam();
register int i;
int leave();
char buffer[SLEN];
userid = getuid();
progid = geteuid();
strcpy(home,getenv("HOME"));
strcpy(shell,getenv("SHELL"));
if (debug) { /* setup for dprintf statements! */
char filename[SLEN];
sprintf(filename, "%s/%s", home, DEBUG);
if ((debugfile = fopen(filename, "w")) == NULL) {
debug = 0; /* otherwise 'leave' will try to log! */
leave(fprintf(stderr,"Could not open file %s for debug output!\n",
filename));
}
chown(filename, userid, getgid()); /* file owned by user */
fprintf(stderr,"\r\n** Debug output going to '%s' **\n\r", filename);
sleep(2);
fprintf(debugfile, "\nDebug output of MSG program, version %s\n\n",
VERSION);
}
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, leave);
signal(SIGTERM, leave);
read_lsys();
get_term_chars();
gethostname(hostname, sizeof(hostname));
strcpy(username,getlogin());
if (strlen(username) == 0)
cuserid(username);
/* now let's get the full username.. */
if ((pass = getpwnam(username)) == NULL) {
error("Couldn't read password entry??");
strcpy(full_username, username);
}
else {
for (i=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
i++)
full_username[i] = pass->pw_gecos[i];
full_username[i] = '\0';
}
editor[0] = '\0';
strcpy(editor,getenv("EDITOR"));
if (editor[0] == '\0')
strcpy(editor,default_editor);
if (! mail_only) {
mailbox[0] = '\0';
strcpy(prefixchars, "> "); /* default message prefix */
}
read_rc_file(); /* reading the .msgrc next... */
/** check to see if the user has defined a LINES or COLUMNS
value different to that in the termcap entry (for
windowing systems, of course!) **/
strcpy(buffer, getenv("LINES"));
if (isdigit(buffer[0]))
sscanf(buffer, "%d", &LINES);
strcpy(buffer, getenv("COLUMNS"));
if (isdigit(buffer[0]))
sscanf(buffer, "%d", &COLUMNS);
/** fix the shell if needed **/
if (shell[0] != '/') {
sprintf(buffer, "/bin/%s", shell);
strcpy(shell, buffer);
}
if (! mail_only) {
mailbox_defined = (mailbox[0] != '\0');
/* now get the inverse video sequences from the termcap... */
strcpy(start_highlight, return_value_of("so"));
strcpy(end_highlight, return_value_of("se"));
/* get the cursor control keys... */
strcpy(up, return_value_of("ku"));
if (strlen(up) != 2) /* don't want arbitrary length! */
cursor_control = FALSE;
else {
strcpy(down, return_value_of("kd"));
cursor_control = TRUE;
transmit_functions(ON);
}
}
if (read_aliases)
read_alias_files();
if (! mail_only) {
if (! mbox_specified)
newmbox(1,FALSE); /* read the incoming mail mailbox! */
else
newmbox(0,FALSE); /* read the specified mail file! */
if (mini_menu)
headers_per_page = LINES - 13;
else
headers_per_page = LINES - 8; /* 5 more headers! */
}
init_findnode(); /* set up the path alias stuff */
dprint0("\n\n------ Past the Initialization stuff ------\n\n");
dprint3("\nhostname = '%s' username = '%s' full_username = '%s'\n",
hostname, username, full_username);
dprint3("home = '%s' editor = '%s' mailbox = '%s'\n",
home, editor, mailbox);
dprint3("hp_terminal = %s, hp_softkeys = %s, and cursor_control=%s\n\n",
onoff(hp_terminal), onoff(hp_softkeys), onoff(cursor_control));
}
get_term_chars()
{
/** This routine sucks out the special terminal characters
ERASE and KILL for use in the input routine. The meaning
of the characters are (dare I say it?) fairly obvious... **/
#ifndef BSD
struct termio term_buffer;
if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
dprint1("** Error %d encountered on initial ioctl call **\n", errno);
/* set to defaults for terminal driver */
#endif
backspace = BACKSPACE;
kill_line = ctrl('U');
#ifndef BSD
}
else {
backspace = term_buffer.c_cc[VERASE];
kill_line = term_buffer.c_cc[VKILL];
}
#endif
}
read_lsys()
{
/** Read the system L.sys file and put all the machine names in
the talk-to-sys linked list structure! **/
FILE *lsysfile;
char buffer[SLEN], sysname[NLEN];
struct lsys_rec *system_record, *previous_record;
previous_record = NULL;
if ((lsysfile = fopen(Lsys,"r")) == NULL) {
dprint1("\nCan't open L.sys file '%s' for reading!!\n\n",
Lsys);
error("Warning: couldn't read L.sys file...");
talk_to_sys = NULL;
return;
}
while (fgets(buffer, SLEN, lsysfile) != NULL) {
sscanf(buffer,"%s", sysname);
if (previous_record == NULL) {
dprint1("\tread '%s' out of L.sys file\n", sysname);
previous_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
strcpy(previous_record->name, sysname);
previous_record->next = NULL;
talk_to_sys = previous_record;
}
else if (! talk_to(sysname)) {
dprint1("\tread '%s' out of L.sys file\n", sysname);
system_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
strcpy(system_record->name, sysname);
system_record->next = NULL;
previous_record->next = system_record;
previous_record = system_record;
}
}
fclose(lsysfile);
}
END-OF-FILE
size=`wc -c < src/initialize.c`
if [ $size != 5676 ]
then
echo Warning: src/initialize.c changed - should be 5676 bytes, not $size bytes
fi
chmod 644 src/initialize.c
# ---------- file src/input_utils.c ----------
if [ -f src/input_utils.c ]
then
echo File 'src/input_utils.c' already exists\!
exit 1
fi
echo extracting file src/input_utils.c...
cat << 'END-OF-FILE' > src/input_utils.c
/** input_utils.c **/
/** Mindless I/O routines for MSG
(C) Copyright 1985 Dave Taylor
**/
#include "headers.h"
int
want_to(s, def, echo_answer)
char *s, def;
int echo_answer;
{
/** ask 's' at 20,40, return answer in lower case.
If 'echo_answer', then echo answer. 'def' is the
default answer if <return> is pressed.
**/
register char ch;
if (strlen(s) < 30)
MoveCursor(LINES-3, COLUMNS-40);
else
MoveCursor(LINES-3, COLUMNS-50);
printf("%s%c%c", s, def, BACKSPACE);
fflush(stdout);
ch = tolower(ReadCh());
if (echo_answer && ch > (char) ' ')
putchar(ch);
return(ch);
}
int
read_number(ch, max)
char ch;
int max;
{
/** read a number, where 'ch' is the leading digit!
If max < 10 then just return 'ch' **/
char buff[SHORT_SLEN];
int num;
if (max < 10)
return( (int) ch - '0' );
buff[0] = ch;
buff[1] = '\0';
PutLine(LINES-3, COLUMNS-40,"Set current message to :");
if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE) == -1)
return(current);
sscanf(buff,"%d", &num);
return(num);
}
int
optionally_enter(string, x, y, append_current)
char *string;
int x,y, append_current;
{
/** Display the string on the screen and if RETURN is pressed, return
it. Otherwise, allow standard text input, including backspaces
and such until RETURN is hit.
If "append_current" is set, then leave the default string in
place and edit AFTER it...assume 'x,y' is placing us at the
beginning of the string...
This routine returns zero unless INTERRUPT hit, then it returns
-1 and must be treated accordingly.
**/
char ch;
register index = 0;
MoveCursor(x,y);
printf("%s", string);
CleartoEOLN();
if (! append_current)
MoveCursor(x,y);
if (cursor_control)
transmit_functions(OFF);
ch = getchar();
if (ch == '\n' || ch == '\r') {
if (cursor_control)
transmit_functions(ON);
return(0); /* we're done. No change needed */
}
CleartoEOLN();
index = (append_current? strlen(string) : 0);
if (ch == kill_line) {
if (! mail_only)
MoveCursor(x,y);
CleartoEOLN();
index = 0;
}
else if (ch != backspace) {
putchar(ch);
string[index++] = ch;
}
else if (index > 0) {
index--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
fflush(stdout);
}
else {
putchar(' ');
putchar(BACKSPACE);
fflush(stdout);
}
do {
ch = getchar();
/* the following is converted from a case statement to
allow the variable characters (backspace, kill_line
and break) to be processed. Case statements in
C require constants as labels, so it failed ...
*/
if (ch == backspace) {
if (index > 0) {
index--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
fflush(stdout);
}
else {
putchar(' ');
putchar(BACKSPACE);
fflush(stdout);
}
}
else if (ch == '\n' || ch == '\r') {
string[index] = '\0';
if (cursor_control)
transmit_functions(ON);
return(0);
}
else if (ch == kill_line) {
if (mail_only)
back_up(index+1);
else
MoveCursor(x,y);
CleartoEOLN();
index = 0;
}
else if (ch == NULL) {
if (cursor_control)
transmit_functions(ON);
fflush(stdin); /* remove extraneous chars, if any */
string[0] = '\0'; /* clean up string, and... */
return(-1);
}
else { /* default case */
string[index++] = ch;
putchar(ch);
}
} while (index < SLEN);
string[index] = '\0';
if (cursor_control)
transmit_functions(ON);
return(0);
}
int
pattern_enter(string, alt_string, x, y, alternate_prompt)
char *string, *alt_string, *alternate_prompt;
int x,y;
{
/** This function is functionally similar to the routine
optionally-enter, but if the first character pressed
is a '/' character, then the alternate prompt and string
are used rather than the normal one. This routine
returns 1 if alternate was used, 0 if not
**/
char ch;
register index = 0;
dprint4("pattern_enter(string='%s', alt_string='%s', x=%d, y=%d,\n",
string, alt_string, x, y);
dprint1(" alt-prompt='%s')\n", alternate_prompt);
MoveCursor(x,y);
printf("%s", string);
CleartoEOLN();
MoveCursor(x,y);
if (cursor_control)
transmit_functions(OFF);
ch = getchar();
if (ch == '\n' || ch == '\r') {
if (cursor_control)
transmit_functions(ON);
return(0); /* we're done. No change needed */
}
if (ch == '/') {
MoveCursor(x, 0);
CleartoEOLN();
printf("%s", alternate_prompt);
(void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
FALSE);
return(1);
}
CleartoEOLN();
index = 0;
if (ch == kill_line) {
MoveCursor(x,y);
CleartoEOLN();
index = 0;
}
else if (ch != backspace) {
putchar(ch);
string[index++] = ch;
}
else if (index > 0) {
index--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
}
else {
putchar(' ');
putchar(BACKSPACE);
}
do {
fflush(stdout);
ch = getchar();
/* the following is converted from a case statement to
allow the variable characters (backspace, kill_line
and break) to be processed. Case statements in
C require constants as labels, so it failed ...
*/
if (ch == backspace) {
if (index > 0) {
index--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
}
else {
putchar(' ');
putchar(BACKSPACE);
}
}
else if (ch == '\n' || ch == '\r') {
string[index] = '\0';
if (cursor_control)
transmit_functions(ON);
return(0);
}
else if (ch == kill_line) {
MoveCursor(x,y);
CleartoEOLN();
index = 0;
}
else if (ch == NULL) {
if (cursor_control)
transmit_functions(ON);
fflush(stdin); /* remove extraneous chars, if any */
string[0] = '\0'; /* clean up string, and... */
return(-1);
}
else { /* default case */
string[index++] = ch;
putchar(ch);
}
} while (index < SLEN);
string[index] = '\0';
if (cursor_control)
transmit_functions(ON);
return(0);
}
back_up(spaces)
int spaces;
{
/** this routine is to replace the goto x,y call for when sending
mail without starting the entire "msg" system up... **/
dprint1("back-up(spaces=%d)\n", spaces);
while (spaces--) {
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
}
fflush(stdout);
}
END-OF-FILE
size=`wc -c < src/input_utils.c`
if [ $size != 6604 ]
then
echo Warning: src/input_utils.c changed - should be 6604 bytes, not $size bytes
fi
chmod 644 src/input_utils.c
# ---------- file src/leavembox.c ----------
if [ -f src/leavembox.c ]
then
echo File 'src/leavembox.c' already exists\!
exit 1
fi
echo extracting file src/leavembox.c...
cat << 'END-OF-FILE' > src/leavembox.c
/** 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;
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 TRUE iff mailfile was
changed (ie messages deleted from file)
**/
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;
dprint0("leave_mbox()\n");
if (message_count == 0)
return(FALSE); /* nothing changed */
for (i = 0; i < message_count; i++)
if (header_table[i].delete) to_delete++;
else to_save++;
dprint2("\t%d messages to delete and %d to save\n", to_delete, to_save);
if (mbox_specified == 0)
update_mailtime();
if (to_delete)
if (to_save) {
sprintf(buffer, "Delete message%s? (y/n) ", to_save == 1? "" : "s");
if (want_to(buffer, 'n', ECHOIT) != 'y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint0("\tNothing deleted ('n' to delete messages)\n");
error("Nothing deleted");
return(FALSE); /* nothing was deleted! */
}
}
else if (! to_save)
if (want_to("Delete all messages? (y/n) ", 'n', ECHOIT) != 'y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint0("\tNothing deleted (don't want to delete all msgs)\n");
error("Nothing deleted");
return(FALSE); /* nothing was deleted */
}
if (to_save && mbox_specified == 0)
if (want_to("Keep mail in incoming mailbox? (y/n) ",'n',ECHOIT)=='y')
if (to_delete) /* okay - keep undeleted as pending! */
pending++;
else { /* gag! nothing to delete, don't save! */
unlock(); /* remove mailfile lock! */
dprint0("\tIncoming mailbox unchanged (nothing to delete\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';
}
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 ((temp = fopen(outfile,"a")) == NULL) {
if (mbox_specified == 0)
unlock(); /* remove mailfile lock! */
dprint1("\tCould not append to file %s!\n", outfile);
sprintf(buffer, " Could not append to file %s! ",
outfile);
leave(Centerline(LINES-1, buffer));
}
for (i = 0; i < message_count; i++)
if (header_table[i].delete == 0) {
current = i+1;
dprint1("\tsaving message %d\n", current);
copy_message("", temp, FALSE);
}
fclose(temp);
}
/* 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("\tencountered error #%d on stat(%s)\n", errno, infile);
error2("Error %d on stat(%s)!", errno, infile);
}
}
fclose(mailfile); /* close the baby... */
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("\tCouldn't modify mail file: copy(%s, %s) failed!\n",
outfile, infile);
error("couldn't modify mail file!");
sleep(1);
sprintf(infile,"%s/%s", home, unedited_mail);
if (copy(outfile, infile) != 0) {
dprint1("\tcouldn't copy to %s either!! Help!\n", infile);
error("something godawful is happening to me!!!");
emergency_exit();
}
else {
dprint1("\tsaved mailbox as file %s\n", infile);
error1("saved mailbox as %s", infile);
}
}
}
else {
dprint3("\tlink(%s, %s) failed with error %d\n", outfile,
infile, errno);
error1("link failed for unknown reasons [errno=%d!!", 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) {
dprint2("\tencountered error %d on utime(%s)\n",
errno, infile);
error1("Error %d trying utime", errno);
}
}
unlock(); /* remove the lock on the file ASAP! */
/** finally, let's change the ownership of the default
outgoing mailbox, if needed **/
if (to_save) {
dprint3("\tchown(%s, %d, %d)\n", outfile, userid, getgid());
chown(outfile, userid, getgid());
}
}
dprint3("\tchown(%s, %d, %d)\n", infile, userid, getgid());
chown(infile, userid, getgid()); /* file owned by user */
return(to_delete);
}
char lock_name[SLEN];
extern int errno; /* system error number! */
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, stat_val;
struct stat buffer;
dprint1("lock(direction=%s)\n", direction? "INCOMING" : "OUTGOING");
sprintf(lock_name,"%s%s.lock", mailhome, username);
stat_val = stat(lock_name, &buffer);
while (stat_val != -1 && iteration++ < MAX_ATTEMPTS) {
dprint2("\tstat(%s) returned %d\n",
lock_name, stat_val);
if (direction == INCOMING)
fprintf(stderr,"Mail being received!\nwaiting...");
else
error2("Attempt %d: Mail being received (%d)...waiting",
iteration, stat_val);
sleep(5);
stat_val = stat(lock_name, &buffer);
}
if (stat_val != -1) {
#ifdef REMOVE_AT_LAST
/** time to waste the lock file! Must be there in error! **/
error("Throwing away the current lock file!");
dprint0("\tthrowing away current lock file!\n");
if (unlink(lock_name) != 0) {
dprint0("\tcouldn't unlink!! Error was %d\n", errno);
leave(error("could not remove current lock file!"));
}
/* 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) {
printf("Giving up after %d iterations...\n", iteration);
printf("Try again later, please.\n");
dprint1("\tbailing out after %d iterations...\n", iteration);
leave_locked();
}
else {
dprint1("\ttimed out on lock file reads. Iterations=%d\n",
iteration);
leave(error("Timed out on lock file reads. Bye!"));
}
#endif
}
/* if we get here we can create the lock file, so lets do it! */
if (creat(lock_name, 0) == -1) {
dprint2("\tCan't create lock file: creat(%s) raises error %d\n",
lock_name, errno);
if (errno == EACCES)
leave(error(
"Can't create lock file! Make sure I'm setuid root!\n\r"));
else
leave(error1("error %d attempting to create lock file!", errno));
}
}
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! **/
dprint0("unlock()\n");
(void) unlink(lock_name);
}
END-OF-FILE
size=`wc -c < src/leavembox.c`
if [ $size != 9540 ]
then
echo Warning: src/leavembox.c changed - should be 9540 bytes, not $size bytes
fi
chmod 644 src/leavembox.c
# ---------- file src/mailout.c ----------
if [ -f src/mailout.c ]
then
echo File 'src/mailout.c' already exists\!
exit 1
fi
echo extracting file src/mailout.c...
cat << 'END-OF-FILE' > src/mailout.c
/** mailout.c **/
/** Interface to allow mail to be sent to users. Part of MSG **/
/** (C) Copyright 1986, Dave Taylor **/
/** System output is a line of the form;
sendmail -oi addresses < tempfile
or
mailer addresses < tempfile
Changed 8/12 to conform to RFC-822 style headers (ARPA and so on)
Changed 9/23 to deal with commas, and other bug fixes
Changed 9/24 to add reading the users .mailheaders file
Changed 10/26 to use the shared subject, to, cc, etc fields
Changed 2/20 to use batch_subject, if specified
**/
#include "headers.h"
/** strings defined for the hdrconfg routines **/
char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN], priority[SLEN];
char to[VERY_LONG_STRING], cc[VERY_LONG_STRING];
char *format_long(), *strip_commas(), *tail_of_string();
int gotten_key = 0;
int
send(given_to, given_subject, edit_message)
char *given_to, *given_subject;
int edit_message;
{
/** Prompt for fields and then call mail() to send the specified
message. If 'edit_message' is true then don't allow the
message to be edited. **/
char address[VERY_LONG_STRING]; /* BIG address! */
char addressII[VERY_LONG_STRING];
char *buffer; /* misc, for I/O */
int copy_msg = FALSE, is_a_response = FALSE;
dprint2("send(to='%s', subject='%s')\n", given_to, given_subject);
/* zero all current global message strings */
cc[0] = action[0] = reply_to[0] = expires[0] = priority[0] = '\0';
addressII[0] = '\0';
/* initialize 'to' and 'subject' according to what we were given */
strcpy(subject, given_subject);
strcpy(to, given_to);
/** Copy message? **/
if (strlen(to) > 0 && !mail_only) { /* predefined 'to' line! */
if (auto_copy)
copy_msg = TRUE;
else
copy_msg = (want_to("Copy message? (y/n) ", 'n', TRUE) == 'y');
is_a_response = TRUE;
}
else
if (strlen(subject) > 0) /* predefined 'subject' (Forward) */
copy_msg = TRUE;
/** To: **/
if (strlen(to) == 0) {
PutLine(LINES-2, 0, "To: ");
(void) optionally_enter(to, LINES-2, 4, FALSE);
if (strlen(to) == 0) {
MoveCursor(LINES-2,0); CleartoEOLN();
error("mail not sent");
return(0);
}
build_address(strip_commas(to), address);
}
else if (mail_only)
build_address(strip_commas(to), address);
else
strcpy(address, to);
if (strlen(address) == 0) { /* bad address! Removed!! */
if (! mail_only)
ClearLine(LINES-2);
return(0);
}
if (! mail_only) {
MoveCursor(LINES-3, COLUMNS-50);
CleartoEOLN();
printf(" "); /* 10 spaces */
}
if (mail_only && strlen(batch_subject) > 0) {
/** User wants to send the mail without editing or anything...
just suck in stdin for the file and don't prompt for anything!
**/
strcpy(subject, batch_subject);
mail(address, NULL, FALSE, FALSE, FALSE, TRUE);
return;
}
if (mail_only && check_only) {
printf("Expands to: %s\n", format_long(address, 12));
leave();
}
if (mail_only)
printf("To: %s\n\r", format_long(address));
else {
if (strlen(address) > COLUMNS-50) {
buffer = tail_of_string(address, COLUMNS-50);
printf("To: (%s)", buffer);
}
else
printf("To: %s", address);
}
/** Subject: **/
if (mail_only)
printf("Subject: ");
else
PutLine(LINES-2,0,"Subject: ");
CleartoEOLN();
if (optionally_enter(subject, LINES-2, 9, TRUE) == -1) {
MoveCursor(LINES-2,0); CleartoEOLN();
error("mail not sent");
return(0);
}
if (strlen(subject) == 0) {
if (mail_only)
printf("\n\rNo subject - Continue with message? (y/n) ");
else
PutLine(LINES-2,0,"No subject - Continue with message? (y/n) ");
printf("n%c", BACKSPACE);
fflush(stdout);
if (tolower(ReadCh()) != 'y') {
if (mail_only) {
printf("\n\r\n\rMail Cancelled!\n\r");
return(0);
}
MoveCursor(LINES-2,0); CleartoEOLN();
error("mail not sent");
return(0);
}
else if (! mail_only) {
PutLine(LINES-2,0,"Subject: <none>");
CleartoEOLN();
}
}
/** Copies to: **/
if (mail_only)
printf("\n\rCopies To: ");
else
PutLine(LINES-1,0,"Copies To: ");
fflush(stdout);
if (optionally_enter(cc, LINES-1, 11, FALSE) == -1) {
if (mail_only) {
printf("\n\r\n\rMail not sent!\n\r");
return(0);
}
MoveCursor(LINES-2,0); CleartoEOLN();
MoveCursor(LINES-1,0); CleartoEOLN();
error("mail not sent");
return(0);
}
build_address(strip_commas(cc), addressII);
if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
error("Too many people. Copies ignored");
cc[0] = '\0';
}
if (mail_only)
printf("\n\r");
else
MoveCursor(LINES,0); /* you know you're hit <return> ! */
/* and mail that puppy outta here! */
mail(address, addressII, copy_msg, is_a_response, edit_message, FALSE);
return(edit_message);
}
mail(expanded_to, expanded_cc, copy_msg, is_a_response, edit_message, batch)
char *expanded_to, *expanded_cc;
int copy_msg, is_a_response, edit_message, batch;
{
/** Given the addresses and various other miscellany (specifically,
'copy-msg' indicates whether a copy of the current message should
be included, 'is-a-response' indicates if 'In-Reply-To:' should be
generated for this message, '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 */
FILE *headerfile; /* copy default headers */
char buffer[LONG_SLEN], filename[SLEN], filename2[SLEN],
very_long_buffer[VERY_LONG_STRING];
char hfname[SLEN], ret_ch;
register int i, crypted=0, encoded_lines = 0, retransmit = 0;
static int cancelled_msg = 0;
dprint6("mail(to='%s', cc='%s', copy-msg=%s, is-a-response=%s, edit-message=%s, batch=%s)\n",
expanded_to, expanded_cc, onoff(copy_msg),
onoff(is_a_response), onoff(edit_message), onoff(batch));
sprintf(filename,"%s%d",temp_file, getpid());
if (! batch) {
if ((reply = fopen(filename,"r")) != NULL && cancelled_msg) {
Raw(ON);
if (copy_msg)
PutLine(LINES-1,0,"Recall last kept message instead? (y/n) ");
else
PutLine(LINES-1,0,"Recall last kept message? (y/n) ");
CleartoEOS();
printf("y%c", BACKSPACE);
fflush(stdout);
if (tolower(ReadCh()) != 'n') {
printf("Yes"); fflush(stdout);
retransmit++;
}
else {
printf("No"); fflush(stdout);
fclose(reply);
}
cancelled_msg = 0;
}
}
if (! retransmit)
if ((reply = fopen(filename,"w")) == NULL)
return(error1("Could not create file %s",filename));
if (copy_msg)
if (edit_message)
copy_message(prefixchars, reply, noheader);
else
copy_message("", reply, noheader);
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("\n<end-of-message>\n");
}
fclose(reply);
if (edit_message) {
sprintf(buffer,"%s %s", editor, filename);
Raw(OFF);
chown(filename, userid, getgid());
if ((i =system_call(buffer,SH)) != 0) { /* edit mail as user */
error1("Problems with the editor: error %d", i);
MoveCursor(LINES-1,0); CleartoEOLN();
sleep(2);
}
Raw(ON);
}
if ((reply = fopen(filename,"r")) == NULL)
return(error("Could not open reply file"));
/* make sure this twit really wants to send mail before we go any
further! */
generate_reply_to((is_a_response? current-1 : -1));
edit_headers((is_a_response? current-1 : -1));
if (check_first && ! batch) {
if (mail_only) {
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(0);
}
else
printf("Yes\n\r\n\r");
}
else {
MoveCursor(LINES,0);
CleartoEOLN();
MoveCursor(LINES-1,0);
printf("Are 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");
set_error(
"Message kept - Can be restored at next F)orward, M)ail or R)eply ");
cancelled_msg = 1;
fclose(reply);
return(1);
}
printf("Yes!");
fflush(stdout);
}
}
cancelled_msg = 0; /* it ain't cancelled, is it? */
/** 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);
if ((real_reply = fopen(filename2,"w")) == NULL) {
/* contingency: use mailx... */
if (cc[0] != '\0') /* copies! */
sprintf(to,"%s %s", to, cc);
sprintf(very_long_buffer, "(%s -s \"%s\" %s < %s ; %s %s)&",
mailx, subject, strip_commas(to), filename, remove, filename);
error1("couldn't open %s for writing!", filename2);
sleep(2); /* ensure time to see this prompt! */
}
else {
/* write header to file then message... */
fprintf(real_reply, "To: %s\n", format_long(to, strlen("To:")));
fprintf(real_reply,"Date: %s\n", (char *) get_arpa_date());
fprintf(real_reply,"From: %s!%s (%s)\n", hostname, username,
full_username);
fprintf(real_reply, "Subject: %s\n", subject);
if (cc[0] != '\0')
fprintf(real_reply, "Cc: %s\n",
format_long(cc, strlen("Cc: ")));
if (strlen(action) > 0)
fprintf(real_reply, "Action: %s\n", action);
if (strlen(priority) > 0)
fprintf(real_reply, "Priority: %s\n", priority);
if (strlen(expires) > 0)
fprintf(real_reply, "Expiration-Date: %s\n", expires);
if (strlen(reply_to) > 0)
fprintf(real_reply, "In-Reply-To: %s\n", reply_to);
/*** add the users .mailheaders file if available ***/
sprintf(hfname, "%s/%s", home, mailheaders);
if ((headerfile = fopen(hfname, "r")) != NULL) {
while (fgets(buffer, LONG_SLEN, headerfile) != NULL)
fprintf(real_reply, "%s", buffer);
fclose(headerfile);
}
fprintf(real_reply, "X-Mailer: msg [version %s]\n", VERSION);
fprintf(real_reply, "\n");
/** now copy message across! **/
while (fgets(buffer, LONG_SLEN, reply) != 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)
continue; /* next line? */
}
else if (crypted) {
if (! gotten_key++)
getkey(ON);
else if (! encoded_lines++)
get_key_no_prompt(); /* reinitialize.. */
encode(buffer);
}
fputs(buffer, real_reply);
}
fclose(reply);
fclose(real_reply);
if (cc[0] != '\0') /* copies! */
sprintf(to,"%s %s", to, cc);
if (access(sendmail, EXECUTE_ACCESS) == 0) /* yeah! Sendmail! */
sprintf(very_long_buffer,"(%s %s %s < %s ; %s %s) &",
sendmail, sendmailflags, strip_commas(to), filename2,
remove, filename2);
else /* oh well, use default mailer... */
sprintf(very_long_buffer,"(%s %s < %s ; %s %s) &",
mailer, strip_commas(to), filename2,
remove, filename2);
}
if (mail_only) {
if (! batch) {
printf("sending mail...");
fflush(stdout);
}
}
else {
PutLine(LINES,0,"sending mail...");
CleartoEOLN();
}
dprint1("\n\n\t%s\n\n", very_long_buffer);
system(very_long_buffer);
if (mail_only) {
if (! batch)
printf("\rmail sent! \n\r");
}
else
set_error("Mail sent!");
return(TRUE);
}
END-OF-FILE
size=`wc -c < src/mailout.c`
if [ $size != 12387 ]
then
echo Warning: src/mailout.c changed - should be 12387 bytes, not $size bytes
fi
chmod 644 src/mailout.c
# ---------- file src/mailtime.c ----------
if [ -f src/mailtime.c ]
then
echo File 'src/mailtime.c' already exists\!
exit 1
fi
echo extracting file src/mailtime.c...
cat << 'END-OF-FILE' > src/mailtime.c
/** 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 **/
dprint0("resolve_received(<entry>)\n");
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));
dprint3("\tthis message received %d/%d/%d at",
entry->received.month,
entry->received.day,
entry->received.year);
dprint2("%d:%d\n", 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];
dprint0("get_mailtime()\n");
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;
}
dprint3("\tmail time set to %d/%d/%d at ", last_read_mail.month,
last_read_mail.day, last_read_mail.year);
dprint2("%d:%02d\n", last_read_mail.hour, last_read_mail.minute);
}
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];
sprintf(filename, "%s/%s", home, mailtime_file);
if (utime(filename, NULL) == -1)
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
size=`wc -c < src/mailtime.c`
if [ $size != 4529 ]
then
echo Warning: src/mailtime.c changed - should be 4529 bytes, not $size bytes
fi
chmod 644 src/mailtime.c
# ---------- file src/mkhdrs.c ----------
if [ -f src/mkhdrs.c ]
then
echo File 'src/mkhdrs.c' already exists\!
exit 1
fi
echo extracting file src/mkhdrs.c...
cat << 'END-OF-FILE' > src/mkhdrs.c
/** mkhdrs.c **/
/** This contains all the header generating routines for the MSG
program.
(C) Copyright 1985 Dave Taylor
**/
#include <stdio.h>
#include "headers.h"
extern char reply_to[SLEN];
generate_reply_to(msg)
int msg;
{
/** Generate an 'in-reply-to' message... **/
char buffer[SLEN];
if (msg == -1) /* not a reply! */
reply_to[0] = '\0';
else {
if (chloc(header_table[msg].from, '!') != -1)
tail_of(header_table[msg].from, buffer, FALSE);
else
strcpy(buffer, header_table[msg].from);
sprintf(reply_to, "Message from \"%s\" of %s %s, %s at %s",
buffer,
header_table[msg].month,
header_table[msg].day,
header_table[msg].year,
header_table[msg].time);
}
}
END-OF-FILE
size=`wc -c < src/mkhdrs.c`
if [ $size != 728 ]
then
echo Warning: src/mkhdrs.c changed - should be 728 bytes, not $size bytes
fi
chmod 644 src/mkhdrs.c
# ---------- file src/msg.c ----------
if [ -f src/msg.c ]
then
echo File 'src/msg.c' already exists\!
exit 1
fi
echo extracting file src/msg.c...
cat << 'END-OF-FILE' > src/msg.c
/** msg.c **/
/* main program of the MSG mail system!
This file and all associated files and documentation:
(C) Copyright 1986 Dave Taylor
*/
#include "msg.h"
main(argc, argv)
int argc;
char *argv[];
{
char ch, address[SLEN], to_whom[LONG_SLEN];
int redraw, /** do we need to rewrite the entire screen? **/
nuhead, /** or perhaps just the headers section... **/
nucurr, /** or just the current message pointer... **/
nufoot; /** clear lines 16 thru bottom and new menu **/
int i, size;/** number of bytes in file. Only mailbox! **/
int pageon; /** for when we receive new mail... **/
parse_arguments(argc, argv, to_whom);
if (mail_only) {
initialize();
Raw(ON);
dprint1("\n\n\tmail-only: mailing to %s\n\n", to_whom);
(void) send(to_whom, "", TRUE);
leave(0);
}
InitScreen();
ScreenSize(&LINES, &COLUMNS);
initialize();
showscreen();
size = bytes(infile);
dprint1("\tStarting mailbox size = %d bytes\n", size);
Raw(ON);
while (1) {
redraw = 0;
nuhead = 0;
nufoot = 0;
nucurr = 0;
if ((i = bytes(infile)) != size) {
if (debug)
error1("New mail in this file: %d bytes more", i - size);
else
error("New mail has arrived! Hang on...");
dprint1("\tnew mail in mailbox: %d bytes\n", i - size);
pageon = header_page;
newmbox(2, FALSE);
clear_error();
header_page = pageon;
showscreen();
size = i;
transmit_functions(ON); /* insurance */
}
prompt("Mail :");
CleartoEOLN();
ch = tolower(ReadCh());
CleartoEOS();
set_error(""); /* clear error buffer */
MoveCursor(LINES-3,COLUMNS-74);
dprint1("\n\nEntered command: %c\n\n\n", ch);
switch (ch) {
case '?' : redraw = help(); break;
case ' ' :
case '+' : header_page++; nuhead++;
if (move_when_paged)
current = header_page*headers_per_page + 1;
break;
case '-' : header_page--; nuhead++;
if (move_when_paged)
current = header_page*headers_per_page + 1;
break;
case '=' : if (current != 1) {
current = 1;
if (get_page(current))
nuhead++;
else
nucurr++;
} break;
case '*' : if (current != message_count) {
current = message_count;
if (get_page(current))
nuhead++;
else
nucurr++;
} break;
case '|' : putchar('|');
softkeys_off();
redraw = pipe();
softkeys_on(); break;
case '!' : putchar('!');
softkeys_off();
redraw = subshell();
softkeys_on(); break;
case '%' : get_return(address);
clear_error();
MoveCursor(LINES,(COLUMNS-strlen(address))/2);
printf("%.78s", address); break;
case '/' : if (pattern_match()) {
if (get_page(current))
nuhead++;
else
nucurr++;
}
else
error("pattern not found!");
break;
case 'a' : alias();
nufoot++;
define_softkeys(MAIN); break;
case 'c' : printf("Change mailbox");
define_softkeys(CHANGE);
file_changed = leave_mbox(FALSE);
dprint1("\tleave_mbox returned %s\n",
file_changed? "TRUE": "FALSE");
redraw = newmbox(0, TRUE);
size = bytes(infile);
define_softkeys(MAIN);
break;
case '^' :
case 'd' : delete((ch == 'd'));
if (resolve_mode) /* move after mail resolved */
if (current < message_count) {
current++;
if (get_page(current))
nuhead++;
else
nucurr++;
}
break;
case 'f' : printf("Forward");
define_softkeys(YESNO);
if (current > 0)
redraw = forward();
else
error("No mail to forward!");
define_softkeys(MAIN);
break;
case 'g' : printf("Group reply");
define_softkeys(YESNO);
fflush(stdout);
if (current > 0) {
PutLine(LINES-3,COLUMNS-40,
"building addresses...");
redraw = reply_to_everyone();
}
else
error("No mail to reply to!");
define_softkeys(MAIN);
break;
case 'h' : if (filter)
printf("Message with headers...");
else
printf("Next message");
fflush(stdout);
i = filter;
filter = FALSE;
redraw = show_msg(current);
filter = i;
break;
case 'm' : printf("Mail");
redraw = send("", "", TRUE);
break;
case ctrl('J'):
case ctrl('M'):printf("Read Message"); fflush(stdout);
define_softkeys(READ);
redraw = show_msg(current);
break;
case 'n' : printf("Next Message");
fflush(stdout);
define_softkeys(READ);
redraw = show_msg(current);
current += redraw;
(void) get_page(current); /* rewrites ANYway */
if (current > message_count)
current = message_count;
break;
case 'j' : current++;
if (get_page(current))
nuhead++;
else
nucurr++; break;
case 'k' : current--;
if (get_page(current))
nuhead++;
else
nucurr++; break;
case 'p' : printf("Print message");
fflush(stdout);
printmsg(); break;
case 'r' : printf("Reply to message");
if (current > 0)
redraw = reply();
else
error("No mail to reply to!"); break;
case '>' : /** backwards compatibility **/
case 's' : printf("Save Message");
if (save() && resolve_mode) {
delete(TRUE); /* mark for deletion */
if (current < message_count) {
current++; /* move to next message */
if (get_page(current))
nuhead++;
else
nucurr++;
}
}
ClearLine(LINES-2); break;
case 't' : error1("%s",(char *) get_date());break;
case 'q' : printf("Quit"); fflush(stdout);
if (mbox_specified == 0) {
lock(OUTGOING);
if (size != bytes(infile)) {
error("New Mail! Quit cancelled...");
unlock();
}
else
quit();
}
else
quit();
break;
case 'u' : undelete();
if (resolve_mode) /* move after mail resolved */
if (current < message_count) {
current++;
if (get_page(current))
nuhead++;
else
nucurr++;
}
break;
case ctrl('Q') :
case ctrl('Z') : /* exit fast! */
case ctrl('?') :
case 'x' : printf("Exit");
fflush(stdout); leave();
case ctrl('L') : redraw++; break;
case '@' : debug_screen(); redraw++; break;
case '#' : debug_message(); redraw++; break;
case ESCAPE : if (cursor_control) {
ch = ReadCh();
if (ch == up[1]) {
current--;
if (get_page(current))
nuhead++;
else
nucurr++;
}
else if (ch == down[1]) {
current++;
if (get_page(current))
nuhead++;
else
nucurr++;
}
else if (hp_terminal) { /* kludge! */
if (ch == 'U') { /* <NEXT> */
header_page++;
nuhead++;
if (move_when_paged)
current = header_page*headers_per_page + 1;
}
else if (ch == 'V') { /* <PREV> */
header_page--;
nuhead++;
if (move_when_paged)
current = header_page*headers_per_page + 1;
}
else if (ch == 'h') { /* <HOME UP> */
current = 1;
if (get_page(current))
nuhead++;
else
nucurr++;
}
else if (ch == 'F') { /* <HOME DOWN> */
current = message_count;
if (get_page(current))
nuhead++;
else
nucurr++;
}
else /* what DID they hit??? */
printf("%c%c", ESCAPE, ch);
}
else /* false hit - output */
printf("%c%c", ESCAPE, ch);
break;
}
/* else fall into default.. */
default : if (ch > '0' && ch <= '9') {
printf("New Current Message");
current = read_number(ch, message_count);
if (get_page(current))
nuhead++;
else
nucurr++;
}
else
error("Unknown command: Use '?' for commands");
}
if (redraw)
showscreen();
if (current < 1) {
if (message_count > 0) {
error("already at message #1!");
current = 1;
}
else if (current < 0) {
error("No messages to read!");
current = 0;
}
}
else if (current > message_count) {
if (message_count > 0) {
error2("only %d message%s!", message_count,
plural(message_count));
current = message_count;
}
else {
error("No messages to read!");
current = 0;
}
}
if (nuhead)
show_headers();
else if (nucurr)
show_current();
else if (nufoot) {
MoveCursor(LINES-7, 0);
CleartoEOS();
if (mini_menu)
show_menu();
}
} /* the BIG while loop! */
}
debug_screen()
{
/**** spit out all the current variable settings and the table
entries for the current 'n' items displayed. ****/
register int i, j;
ClearScreen();
Raw(OFF);
printf("Current message number = %d\t\t%d message(s) total\n\n",
current, message_count);
printf("Header_page = %d \t\t%d possible page(s)\n",
header_page, (int) (message_count / headers_per_page) + 1);
printf("\nCurrent mailfile is %s.\n\n", infile);
i = header_page*headers_per_page; /* starting header */
if ((j = i + (headers_per_page-1)) >= message_count)
j = message_count-1;
printf(
"Num From Subject Lines Offset\n\n");
while (i <= j) {
printf(
"%3d %-16.16s %-40.40s %4d %d\n",
i+1,
header_table[i].from,
header_table[i].subject,
header_table[i].lines,
header_table[i].offset);
i++;
}
Raw(ON);
PutLine(LINES,0,"Press any key to return: ");
(void) ReadCh();
}
debug_message()
{
/**** Spit out the current message record. Include EVERYTHING
in the record structure. **/
ClearScreen();
Raw(OFF);
printf("\t\t\t----- Message %d -----\n\n\n\n",
current);
printf("Lines : %-5d\t\t\t\tPriority message? %s\n\n",
header_table[current-1].lines,
header_table[current-1].priority? "YES" : "NO");
printf("Offset: %ld\t\t\t\t Delete message? %s\n\n\n",
header_table[current-1].offset,
header_table[current-1].delete? "YES" : "NO");
printf("Received on: %d/%d/%d at %d:%02d\n\n",
header_table[current-1].received.month+1,
header_table[current-1].received.day,
header_table[current-1].received.year,
header_table[current-1].received.hour,
header_table[current-1].received.minute);
printf("Msg sent on: %s, %s %s, %s at %s\n\n",
header_table[current-1].dayname,
header_table[current-1].month,
header_table[current-1].day,
header_table[current-1].year,
header_table[current-1].time);
printf("\nFrom: %s\n\nSubject: %s",
header_table[current-1].from,
header_table[current-1].subject);
Raw(ON);
PutLine(LINES,0,"Press any key to return: ");
(void) ReadCh();
}
END-OF-FILE
size=`wc -c < src/msg.c`
if [ $size != 12135 ]
then
echo Warning: src/msg.c changed - should be 12135 bytes, not $size bytes
fi
chmod 644 src/msg.c
echo done
exit 0
More information about the Mod.sources
mailing list