taylor@hpldat.UUCP (Dave Taylor) (04/28/87)
There were a couple of problems with the 'from' command, and there
was an entire algorithm that was rather sub-optimal, so here's a
completely new version of "utils/from.c" to replace the existing one
with.
-- Dave Taylor
ps: expect extensive "patch" format changes to show up starting in a
few days...
--- Shell Archive of "from.c"
# Shell Archive created by hpldat!taylor at Mon Apr 27 18:44:51 1987
# 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;
# utils/from.c
if [ ! -d utils ]
then
echo creating directory utils
mkdir utils
fi
# ---------- file utils/from.c ----------
filename="utils/from.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file utils/from.c...
fi
cat << 'END-OF-FILE' > $filename
/** from.c **/
/** print out whom each message is from in the pending folder or specified
one, including a subject line if available..
Added PREFER_UUCP knowledge 6/86
Added "-n" flag, 9/86
Added "-v" flag, 3/87
(C) Copyright 1986 Dave Taylor
**/
#include <stdio.h>
#include "defs.h"
static char ident[] = { WHAT_STRING };
#define LINEFEED (char) 10
#define metachar(c) (c == '=' || c == '+' || c == '%')
FILE *mailfile;
char *expand_define();
int number = 0, /* should we number the messages?? */
verbose = 0; /* and should we prepend a header? */
main(argc, argv)
int argc;
char *argv[];
{
char infile[LONG_SLEN], username[SLEN], c;
int multiple_files = 0, output_files = 0;
extern int opt_index;
while ((c = get_options(argc, argv, "nv")) > 0)
switch (c) {
case 'n': number++; break;
case 'v': verbose++; break;
}
if (c == -1) {
printf("Usage: %s [-n] {filename | username}\n", argv[0]);
exit(1);
}
if (opt_index == argc) {
strcpy(username, getlogin());
if (strlen(username) == 0)
cuserid(username);
sprintf(infile,"%s%s",mailhome, username);
opt_index -= 1; /* ensure one pass through loop */
}
multiple_files = (argc - opt_index > 1);
while (opt_index < argc) {
if (multiple_files) {
strcpy(infile, argv[opt_index]);
printf("%s%s: \n", output_files++ > 0 ? "\n":"", infile);
}
else if (infile[0] == '\0')
strcpy(infile, argv[opt_index]);
if (metachar(infile[0])) {
if (expand(infile) == 0) {
fprintf(stderr, "%s: couldn't expand filename %s!\n",
argv[0], infile);
exit(1);
}
}
if ((mailfile = fopen(infile,"r")) == NULL) {
if (opt_index+1 == argc)
printf("No mail\n");
else {
if (infile[0] == '/')
printf("Couldn't open folder \"%s\".\n", infile);
else {
sprintf(infile,"%s%s", mailhome, argv[opt_index]);
if ((mailfile = fopen(infile,"r")) == NULL)
printf("Couldn't open folders \"%s\" or \"%s\".\n",
argv[opt_index], infile);
else if (read_headers()==0)
printf("No messages in that folder!\n");
}
}
}
else
if (read_headers(opt_index+1 == argc)==0)
if (opt_index+1 == argc)
printf("No mail\n");
else
printf("No messages in that folder!\n");
opt_index++;
}
}
int
read_headers(user_mailbox)
int user_mailbox;
{
/** Read the headers, output as found. User-Mailbox is to guarantee
that we get a reasonably sensible message from the '-v' option
**/
char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
register int subj = 0, in_header = 1, count = 0;
while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
if (first_word(buffer,"From ")) {
if (real_from(buffer, from_whom)) {
subj = 0;
in_header = 1;
}
}
else if (in_header) {
if (first_word(buffer,">From"))
forwarded(buffer, from_whom); /* return address */
else if (first_word(buffer,"Subject:") ||
first_word(buffer,"Re:")) {
if (! subj++) {
remove_first_word(buffer);
strcpy(subject, buffer);
}
}
else if (first_word(buffer,"From:"))
parse_arpa_from(buffer, from_whom);
else if (buffer[0] == LINEFEED) {
if (verbose && count == 0)
printf("%s contains the following messages:\n\n",
user_mailbox?"Your mailbox" : "Folder");
in_header = 0; /* in body of message! */
show_header(count+1, from_whom, subject);
from_whom[0] = 0;
subject[0] = 0;
count++;
}
}
}
return(count);
}
int
real_from(buffer, who)
char *buffer, *who;
{
/***** returns true iff 's' has the seven 'from' fields,
initializing the who to the sender *****/
char junk[80];
junk[0] = '\0';
sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
who, junk);
return(junk[0] != '\0');
}
forwarded(buffer, who)
char *buffer, *who;
{
/** change 'from' and date fields to reflect the ORIGINATOR of
the message by iteratively parsing the >From fields... **/
char machine[80], buff[80];
machine[0] = '\0';
sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
who, machine);
if (machine[0] == '\0') /* try for srm address */
sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
who, machine);
if (machine[0] == '\0')
sprintf(buff,"anonymous");
else
sprintf(buff,"%s!%s", machine, who);
strncpy(who, buff, 80);
}
remove_first_word(string)
char *string;
{ /** removes first word of string, ie up to first non-white space
following a white space! **/
register int loc;
for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
;
while (string[loc] == ' ' || string[loc] == '\t')
loc++;
move_left(string, loc);
}
move_left(string, chars)
char string[];
int chars;
{
/** moves string chars characters to the left DESTRUCTIVELY **/
register int i;
chars--; /* index starting at zero! */
for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
string[i-chars] = string[i];
string[i-chars] = '\0';
}
show_header(count, from, subject)
int count;
char *from, *subject;
{
/** output header in clean format, including abbreviation
of return address if more than one machine name is
contained within it! **/
char buffer[SLEN];
int loc, i=0, exc=0;
#ifdef PREFER_UUCP
char *p;
if (chloc(from,'!') != -1 && chloc(from,'@') > 0)
for (p=from;*p != '@'; p++) ;
*p = '\0';
#endif
loc = strlen(from);
while (exc < 2 && loc > 0)
if (from[--loc] == '!')
exc++;
if (exc == 2) { /* lots of machine names! Get last one */
loc++;
while (loc < strlen(from) && loc < SLEN)
buffer[i++] = from[loc++];
buffer[i] = '\0';
if (number)
printf("%3d: %-20s %s\n", count, buffer, subject);
else
printf("%-20s %s\n", buffer, subject);
}
else
if (number)
printf("%3d: %-20s %s\n", count, from, subject);
else
printf("%-20s %s\n", from, subject);
}
parse_arpa_from(buffer, newfrom)
char *buffer, *newfrom;
{
/** try to parse the 'From:' line given... It can be in one of
two formats:
From: Dave Taylor <hpcnou!dat>
or From: hpcnou!dat (Dave Taylor)
Change 'newfrom' ONLY if sucessfully parsed this entry and
the resulting name is non-null!
**/
char temp_buffer[SLEN], *temp;
register int i, j = 0;
temp = (char *) temp_buffer;
temp[0] = '\0';
no_ret(buffer); /* blow away '\n' char! */
if (lastch(buffer) == '>') {
for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
buffer[i] != '('; i++)
temp[j++] = buffer[i];
temp[j] = '\0';
}
else if (lastch(buffer) == ')') {
for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
buffer[i] != '<'; i--)
temp[j++] = buffer[i];
temp[j] = '\0';
reverse(temp);
}
if (strlen(temp) > 0) { /* mess with buffer... */
/* remove leading spaces... */
while (whitespace(temp[0]))
temp = (char *) (temp + 1); /* increment address! */
/* remove trailing spaces... */
i = strlen(temp) - 1;
while (whitespace(temp[i]))
temp[i--] = '\0';
/* if anything is left, let's change 'from' value! */
if (strlen(temp) > 0)
strcpy(newfrom, temp);
}
}
reverse(string)
char *string;
{
/** reverse string... pretty trivial routine, actually! **/
char buffer[SLEN];
register int i, j = 0;
for (i = strlen(string)-1; i >= 0; i--)
buffer[j++] = string[i];
buffer[j] = '\0';
strcpy(string, buffer);
}
int
expand(infile)
char *infile;
{
/** Expand the filename since the first character is a meta-
character that should expand to the "maildir" variable
in the users ".elmrc" file...
Note: this is a brute force way of getting the entry out
of the .elmrc file, and isn't recommended for the faint
of heart!
**/
FILE *rcfile;
char buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr;
int foundit = 0;
bufptr = (char *) buffer; /* same address */
if ((home = getenv("HOME")) == NULL) {
printf(
"Can't expand environment variable $HOME to find .elmrc file!\n");
exit(1);
}
sprintf(buffer, "%s/%s", home, elmrcfile);
if ((rcfile = fopen(buffer, "r")) == NULL) {
printf("Can't open your \".elmrc\" file (%s) for reading!\n",
buffer);
exit(1);
}
while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) {
if (strncmp(buffer, "maildir", 7) == 0 ||
strncmp(buffer, "folders", 7) == 0) {
while (*bufptr != '=' && *bufptr)
bufptr++;
bufptr++; /* skip the equals sign */
while (whitespace(*bufptr) && *bufptr)
bufptr++;
home = bufptr; /* remember this address */
while (! whitespace(*bufptr) && *bufptr != '\n')
bufptr++;
*bufptr = '\0'; /* remove trailing space */
foundit++;
}
}
fclose(rcfile); /* be nice... */
if (! foundit) {
printf("Couldn't find \"maildir\" in your .elmrc file!\n");
exit(1);
}
/** Home now points to the string containing your maildir, with
no leading or trailing white space...
**/
expanded_dir = expand_define(home);
sprintf(buffer, "%s%s%s", expanded_dir,
(expanded_dir[strlen(expanded_dir)-1] == '/' ||
infile[0] == '/') ? "" : "/", (char *) infile+1);
strcpy(infile, buffer);
}
char *expand_define(maildir)
char *maildir;
{
/** This routine expands any occurances of "~" or "$var" in
the users definition of their maildir directory out of
their .elmrc file.
Again, another routine not for the weak of heart or staunch
of will!
**/
static char buffer[SLEN]; /* static buffer AIEE!! */
char name[SLEN], /* dynamic buffer!! (?) */
*nameptr, /* pointer to name?? */
*value; /* char pointer for munging */
if (*maildir == '~')
sprintf(buffer, "%s%s", getenv("HOME"), ++maildir);
else if (*maildir == '$') { /* shell variable */
/** break it into a single word - the variable name **/
strcpy(name, (char *) maildir + 1); /* hurl the '$' */
nameptr = (char *) name;
while (*nameptr != '/' && *nameptr) nameptr++;
*nameptr = '\0'; /* null terminate */
/** got word "name" for expansion **/
if ((value = getenv(name)) == NULL) {
printf("Couldn't expand shell variable $%s in .elmrc!\n", name);
exit(1);
}
sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1);
}
else strcpy(buffer, maildir);
return( ( char *) buffer);
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 10520 ]
then
echo $filename changed - should be 10520 bytes, not $size bytes
fi
chmod 666 $filename
fi
echo done
exit 0