Msg Shar.part.5
sources-request at panda.UUCP
sources-request at panda.UUCP
Mon Mar 3 11:16:54 AEST 1986
Mod.sources: Volume 4, Issue 9
Submitted by: decvax!hplabs!hpcnou!dat (Dave Taylor)
# Msg Shar part 5 of 7
# Shell Archive created by hpcnou!dat at Wed Feb 26 15:56:34 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/notesfile.c src/opt_utils.c src/output_utils.c src/pattern.c
# src/quit.c src/read_rc.c src/reply.c src/return_addr.c
# src/savecopy.c src/screen.c src/showmsg.c src/softkeys.c
if [ ! -d src ]
then
echo creating directory src
mkdir src
fi
# ---------- file src/notesfile.c ----------
if [ -f src/notesfile.c ]
then
echo File 'src/notesfile.c' already exists\!
exit 1
fi
echo extracting file src/notesfile.c...
cat << 'END-OF-FILE' > src/notesfile.c
/** notesfile.c **/
/** Routine that reads in a file comprised of saved messages from
'notes'.
(C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <errno.h>
char *notes_machine();
extern int errno;
int
read_notesfile()
{
/** read in the current mailfile, assuming it's actually a set
of stored notes from the notes program... **/
char buffer[LONG_STRING];
register int line = 0, count = 0;
long bytes = 0L, line_bytes = 0L;
static int first_read = 0;
int count_x , count_y = 17;
dprint0("read_notesfile()\n");
if (! first_read++) {
MoveCursor(LINES-2, 0);
CleartoEOS();
PutLine(LINES-1, 0, "Reading in %s, message: 0", infile);
count_x = LINES-1;
count_y = 22 + strlen(infile);
}
else {
PutLine(LINES-2, 0, "Reading message: 0");
count_x = LINES-2;
}
while (fgets(buffer, LONG_STRING, mailfile) != NULL) {
if (line == 0) {
/** Double check to make sure this is okay... if the first
word is "From " then we're actually reading a normal
file so cruise over to the read_headers() routine
instead! **/
if (first_word(buffer, "From ")) {
notesfile = 0; /* turn that bloody flag off! */
rewind(mailfile); /* back up in da file... */
return( read_headers(FALSE) );
}
}
line_bytes = (long) strlen(buffer);
line++;
if (first_word(buffer, "/***** ")) {
if (real_notes_header(buffer, &header_table[count])) {
header_table[count].offset = (long) bytes;
header_table[count].delete = 0;
header_table[count++].lines = line;
header_table[count].priority = 0;
PutLine(count_x, count_y, "%d", count);
if (count > 1)
header_table[count-2].lines = line -header_table[count-2].lines;
}
}
bytes += (long) line_bytes;
}
total_lines_in_file = line;
header_table[count-1].lines = line - header_table[count-1].lines;
rewind(mailfile);
return(count);
}
int
real_notes_header(buffer, entry)
char *buffer;
struct header_rec *entry;
{
/** confirms that we're looking at a REAL notes header,
and if so, saves it in the appropriate data entry **/
char subjectbuffer[SLEN], timebuffer[NLEN], lastbuffer[NLEN],
am_pm[NLEN], the_day[NLEN], nullbuffer[NLEN];
dprint1("real_notes_header(buffer='%s')\n", buffer);
strcpy(nullbuffer, "NULL");
strcpy(lastbuffer, "LAST");
sscanf(buffer, "%*s %s %*c %s %*c %s %s %s %s %s %s",
subjectbuffer, entry->from,
timebuffer, am_pm, entry->month, the_day,
lastbuffer, nullbuffer);
if (strcmp(lastbuffer, "LAST") == 0)
return(0);
if (strcmp(nullbuffer,"NULL") != 0)
return(0);
if (timebuffer[1] != ':' && timebuffer[2] != ':')
return(0);
/* now let's play format! */
clean_up(subjectbuffer);
sprintf(entry->subject, "Note from group %s", subjectbuffer);
sprintf(entry->day,"%d", atoi(the_day));
sprintf(entry->year,"%d", atoi(lastbuffer) % 100);
sprintf(entry->time,"%s %s", timebuffer, am_pm);
return(1);
}
char *notes_machine()
{
/** For those rare notes posted by someone on the machine that
the notesfiles are saved from, this routine will fix the
address to ensure it's valid. The return value will be
either 'machine!' or NULL if it's from the machine we're on
**/
static char machine_group[NLEN];
char buffer[SLEN];
register int i;
dprint0("notes_machine()\n");
if (fseek(mailfile, header_table[current-1].offset, 0L) != 0) {
error("error [notes_machine] trying to seek!");
dprint1("\n\tError %d trying to seek into file!\n\n", errno);
return( NULL );
}
if (fgets(buffer, SLEN, mailfile) == NULL) {
error("error [notes_machine] trying to read!");
dprint1("\n\tError %d trying to read file!\n\n", errno);
return( NULL );
}
sscanf(buffer,"%*s %s", machine_group);
for (i=0; machine_group[i] != ':'; i++)
;
machine_group[i] = '\0';
return( (char *) machine_group);
}
END-OF-FILE
size=`wc -c < src/notesfile.c`
if [ $size != 3955 ]
then
echo Warning: src/notesfile.c changed - should be 3955 bytes, not $size bytes
fi
chmod 644 src/notesfile.c
# ---------- file src/opt_utils.c ----------
if [ -f src/opt_utils.c ]
then
echo File 'src/opt_utils.c' already exists\!
exit 1
fi
echo extracting file src/opt_utils.c...
cat << 'END-OF-FILE' > src/opt_utils.c
/** 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 "headers.h"
#ifdef BSD
# include <pwd.h>
#endif
#ifdef UTS
# include <sys/utsname.h>
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';
}
#endif /* def UTS */
#ifdef BSD
cuserid(username)
char *username;
{
/** Added for compatibility with Bell systems, this is the last-ditch
attempt to get the users login name, after getlogin() fails. It
instantiates "username" to the name of the user...
**/
struct passwd *password_entry, *getpwuid();
password_entry = getpwuid(getuid());
strcpy(username, 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);
}
#endif
END-OF-FILE
size=`wc -c < src/opt_utils.c`
if [ $size != 4053 ]
then
echo Warning: src/opt_utils.c changed - should be 4053 bytes, not $size bytes
fi
chmod 644 src/opt_utils.c
# ---------- file src/output_utils.c ----------
if [ -f src/output_utils.c ]
then
echo File 'src/output_utils.c' already exists\!
exit 1
fi
echo extracting file src/output_utils.c...
cat << 'END-OF-FILE' > src/output_utils.c
/** output_utils.c **/
/** This file contains routines used for output in the MSG 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();
PutLine(LINES,(COLUMNS-strlen(s))/2,s);
if (strlen(s) > 0)
dprint1("\nError: %s\n\n", 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);
}
prompt(s)
char *s;
{
/** prompt user for input on LINES-3 line, left justified **/
PutLine(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
size=`wc -c < src/output_utils.c`
if [ $size != 1861 ]
then
echo Warning: src/output_utils.c changed - should be 1861 bytes, not $size bytes
fi
chmod 644 src/output_utils.c
# ---------- file src/pattern.c ----------
if [ -f src/pattern.c ]
then
echo File 'src/pattern.c' already exists\!
exit 1
fi
echo extracting file src/pattern.c...
cat << 'END-OF-FILE' > src/pattern.c
/** pattern.c **/
/** General pattern matching for the MSG mailer.
(C) Copyright 1986 Dave Taylor
**/
#include <errno.h>
#include "headers.h"
static char pattern[SLEN] = { "" };
static char alt_pattern[SLEN] = { "" };
extern int errno;
int
pattern_match()
{
/** Get a pattern from the user and try to match it with the
from/subject lines being displayed. If matched (ignoring
case), move current message pointer to that message, if
not, error and return ZERO **/
register int i;
PutLine(LINES-3,40,"/ =match anywhere in messages");
PutLine(LINES-1,0, "Match Pattern:");
if (pattern_enter(pattern, alt_pattern, LINES-1, 16,
"Match Pattern (in entire mailbox):"))
if (strlen(alt_pattern) > 0)
return(match_in_message(alt_pattern));
else
return(1);
if (strlen(pattern) == 0)
return(0);
for (i = current; i < message_count; i++) {
if (from_matches(i, pattern)) {
current = ++i;
return(1);
}
else if (subject_matches(i, pattern)) {
current = ++i;
return(1);
}
}
return(0);
}
int
from_matches(message_number, pattern)
int message_number;
char *pattern;
{
/** Returns true iff the pattern occurs in it's entirety
in the from line of the indicated message **/
return( in_string(header_table[message_number].from, pattern) );
}
int
subject_matches(message_number, pattern)
int message_number;
char *pattern;
{
/** Returns true iff the pattern occurs in it's entirety
in the subject line of the indicated message **/
return( in_string(header_table[message_number].subject, pattern) );
}
match_in_message(pattern)
char *pattern;
{
/** Match a string INSIDE a message...starting at the current
message read each line and try to find the pattern. As
soon as we do, set current and leave!
Returns 1 if found, 0 if not
**/
char buffer[LONG_STRING];
int message_number;
long location;
dprint1("match_in_message(pattern='%s')\n", pattern);
location = header_table[current-1].offset;
message_number = current-1;
if (fseek(mailfile, location, 0) != 0) {
dprint2("\tfseek(mailfile, %ld, 0) failed with error %d\n",
location, errno);
error1("msg [match] failed looking %ld bytes into file",
location);
return(1); /* fake it out to avoid replacing error message */
}
error("searching for pattern...");
while (fgets(buffer, LONG_STRING, mailfile) != NULL) {
if (in_string(buffer, pattern)) {
current = message_number;
clear_error();
return(1);
}
location += strlen(buffer);
if (location > header_table[message_number].offset)
message_number++;
}
return(0);
}
END-OF-FILE
size=`wc -c < src/pattern.c`
if [ $size != 2675 ]
then
echo Warning: src/pattern.c changed - should be 2675 bytes, not $size bytes
fi
chmod 644 src/pattern.c
# ---------- file src/quit.c ----------
if [ -f src/quit.c ]
then
echo File 'src/quit.c' already exists\!
exit 1
fi
echo extracting file src/quit.c...
cat << 'END-OF-FILE' > src/quit.c
/** quit.c **/
/** quit: leave the current mailbox and quit the program.
(C) Copyright 1985, Dave Taylor
**/
#ifndef TRUE
#define TRUE 1
#endif
quit()
{
/* a wonderfully short routine!! */
leave_mbox();
leave();
}
resync()
{
/* leave the current mailbox and read it in again. This
is used as needed to allow editing of messages and so
on... */
leave_mbox();
error("reading mailfile in again...");
newmbox(2, TRUE);
showscreen();
}
END-OF-FILE
size=`wc -c < src/quit.c`
if [ $size != 466 ]
then
echo Warning: src/quit.c changed - should be 466 bytes, not $size bytes
fi
chmod 644 src/quit.c
# ---------- file src/read_rc.c ----------
if [ -f src/read_rc.c ]
then
echo File 'src/read_rc.c' already exists\!
exit 1
fi
echo extracting file src/read_rc.c...
cat << 'END-OF-FILE' > src/read_rc.c
/** read_rc.c **/
/** (C) Copyright 1985, Dave Taylor **/
/** This file contains programs to allow the user to have a .msgrc file
in their home directory containing any of the following:
fullname= <username string>
maildir = <directory>
mailbox = <file>
editor = <editor>
savemail= <savefile>
shell = <shell>
print = <print command>
weedout = <list of headers to weed out>
prefix = <copied message prefix string>
alternatives = <list of addresses that forward to us>
and/or the logical arguments:
autocopy [on|off]
copy [on|off]
resolve [on|off]
weed [on|off]
noheader [on|off]
titles [on|off]
editout [on|off]
savebyname [on|off]
movepage [on|off]
Lines starting with '#' are considered comments and are not checked
any further!
Modified 10/85 to know about "Environment" variables..
Modified 12/85 for the 'prefix' option
Modified 2/86 for the "movepage" flag
**/
#include <stdio.h>
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
#include "headers.h"
char *shift_lower(), *strtok(), *getenv();
#define NOTWEEDOUT 0
#define WEEDOUT 1
#define ALTERNATIVES 2
read_rc_file()
{
/** this routine does all the actual work of reading in the
.rc file... **/
FILE *file;
char buffer[SLEN], filename[SLEN];
char word1[SLEN], word2[SLEN];
int errors = 0, last = NOTWEEDOUT;
dprint0("read_rc_file()\n");
sprintf(filename,"%s/%s", home, msgrcfile);
default_weedlist();
alternative_addresses = NULL; /* none yet! */
if ((file = fopen(filename, "r")) == NULL)
return; /* we're done! */
while (fgets(buffer, SLEN, file) != NULL) {
no_ret(buffer); /* remove return */
if (buffer[0] == '#') { /* comment */
last = NOTWEEDOUT;
continue;
}
if (strlen(buffer) < 2) { /* empty line */
last = NOTWEEDOUT;
continue;
}
breakup(buffer, word1, word2);
strcpy(word1, shift_lower(word1)); /* to lower case */
if (word2[0] == 0 && (last != WEEDOUT || last != ALTERNATIVES)) {
fprintf(stderr, "Malformed line from .msgrc file: %s\n", buffer);
errors++;
continue;
}
if (equal(word1,"maildir") || equal(word1,"folders")) {
expand_env(folders, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "fullname") || equal(word1,"username") ||
equal(word1, "name")) {
strcpy(full_username, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "prefix")) {
strcpy(prefixchars, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "shell")) {
expand_env(shell, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "mailbox")) {
expand_env(mailbox, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "editor") || equal(word1,"mailedit")) {
expand_env(editor, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "savemail") || equal(word1, "saveto")) {
expand_env(savefile, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "print") || equal(word1, "printmail")) {
expand_env(printout, word2);
last = NOTWEEDOUT;
}
else if (equal(word1, "autocopy")) {
auto_copy = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "copy") || equal(word1, "auto_cc")) {
auto_cc = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "resolve")) {
resolve_mode = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "weed")) {
filter = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "noheader")) {
noheader = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "titles")) {
title_messages = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "editout")) {
edit_outbound = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "savebyname") || equal(word1, "savename")) {
save_by_name = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "movepage") || equal(word1, "page") ||
equal(word1, "movewhenpaged")) {
move_when_paged = equal(shift_lower(word2), "on");
last = NOTWEEDOUT;
}
else if (equal(word1, "weedout")) {
weedout(word2);
last = WEEDOUT;
}
else if (equal(word1, "alternatives")) {
alternatives(word2);
last = ALTERNATIVES;
}
else if (last == WEEDOUT) /* could be multiple line weedout */
weedout(buffer);
else if (last == ALTERNATIVES) /* multi-line addresses */
alternatives(buffer);
else {
fprintf(stderr, "Unknown line from .rc file: %s\n", buffer);
errors++;
}
}
if (errors) {
fprintf(stderr,"Msg quit from errors in .msgrc file\n");
exit(errors);
}
}
weedout(string)
char *string;
{
/** This routine is called with a list of headers to weed out. **/
register int i;
char *strptr, *header;
dprint1("weedout(string='%s')\n", string);
strptr = (char *) string;
while ((header = strtok(strptr, "\t ,\"'")) != NULL) {
if (weedcount == MAX_IN_WEEDLIST)
exit(fprintf(stderr, "Read in too many weed headers. Max is %d\n",
MAX_IN_WEEDLIST-1));
if (strlen(header) > 0)
if (strlen(header) > NLEN)
fprintf(stderr, "Bad weed header: %s. Too Long - Len is < %d!\n",
header, NLEN);
else {
for (i=0; i < strlen(header); i++)
if (header[i] == '_') header[i] = ' ';
strncpy(weedlist[weedcount++], header, NLEN);
}
strptr = (char *) NULL;
}
}
alternatives(string)
char *string;
{
/** This routine is called with a list of alternative addresses
that you may receive mail from (forwarded) **/
char *strptr, *address;
struct addr_rec *current_record, *previous_record;
dprint1("alternatives(string='%s')\n", string);
previous_record = NULL;
strptr = (char *) string;
while ((address = strtok(strptr, "\t ,\"'")) != NULL) {
if (previous_record == NULL) {
previous_record = (struct addr_rec *)
malloc(sizeof *alternative_addresses);
strcpy(previous_record->address, address);
previous_record->next = NULL;
alternative_addresses = previous_record;
}
else {
current_record = (struct addr_rec *)
malloc(sizeof *alternative_addresses);
strcpy(current_record->address, address);
current_record->next = NULL;
previous_record->next = current_record;
previous_record = current_record;
}
strptr = (char *) NULL;
}
}
default_weedlist()
{
/** install the default headers to weed out! **/
dprint0("default_weedlist()\n");
weedcount = 0;
strncpy(weedlist[weedcount++], ">From", NLEN);
strncpy(weedlist[weedcount++], "In-Reply-To", NLEN);
strncpy(weedlist[weedcount++], "References", NLEN);
strncpy(weedlist[weedcount++], "Newsgroups", NLEN);
strncpy(weedlist[weedcount++], "Received", NLEN);
strncpy(weedlist[weedcount++], "Apparently-To:", NLEN);
strncpy(weedlist[weedcount++], "Message-Id:", NLEN);
}
int
matches_weedlist(buffer)
char *buffer;
{
/** returns true iff the first 'n' characters of 'buffer'
match an entry of the weedlist **/
register int i;
dprint1("matches_weedlist(buffer='%s')\n", buffer);
for (i=0;i < weedcount; i++)
if (strncmp(buffer, weedlist[i], strlen(weedlist[i])) == 0)
return(1);
return(0);
}
breakup(buffer, word1, word2)
char *buffer, *word1, *word2;
{
/** This routine breaks buffer down into word1, word2 where
word1 is alpha characters only, and there is an equal
sign delimiting the two...
alpha = beta
For lines with more than one 'rhs', word2 is set to the
entire string...
**/
register int i;
for (i=0;i<strlen(buffer) && isalpha(buffer[i]); i++)
word1[i] = buffer[i];
word1[i++] = '\0'; /* that's the first word! */
/** spaces before equal sign? **/
while (buffer[i] == ' ' || buffer[i] == '\t') i++;
if (buffer[i] == '=') i++;
/** spaces after equal sign? **/
while (buffer[i] == ' ' || buffer[i] == '\t') i++;
if (i < strlen(buffer))
strcpy(word2, (char *) (buffer + i));
else
word2[0] = '\0';
}
expand_env(dest, buffer)
char *dest, *buffer;
{
/** expand possible metacharacters in buffer and then copy
to dest...
This routine knows about "~" being the home directory,
and "$xxx" being an environment variable.
**/
char *word, *string, next_word[SLEN];
if (buffer[0] == '/') {
dest[0] = '/';
dest[1] = '\0';
}
else
dest[0] = '\0';
string = (char *) buffer;
while ((word = strtok(string, "/")) != NULL) {
if (word[0] == '$') {
strcpy(next_word, getenv((char *) (word + 1)));
if (strlen(next_word) == 0)
leave(printf("\n\rCan't expand environment variable '%s'\n\r",
word));
}
else if (word[0] == '~' && word[1] == '\0')
strcpy(next_word, home);
else
strcpy(next_word, word);
sprintf(dest, "%s%s%s", dest, (strlen(dest) > 0? "/":""),
next_word);
string = (char *) NULL;
}
}
END-OF-FILE
size=`wc -c < src/read_rc.c`
if [ $size != 9083 ]
then
echo Warning: src/read_rc.c changed - should be 9083 bytes, not $size bytes
fi
chmod 644 src/read_rc.c
# ---------- file src/reply.c ----------
if [ -f src/reply.c ]
then
echo File 'src/reply.c' already exists\!
exit 1
fi
echo extracting file src/reply.c...
cat << 'END-OF-FILE' > src/reply.c
/** reply.c **/
/*** routine allows replying to the sender of the current message
(C) Copyright 1985, Dave Taylor
***/
#include "headers.h"
#ifndef BSD
# include <sys/utsname.h>
#endif
/** Note that this routine generates automatic header information
for the subject and (obviously) to lines, but that these can
be altered while in the editor composing the reply message!
**/
char *strip_parens(), *get_token(), *notes_machine();
int
reply()
{
/** Reply to the current message. Returns non-zero iff
the screen has to be rewritten. **/
char return_address[LONG_SLEN], subject[SLEN];
int return_value;
dprint0("reply()\n");
get_return(return_address);
if (header_table[current-1].subject[0] != '\0') {
if ((strncmp("Re:", header_table[current-1].subject, 3) == 0) ||
(strncmp("RE:", header_table[current-1].subject, 3) == 0) ||
(strncmp("re:", header_table[current-1].subject, 3) == 0))
strcpy(subject, header_table[current-1].subject);
else {
strcpy(subject,"Re: ");
strcat(subject,header_table[current-1].subject);
}
return_value = send(return_address, subject, TRUE);
}
else
return_value = send(return_address, "Re: your mail", TRUE);
return(return_value);
}
int
reply_to_everyone()
{
/** Reply to everyone who received the current message.
This includes other people in the 'To:' line and people
in the 'Cc:' line too. Returns non-zero iff the screen
has to be rewritten. **/
char return_address[LONG_SLEN], subject[SLEN];
char full_address[VERY_LONG_STRING];
int return_value;
dprint0("reply_to_everyone()\n");
get_return(return_address);
strcpy(full_address, return_address); /* sender gets copy */
get_and_expand_everyone(return_address, full_address);
if (header_table[current-1].subject[0] != '\0') {
if ((strncmp("Re:", header_table[current-1].subject, 3) == 0) ||
(strncmp("RE:", header_table[current-1].subject, 3) == 0) ||
(strncmp("re:", header_table[current-1].subject, 3) == 0))
strcpy(subject, header_table[current-1].subject);
else {
strcpy(subject,"Re: ");
strcat(subject,header_table[current-1].subject);
}
return_value = send(full_address, subject, TRUE);
}
else
return_value = send(full_address, "Re: your mail", TRUE);
return(return_value);
}
int
forward()
{
/** Forward the current message. What this actually does is
to set auto_copy to true, then call 'send' to get the
address and route the mail.
**/
char subject[SLEN], address[VERY_LONG_STRING];
int original_cc, results, edit_msg;
dprint0("forward()\n");
original_cc = auto_copy;
address[0] = '\0';
edit_msg = (want_to("Edit outgoing message (y/n) ? ",'y',FALSE) != 'n');
printf("%s", edit_msg? "Yes" : "No");
auto_cc = TRUE; /* we want a copy */
if (strlen(header_table[current-1].subject) > 0) {
strcpy(subject,header_table[current-1].subject);
results = send(address, subject, edit_msg);
}
else
results = send(address, "Forwarded Mail...", edit_msg);
auto_copy = original_cc;
return(results);
}
get_and_expand_everyone(return_address, full_address)
char *return_address, *full_address;
{
/** Read the current message, extracting addresses from the 'To:'
and 'Cc:' lines. As each address is taken, ensure that it
isn't to the author of the message NOR to us. If neither,
prepend with current return address and append to the
'full_address' string.
**/
char ret_address[LONG_SLEN], buf[LONG_SLEN], new_address[LONG_SLEN];
char *bufptr, *address;
int in_message = 1, first_pass = 0;
dprint1("get_and_expand_everyone(return_address='%s', <buffer>)\n",
return_address);
/** First off, get to the first line of the message desired **/
if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
error1("msg [seek] couldn't read %d bytes into file",
header_table[current-1].offset);
return;
}
/** okay! Now we're there! **/
/** let's fix the ret_address to reflect the return address of this
message with '%s' instead of the persons login name... **/
translate_return(return_address, ret_address);
/** now let's parse the actual message! **/
while (in_message) {
in_message = (int) (fgets(buf, LONG_SLEN, mailfile) != NULL);
if (first_word(buf, "From ") && first_pass++ != 0)
in_message = FALSE;
else if (first_word(buf, "To:") || first_word(buf, "Cc:") ||
first_word(buf, "CC:") || first_word(buf, "cc:")) {
do {
no_ret(buf);
bufptr = (char *) (strip_parens(buf) + 3); /* 3 = strlen of prompt */
while ((address = get_token(bufptr, "\t, ", 0)) != NULL) {
if (okay_address(address, return_address)) {
sprintf(new_address, ret_address, address);
optimize_and_add(new_address, full_address);
}
bufptr = NULL;
}
in_message = (int) (fgets(buf, LONG_SLEN, mailfile) != NULL);
} while (in_message && whitespace(buf[0]));
}
else if (strlen(buf) < 2) /* done with header */
in_message = FALSE;
}
}
int
okay_address(address, return_address)
char *address, *return_address;
{
/** This routine checks to ensure that the address we just got
from the "To:" or "Cc:" line isn't us AND isn't the person
who sent the message. Returns true iff neither is the case **/
char our_address[SLEN];
struct addr_rec *alternatives;
if (in_string(address, return_address))
return(FALSE);
sprintf(our_address, "%s!%s", hostname, username);
if (in_string(address, our_address))
return(FALSE);
sprintf(our_address, "%s@%s", username, hostname);
if (in_string(address, our_address))
return(FALSE);
alternatives = alternative_addresses;
while (alternatives != NULL) {
if (in_string(address, alternatives->address))
return(FALSE);
alternatives = alternatives->next;
}
return(TRUE);
}
optimize_and_add(new_address, full_address)
char *new_address, *full_address;
{
/** This routine will add the new address to the list of addresses
in the full address buffer IFF it doesn't already occur. It
will also try to fix dumb hops if possible, specifically hops
of the form ...a!b...!a... and hops of the form a at b@b etc
**/
register int len, host_count = 0, i;
char hosts[MAX_HOPS][SLEN]; /* array of machine names */
char *host, *addrptr;
if (in_string(full_address, new_address))
return(1); /* duplicate address */
/** optimize **/
/* break down into a list of machine names, checking as we go along */
addrptr = (char *) new_address;
while ((host = get_token(addrptr, "!", 1)) != NULL) {
for (i = 0; i < host_count && ! equal(hosts[i], host); i++)
;
if (i == host_count) {
strcpy(hosts[host_count++], host);
if (host_count == MAX_HOPS) {
error("Can't build return address - hit MAX_HOPS limit!");
return(1);
}
}
else
host_count = i + 1;
addrptr = NULL;
}
/** fix the ARPA addresses, if needed **/
if (chloc(hosts[host_count-1], '@') > -1)
fix_arpa_address(hosts[host_count-1]);
/** rebuild the address.. **/
new_address[0] = '\0';
for (i = 0; i < host_count; i++)
sprintf(new_address, "%s%s%s", new_address,
new_address[0] == '\0'? "" : "!",
hosts[i]);
dprint1("\tgenerated address '%s'\n", new_address);
if (full_address[0] == '\0')
strcpy(full_address, new_address);
else {
len = strlen(full_address);
full_address[len ] = ',';
full_address[len+1] = ' ';
full_address[len+2] = '\0';
strcat(full_address, new_address);
}
return(0);
}
get_return_name(address, name)
char *address, *name;
{
/** Given the address (either a single address or a combined list
of addresses) extract the login name of the first person on
the list and return it as 'name'. Modified to stop at
any non-alphanumeric character. **/
/** An important note to remember is that it isn't vital that this
always returns just the login name, but rather that it always
returns the SAME name. If the persons' login happens to be,
for example, joe.richards, then it's arguable if the name
should be joe, or the full login. It's really immaterial, as
indicated before, so long as we ALWAYS return the same name! **/
/** Another note: modified to return the argument as all lowercase
always... **/
char single_address[LONG_SLEN];
register int i, loc, index = 0;
/* first step - copy address up to a comma, space, or EOLN */
for (i=0; address[i] != ',' && ! whitespace(address[i]) &&
address[i] != '\0'; i++)
single_address[i] = address[i];
single_address[i] = '\0';
/* Now is it an ARPA address?? */
if ((loc = chloc(single_address, '@')) != -1) { /* Yes */
/* At this point the algorithm is to keep shifting our copy
window left until we hit a '!'. The login name is then
located between the '!' and the first metacharacter to
it's right (ie '%', ':' or '@'). */
for (i=loc; single_address[i] != '!' && i > -1; i--)
if (single_address[i] == '%' ||
single_address[i] == ':' ||
single_address[i] == '.' || /* no domains */
single_address[i] == '@') loc = i-1;
if (single_address[i] == '!') i++;
for (index = 0; index < loc - i + 1; index++)
name[index] = tolower(single_address[index+i]);
name[index] = '\0';
}
else { /* easier - standard USENET address */
/* This really is easier - we just cruise left from the end of
the string until we hit either a '!' or the beginning of the
line. No sweat. */
loc = strlen(single_address)-1; /* last char */
for (i = loc; single_address[i] != '!' && single_address[i] != '.'
&& i > -1; i--)
name[index++] = tolower(single_address[i]);
name[index] = '\0';
reverse(name);
}
}
END-OF-FILE
size=`wc -c < src/reply.c`
if [ $size != 9927 ]
then
echo Warning: src/reply.c changed - should be 9927 bytes, not $size bytes
fi
chmod 644 src/reply.c
# ---------- file src/return_addr.c ----------
if [ -f src/return_addr.c ]
then
echo File 'src/return_addr.c' already exists\!
exit 1
fi
echo extracting file src/return_addr.c...
cat << 'END-OF-FILE' > src/return_addr.c
/** return_addr.c **/
/** This set of routines is used to generate real return addresses
and also return addresses suitable for inclusion in a users
alias files (ie optimized based on the pathalias database).
These routines (C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
char *shift_lower(), *notes_machine(), *expand_address();
optimize_return(address)
char *address;
{
/** This routine tries to create an optimized address, that is,
an address that has the minimal information needed to
route a message to this person given the current path
database...
**/
/** first step is to figure out what sort of address we
have... **/
dprint1("\noptimize_return(address='%s')\n", address);
if (chloc(address, '%') != -1)
optimize_cmplx_arpa(address);
else if (chloc(address, '@') != -1)
optimize_arpa(address);
else
optimize_usenet(address);
}
optimize_cmplx_arpa(address)
char *address;
{
/** Try to optimize a complex ARPA address. A Complex address is one
that contains '%' (deferred '@'). For example:
veeger!hpcnof!hplabs!joe%sytech at syte
is a complex address (no kidding, right?). The algorithm for
trying to resolve it is to move all the way to the right, then
back up left until the first '!' then from there to the SECOND
metacharacter on the right is the name at host address...(in this
example, it would be "joe%sytech"). Check this in the routing
table. If not present, keep backing out to the right until we
find a host that is present, or we hit the '@' sign. Once we
have a 'normal' ARPA address, hand it to optimize_arpa().
**/
char name[SHORT_SLEN], buffer[SLEN], junk[SLEN];
char host[SHORT_SLEN], old_host[SHORT_SLEN];
register int i, loc, nloc = 0, hloc = 0, passes = 1;
dprint1("optimize_cmplx_arpa(address='%s')\n", address);
/** first off, get the name%host... **/
for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
;
while (address[loc] != '\0') {
if (passes == 1) {
loc++;
while (address[loc] != '%' && address[loc] != '@')
name[nloc++] = address[loc++];
}
else {
for (i=0; old_host[i] != '\0'; i++)
name[nloc++] = old_host[i];
}
loc++;
while (address[loc] != '%' && address[loc] != '@')
host[hloc++] = address[loc++];
host[hloc] = name[nloc] = '\0';
dprint2("\tgot name = %s and host = %s\n", name, host);
strcpy(old_host, host);
remove_domains(host);
sprintf(buffer, "%s@%s", name, shift_lower(host));
if (expand_site(buffer, junk) == 0) {
strcpy(address, buffer);
return;
}
else if (address[loc] == '@') {
optimize_arpa(address);
return;
}
else
name[nloc++] = '%'; /* for next pass through */
}
}
optimize_arpa(address)
char *address;
{
/** Get an arpa address and simplify it to the minimal
route needed to get mail to this person... **/
char name[SHORT_SLEN], buffer[SLEN], junk[SLEN];
char host[SHORT_SLEN];
register int loc, nloc = 0, hloc = 0, at_sign = 0;
dprint1("optimize_arpa(address='%s')\n", address);
for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) {
if (address[loc] == '@')
at_sign++; /* remember this spot! */
else if (at_sign)
name[nloc++] = address[loc];
else
host[hloc++] = address[loc];
}
name[nloc] = host[hloc] = '\0';
reverse(name);
reverse(host);
remove_domains(host);
dprint2("\tname = %s and host = %s\n", name, shift_lower(host));
sprintf(buffer,"%s@%s", name, shift_lower(host));
if (expand_site(buffer, junk) == 0) {
strcpy(address, buffer);
return;
}
optimize_usenet(address); /* that didn't work... */
}
optimize_usenet(address)
char *address;
{
/** optimize the return address IFF it's a standard usenet
address...
**/
char name[SHORT_SLEN], new_address[SLEN], buffer[SLEN], junk[SLEN];
register int loc, nloc = 0, aloc = 0, passes = 1;
dprint1("\noptimize_usenet(address='%s')\n", address);
for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
name[nloc++] = address[loc];
name[nloc] = '\0';
reverse(name);
dprint1("\tgot name = %s\n", name);
new_address[0] = '\0';
/* got name, now get machine until we can get outta here */
while (loc > -1) {
new_address[aloc++] = address[loc--]; /* the '!' char */
while (address[loc] != '!' && loc > -1)
new_address[aloc++] = address[loc--];
new_address[aloc] = '\0';
strcpy(buffer, new_address);
reverse(buffer);
if (expand_site(buffer, junk) == 0) {
if (passes == 1 && chloc(name, '@') == -1) {
buffer[strlen(buffer) - 1] = '\0'; /* remove '!' */
dprint2("\tReturning address %s@%s\n", name, buffer);
sprintf(address, "%s@%s", name, buffer);
}
else {
dprint2("\tReturning address '%s%s'\n", buffer, name);
sprintf(address, "%s%s", buffer, name);
}
return; /* success! */
}
else
dprint1("\taddress %s failed!\n", buffer);
passes++;
}
dprint0("\tnothing to do!\n");
return; /* nothing to do! */
}
get_return(buffer)
char *buffer;
{
/** reads 'current' message again, building up the full return
address including all machines that might have forwarded
the message. **/
char buf[LONG_SLEN], name1[SLEN], name2[SLEN], lastname[SLEN];
char hold_return[LONG_SLEN], alt_name2[SLEN];
int ok = 1, lines;
dprint0("get_return(<buffer>)\n");
/** are we reading a notesfile file?? **/
if (notesfile) {
strcpy(buf, header_table[current-1].from);
if (chloc(buf, '!') == -1)
sprintf(buf, "%s!%s", notes_machine(), header_table[current-1].from);
strcpy(buffer, expand_system(buf, 1));
dprint1("\treturn address [notes] = %s\n", buffer);
return;
}
/** get to the first line of the message desired **/
if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
error1("msg [seek] couldn't read %d bytes into file",
header_table[current-1].offset);
return;
}
/** okay! Now we're there! **/
lines = header_table[current-1].lines;
buffer[0] = '\0';
while (ok && lines--) {
ok = (int) (fgets(buf, LONG_SLEN, mailfile) != NULL);
if (first_word(buf, "From ")) {
sscanf(buf, "%*s %s", hold_return);
}
else if (first_word(buf, ">From")) {
sscanf(buf,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s %s",
name1, name2, alt_name2);
if (strcmp(name2, "from") == 0)
strcpy(name2, alt_name2);
add_site(buffer, name2, lastname);
}
#ifdef USE_EMBEDDED_ADDRESSES
else if (first_word(buf, "From:")) {
get_address_from("From:", buf, hold_return);
}
else if (first_word(buf, "Reply-To:")) {
get_address_from("Reply-To:", buf, buffer);
return;
}
#endif
else if (strlen(buf) < 2) /* done with header */
lines = 0; /* let's get outta here! We're done!!! */
}
if (buffer[0] == '\0')
strcpy(buffer, hold_return); /* default address! */
else
add_site(buffer, name1, lastname); /* get the user name too! */
dprint1("\treturn address = '%s'\n", buffer);
}
END-OF-FILE
size=`wc -c < src/return_addr.c`
if [ $size != 7247 ]
then
echo Warning: src/return_addr.c changed - should be 7247 bytes, not $size bytes
fi
chmod 644 src/return_addr.c
# ---------- file src/savecopy.c ----------
if [ -f src/savecopy.c ]
then
echo File 'src/savecopy.c' already exists\!
exit 1
fi
echo extracting file src/savecopy.c...
cat << 'END-OF-FILE' > src/savecopy.c
/** 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
char *format_long(), *get_arpa_date();
extern char reply_to[SLEN]; /* In-Reply-To: string */
extern int gotten_key; /* for encryption */
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? */
dprint5(
"save_copy(subject='%s', to='%s', cc='%s', filename='%s', original-to='%s')\n",
subject, to, cc, filename, original_to);
savename[0] = '\0';
if (save_by_name) {
get_return_name(to, buffer);
sprintf(savename, "%s%s%s", folders,
lastch(folders) == '/'? "" : "/", buffer);
if (access(savename, ACCESS_EXISTS) == -1) /* don't create new! */
savename[0] = '\0';
}
if (strlen(savename) == 0) {
if (strlen(savefile) == 0)
return(error("variable 'SAVEFILE' not defined!"));
strcpy(savename, savefile);
if (save_by_name)
error2("Not creating file '%s'...saving in %s instead",
buffer, savename);
}
dprint1("\tsaving copy of outbound message to file '%s'\n", savename);
if ((save = fopen(savename, "a")) == NULL)
return(error1("couldn't append to %s", savename));
if ((message = fopen(filename, "r")) == NULL) {
fclose(save);
return(error1("save_copy couldn't read file %s!", filename));
}
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 = time(0); /* this must be here for it to work! */
fprintf(save,"\nFrom To:%s %s", buffer, (char *) 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(reply_to) > 0)
fprintf(save, "In-Reply-To: %s\n", 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, getgid());
return(TRUE);
}
}
else if (crypted) {
if (! gotten_key++)
getkey(ON);
encode(buffer);
}
fputs(buffer, save);
}
dprint0("\tclosing the files...\n");
fclose(message);
fclose(save);
/* make sure save file isn't owned by root! */
chown(savename, userid, getgid());
return(TRUE);
}
END-OF-FILE
size=`wc -c < src/savecopy.c`
if [ $size != 3441 ]
then
echo Warning: src/savecopy.c changed - should be 3441 bytes, not $size bytes
fi
chmod 644 src/savecopy.c
# ---------- file src/screen.c ----------
if [ -f src/screen.c ]
then
echo File 'src/screen.c' already exists\!
exit 1
fi
echo extracting file src/screen.c...
cat << 'END-OF-FILE' > src/screen.c
/** screen.c **/
/** screen display routines for MSG program
(C) Copyright 1985, Dave Taylor
**/
#include "headers.h"
static int last_current = -1;
showscreen()
{
char buffer[SLEN];
dprint0("showscreen()\n");
ClearScreen();
if (notesfile)
sprintf(buffer, "Notes from '%s' (%d note%s) [Version %s]",
infile, message_count,
plural(message_count), VERSION);
else
sprintf(buffer, "Mailbox is '%s' with %d message%s [Version %s]",
infile, message_count,
plural(message_count), VERSION);
Centerline(1, buffer);
last_header_page = -1; /* force a redraw regardless */
show_headers();
if (mini_menu)
show_menu();
show_last_error();
if (hp_terminal)
define_softkeys(MAIN);
}
show_menu()
{
/** write main system menu... **/
Centerline(LINES-7,
"|=pipe, !=shell, ?=help, <n>=set current to n, /=search pattern");
Centerline(LINES-6,
"A)lias, C)hange mailbox, D)elete, F)orward, G)roup reply, M)ail,");
Centerline(LINES-5,
"N)ext, P)rint, R)eply, S)ave to file, Q)uit, U)ndelete, or eX)it");
}
int
show_headers()
{
/** display page of headers (10) if present. First check to
ensure that header_page is in bounds, fixing silently if not.
If out of bounds, return zero, else return non-zero **/
register int first = 0, line = 4, last = 0, last_line;
char newfrom[SLEN], buffer[SLEN];
dprint0("show_headers()\n");
if (fix_header_page())
return(FALSE);
if (header_page == last_header_page) /* nothing to do! */
return(FALSE);
/** compute last header to display **/
first= header_page * headers_per_page;
last = first + (headers_per_page - 1);
if (last >= message_count) last = message_count-1;
dprint2("\tdisplaying headers %d thru %d\n", first, last);
/** okay, now let's show the header page! **/
while (first <= last) {
tail_of(header_table[first].from, newfrom, TRUE);
build_header_line(buffer, &header_table[first], first+1, newfrom);
PutLine(line,COLUMNS-80,"%s", buffer); /* avoid '%' probs */
CleartoEOLN();
first++;
line++; /* for clearing up in a sec... */
}
/* clear up the rest of the screen! */
if (mini_menu)
last_line = LINES-8;
else
last_line = LINES-3;
while (line < last_line) {
MoveCursor(line,0);
CleartoEOLN();
line++;
}
display_central_message();
last_current = current;
last_header_page = header_page;
return(TRUE);
}
show_current()
{
/** display page of headers (10) if present. First check to
ensure that header_page is in bounds, fixing silently if not.
Note that this will ensure that 'current' is always set to
the top message on the screen if we go to a new screen! **/
register int first = 0, last = 0, line = 4, changed;
dprint0("show_current()\n");
changed = fix_header_page();
/** compute last header to display **/
first = header_page * headers_per_page;
last = first + (headers_per_page - 1);
if (last > message_count)
last = message_count;
/** okay, now let's show the pointers... **/
/** have we changed??? **/
if (current == last_current) {
dprint0("\tno change. at same message!\n");
return;
}
/** first condition - current on this page & last too */
if (last_current >= first && last_current <= last+1) {
dprint2("\tMoving arrow from %d to (current) %d\n",
last_current, current);
PutLine(((last_current-1) % headers_per_page) + 4, COLUMNS-76," ");
PutLine(((current-1) % headers_per_page) + 4, COLUMNS-76,"<-");
}
/** second condition - current on this page **/
else if (! changed) {
dprint1("\tMoving arrow to (current) %d\n", current);
PutLine(((current-1) % headers_per_page) + 4, COLUMNS-76,"<-");
}
/** third condition - page changed! **/
else {
dprint2("\tdisplaying from message %d to %d\n", first, last);
while (first <= last) {
if (current-1 == first) PutLine(line++,COLUMNS-76,"<-");
else PutLine(line++,COLUMNS-76," ");
first++;
}
}
last_current = current;
}
build_header_line(buffer, entry, number, from)
char *buffer;
struct header_rec *entry;
int number;
char *from;
{
/** Build in buffer the message header ... entry is the current
message entry, number is the numerical ID of the message,
and 'from' is a modified (displayable) from line... **/
/** Note: using 'strncpy' allows us to output as much of the
subject line as possible given the dimensions of the screen.
The key is that 'strncpy' returns a 'char *' to the string
that it is handing to the dummy variable! Neat, eh? **/
char subj[LONG_SLEN]; /* to output subject */
strncpy(subj, entry->subject, COLUMNS-34);
subj[COLUMNS-34] = '\0'; /* insurance, eh? */
sprintf(buffer, "%c%3d%s %c %3.3s %-2d %-18.18s %s",
(entry->priority? 'U' : new_msg(entry)? 'N' : ' '),
number, (number == current? "<-" : " "),
(entry->delete? '*' : ' '),
entry->month, atoi(entry->day), from, subj);
}
int
fix_header_page()
{
/** this routine will check and ensure that the current header
page being displayed contains messages! It will silently
fix 'header-page' if wrong. Returns TRUE if changed. **/
int last_page, old_header;
dprint1("fix_header_page() [%d messages total]\n", message_count);
old_header = header_page;
last_page = (int) ((message_count-1) / headers_per_page);
dprint2("\tThere are 0 to %d pages in file [%d per page]\n",
last_page, headers_per_page);
if (header_page > last_page)
header_page = last_page;
else if (header_page < 0)
header_page = 0;
return(old_header != header_page);
}
END-OF-FILE
size=`wc -c < src/screen.c`
if [ $size != 5636 ]
then
echo Warning: src/screen.c changed - should be 5636 bytes, not $size bytes
fi
chmod 644 src/screen.c
# ---------- file src/showmsg.c ----------
if [ -f src/showmsg.c ]
then
echo File 'src/showmsg.c' already exists\!
exit 1
fi
echo extracting file src/showmsg.c...
cat << 'END-OF-FILE' > src/showmsg.c
/** showmsg.c **/
/** This file contains all the routines needed to display the specified
message.
These routines (C) Copyright 1986 Dave Taylor
**/
#include "headers.h"
#include <ctype.h>
#ifdef BSD
#undef tolower
#endif
int
show_msg(number)
int number;
{
/*** display number'th message. Get starting and ending lines
of message from headers data structure, then fly through
the file, displaying only those lines that are between the
two!
Returns non-zero if message shown!
***/
dprint1("show_msg(number=%d)\n", number);
if (number > message_count) {
error1("Only %d messages!", message_count);
return(0);
}
else if (number < 1) {
error("you can't read THAT message!");
return(0);
}
return(show_message(header_table[number-1].lines,
header_table[number-1].offset,number));
}
int
show_message(lines, file_loc, msgnumber)
int lines, msgnumber;
long file_loc;
{
/*** Show the indicated range of lines from mailfile
for message 'msgnumber' by using 'display'
Returns non-zero if it actually put something on
the screen.
***/
dprint3("show_message(lines=%d, loc=%ld, msg-number=%d)\n",
lines, file_loc, msgnumber);
if (fseek(mailfile, file_loc, 0) != 0) {
error1("msg [seek] failed looking %d bytes into file",
file_loc);
return(FALSE);
}
/* next read will get 'this' line so must be at end of previous */
Raw(OFF);
display(lines, msgnumber);
Raw(ON);
return(TRUE); /* we did it boss! */
}
/** these two variables are used iff the variable 'title_message' is
set, and are buffers for output of message title... **/
static char top_of_screen_left [LONG_STRING],
top_of_screen_right[LONG_STRING];
display(lines, msgnum)
int lines, msgnum;
{
/** Display specified number of lines from file mailfile.
Note: This routine MUST be placed at the first line
of the input file! **/
char buffer[LONG_STRING], *full_month();
int lines_on_screen = 0; /* display */
int crypted = 0, gotten_key = 0; /* encryption */
int weed_header, weeding_out = 0; /* weeding */
dprint2("display(lines=%d, msgnum=%d)\n", lines, msgnum);
if (title_messages) {
tail_of(header_table[msgnum-1].from, buffer, FALSE);
sprintf(top_of_screen_left, "%s #%d %s %s",
notesfile? "Note" : "Message", msgnum,
(strncmp(header_table[msgnum-1].from, "To:", 3) == 0?
"to": "from"), buffer);
sprintf(top_of_screen_right," %s %s %s, %d at %s",
notesfile? "Posted" : "Mailed",
full_month(header_table[msgnum-1].month),
header_table[msgnum-1].day,
atoi(header_table[msgnum-1].year) + 1900,
header_table[msgnum-1].time);
dprint1("\ttos_left: '%s'\n", top_of_screen_left);
dprint1("\ttos_right: '%s'\n", top_of_screen_right);
}
weed_header = filter; /* allow us to change it after header */
ClearScreen();
if (cursor_control) transmit_functions(OFF);
while (lines > 0) {
if (fgets(buffer, LONG_STRING, mailfile) == NULL) {
PutLine(LINES-1, 0, "Please press <space> to return: ");
(void) ReadCh();
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
if (strlen(buffer) > 0)
no_ret(buffer);
if (strlen(buffer) == 0) {
weed_header = 0; /* past header! */
weeding_out = 0;
}
lines--;
if (notesfile) { /* treat notes differently! */
if (filter && (first_word(buffer, NOTES_HEADER) ||
first_word(buffer, NOTES_FOOTER)) )
/*** weed this line out of the display! ***/;
else if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
else { /* "normal" message */
if (weed_header && matches_weedlist(buffer))
weeding_out = 1; /* aha! We don't want to see this! */
else if (buffer[0] == '[') {
if (strcmp(buffer, START_ENCODE)==0)
crypted++;
else if (strcmp(buffer, END_ENCODE)==0)
crypted--;
else if (crypted) {
encode(buffer);
if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
else
if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
else if (crypted) {
if (! gotten_key++) getkey(OFF);
encode(buffer);
if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
else if (weeding_out) {
weeding_out = (whitespace(buffer[0])); /* 'n' line weed */
if (! weeding_out) /* just turned on! */
if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
else
if (show_line(buffer, &lines_on_screen, &lines)) {
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
}
}
PutLine(LINES-1, 0, "Please press <space> to return: ");
Raw(ON);
(void) ReadCh();
if (cursor_control) transmit_functions(ON);
return(TRUE);
}
int
show_line(buffer, lines_on_screen, total)
char *buffer;
int *lines_on_screen, *total;
{
/** Displays the given line if it can. if not, it will put the
'ole 'space to continue' prompt on the bottom of the screen
and wait for either a 'space' or 'return'. If 'return' is
hit (or 'q'), then it will return non-zero, otherwise it'll
return zero.
**/
static char overlap [LONG_SLEN];
char mybuffer[SLEN], ch;
int last_line_loc;
dprint3("show_line(buffer=%s, on-screen=%d, total=%d)\n",
buffer, *lines_on_screen, *total);
last_line_loc = *lines_on_screen; /* one back... */
*lines_on_screen += ((strlen(buffer) / COLUMNS) + 1);
if (last_line_loc == 0 && title_messages) {
display_title(*total);
last_line_loc = 2;
*lines_on_screen += 2;
}
if (*lines_on_screen > LINES-2) {
if (*total > 0) {
sprintf(mybuffer, "%d line%s left", *total, plural(*total));
PutLine(LINES-1, COLUMNS-20, "%s", mybuffer);
PutLine(LINES-1, 0, "Press <space> to continue: ");
}
else
PutLine(LINES-1, 0, "Please press <space> to return: ");
Raw(ON);
ch = ReadCh();
if (ch == '\n' || ch == '\r' || tolower(ch) == 'q')
return(TRUE);
if (ch == ' ' && *total == 0) /* don't want '0' lines left */
return(TRUE);
Raw(OFF);
ClearScreen();
*lines_on_screen = 0;
if (title_messages) {
display_title(*total);
*lines_on_screen = 2;
}
PutLine(*lines_on_screen, 0, "%s", overlap);
*lines_on_screen += ((strlen(overlap) / COLUMNS) + 1);
last_line_loc = *lines_on_screen;
*lines_on_screen += ((strlen(buffer) / COLUMNS) + 1);
}
PutLine(last_line_loc, 0, "%s", buffer);
if (*lines_on_screen > LINES-6) /* in case next is too LONG */
strcpy(overlap, buffer);
return(FALSE);
}
display_title(lines_into_message)
int lines_into_message;
{
/** Display top title, including "Page N" **/
register int page;
dprint1("displaytitle(lines-into-message=%d)\n", lines_into_message);
page = (int) (lines_into_message) / (LINES - 4);
PutLine(0,0,top_of_screen_left);
PutLine(0, COLUMNS-strlen(top_of_screen_right),
top_of_screen_right, page);
}
END-OF-FILE
size=`wc -c < src/showmsg.c`
if [ $size != 7604 ]
then
echo Warning: src/showmsg.c changed - should be 7604 bytes, not $size bytes
fi
chmod 644 src/showmsg.c
# ---------- file src/softkeys.c ----------
if [ -f src/softkeys.c ]
then
echo File 'src/softkeys.c' already exists\!
exit 1
fi
echo extracting file src/softkeys.c...
cat << 'END-OF-FILE' > src/softkeys.c
/** softkeys.c **/
/** This file and associated routines: (C) Copyright 1986, Dave Taylor **/
#include <stdio.h>
#include "headers.h"
define_softkeys(level)
int level;
{
dprint0("define_softkeys(level=");
if (! hp_softkeys) {
dprint0("0) [error: no softkeys!]\n");
return;
}
if (level == MAIN) {
dprint0("MAIN)\n");
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 Msg", "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 Msg", "q");
}
}
else if (level == ALIAS) {
dprint0("ALIAS)\n");
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 Msg", "r");
}
else if (level == YESNO) {
dprint0("YES-NO)\n");
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) {
dprint0("READ)\n");
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 Msg", "\n");
}
else if (level == CHANGE) {
dprint0("CHANGE)\n");
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];
dprint3("define-key(key=%d, display='%s', send='%s'\n",
key, display, send);
sprintf(buffer,"%s%s", display, send);
printf("%c&f%dk%dd%dL%s", ESCAPE, key,
strlen(display), strlen(send), buffer);
}
softkeys_on()
{
/* turn on softkeys (esc&jB) and turn on MENU and USER/SYSTEM */
if (hp_softkeys)
printf("%c&jB%c&jR", ESCAPE, ESCAPE);
}
softkeys_off()
{
/* turn off softkeys (esc&j@) */
if (hp_softkeys)
printf("%c&j@", ESCAPE);
}
clear_key(key)
{
/** set a key to nothing... **/
if (hp_softkeys)
define_key(key, " ", "");
}
END-OF-FILE
size=`wc -c < src/softkeys.c`
if [ $size != 2900 ]
then
echo Warning: src/softkeys.c changed - should be 2900 bytes, not $size bytes
fi
chmod 644 src/softkeys.c
echo done
exit 0
More information about the Mod.sources
mailing list