home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume9
/
elm2
/
part07
< prev
next >
Wrap
Text File
|
1987-03-08
|
53KB
|
2,052 lines
Subject: v09i007: ELM Mail System, Part07/19
Newsgroups: mod.sources
Approved: rs@mirror.TMC.COM
Submitted by: Dave Taylor <hplabs!taylor>
Mod.sources: Volume 9, Issue 7
Archive-name: elm2/Part07
#! /bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
# "End of archive 7 (of 19)."
# Contents: src/aliasdb.c src/domains.c src/initialize.c
# utils/fastmail.c utils/newmail.c utils/wnewmail.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"src/aliasdb.c\" \(7752 characters\)
if test -f src/aliasdb.c ; then
echo shar: Will not over-write existing file \"src/aliasdb.c\"
else
sed "s/^X//" >src/aliasdb.c <<'END_OF_src/aliasdb.c'
X/** aliasdb.c **/
X
X/** Alias database files...
X
X (C) Copyright 1986 Dave Taylor
X**/
X
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X
Xextern int errno;
X
X#ifdef USE_DBM
X# include <dbm.h>
X#endif
X
X#define absolute(x) ((x) > 0 ? x : -(x))
X
Xchar *shift_lower(), *find_path_to(), *strcat(), *strcpy();
Xunsigned long sleep();
X
Xint findnode_has_been_initialized = FALSE;
X
Xfindnode(name, display_error)
Xchar *name;
Xint display_error;
X{
X /** break 'name' into machine!user or user@machine and then
X see if you can find 'machine' in the path database..
X If so, return name as the expanded address. If not,
X return what was given to us! If display_error, then
X do so...
X **/
X
X#ifndef DONT_TOUCH_ADDRESSES
X
X char old_name[SLEN];
X char address[SLEN];
X
X if (strlen(name) == 0)
X return;
X
X if (! findnode_has_been_initialized) {
X if (! mail_only)
X error("initializing internal tables...");
X#ifndef USE_DBM
X get_connections();
X open_domain_file();
X#endif
X init_findnode();
X clear_error();
X findnode_has_been_initialized = TRUE;
X }
X
X strcpy(old_name, name); /* save what we were given */
X
X if (expand_site(name, address) == -1) {
X if (display_error && name[0] != '!') {
X dprint2(2,"Couldn't expand host %s in address. (%s)\n",
X name, "findnode");
X if (! check_only && warnings) { /* be silent if just checking */
X if (mail_only)
X printf("Warning: couldn't expand %s...\n\r", name);
X else {
X error1("Warning: couldn't expand %s...", name);
X sleep(1);
X }
X }
X }
X strcpy(name, old_name); /* and restore... */
X }
X else
X strcpy(name, address);
X#endif
X return;
X}
X
Xint
Xexpand_site(cryptic, expanded)
Xchar *cryptic, *expanded;
X{
X
X /** Given an address of the form 'xyz@site' or 'site!xyz'
X return an address of the form <expanded address for site>
X with 'xyz' embedded according to the path database entry.
X Note that 'xyz' can be eiher a simple address (as in "joe")
X or a complex address (as in "joe%xerox.parc@Xerox.ARPA")!
X 0 = found, -1 return means unknown site code
X
X Modified to strip out parenthetical comments...
X **/
X
X#ifdef ACSNET
X
X strcpy(expanded, cryptic); /* fast and simple */
X return(0);
X
X#else
X# ifdef USE_DBM
X datum key, contents;
X# endif
X
X char name[VERY_LONG_STRING], sitename[VERY_LONG_STRING],
X temp[VERY_LONG_STRING], old_name[VERY_LONG_STRING],
X comment[LONG_STRING];
X char *expand_domain(), *addr;
X register int i = 0, j = 0, domain_name;
X
X strcpy(old_name, cryptic); /* remember what we were given */
X
X /** break down **/
X
X /** first, rip out the comment, if any **/
X
X if ((i = chloc(cryptic, '(')) > -1) {
X comment[j++] = ' '; /* leading space */
X for ( ;cryptic[i] != ')'; i++)
X comment[j++] = cryptic[i];
X comment[j++] = ')';
X comment[j] = '\0';
X /* and remove this from cryptic string too... */
X if (cryptic[(j = chloc(cryptic,'('))-1] == ' ')
X cryptic[j-1] = '\0';
X else
X cryptic[j] = '\0';
X }
X else
X comment[0] = '\0';
X
X i = j = 0; /* reset */
X
X while (cryptic[i] != AT_SIGN && cryptic[i] != BANG &&
X cryptic[i] != '\0' && cryptic[i] != '(')
X sitename[j++] = cryptic[i++];
X
X sitename[j++] = '\0';
X
X j = 0;
X
X if (cryptic[i] == '\0') return(-1); /* nothing to expand! */
X
X domain_name = (cryptic[i] == AT_SIGN);
X
X i++;
X
X while (cryptic[i] != '\0' && cryptic[i] != '(' &&
X ! whitespace(cryptic[i]))
X name[j++] = cryptic[i++];
X
X name[j] = '\0';
X
X if (domain_name) {
X strcpy(temp, name);
X strcpy(name, sitename);
X strcpy(sitename, temp);
X }
X
X dprint3(5,"\nBroke address into '%s' @ '%s' '%s'\n\n",
X name, sitename, comment);
X
X#ifdef USE_DBM
X
X if (size_of_pathfd == 0)
X return(-1);
X
X key.dptr = sitename;
X key.dsize = strlen(sitename) + 1;
X
X contents = fetch(key);
X
X if (contents.dptr == 0)
X return(-1); /* can't find it! */
X
X sprintf(expanded, contents.dptr, name);
X strcat(expanded, " "); /* add a single space... */
X strcat(expanded, comment); /* ...and add comment */
X return(0);
X#endif
X
X#ifndef LOOK_CLOSE_AFTER_SEARCH
X
X if (talk_to(sitename)) {
X strcpy(expanded, old_name); /* restore! */
X return(0);
X }
X#endif
X
X if ((addr = find_path_to(sitename, TRUE)) == NULL) {
X
X#ifdef LOOK_CLOSE_AFTER_SEARCH
X
X if (talk_to(sitename)) {
X strcpy(expanded, old_name); /* restore! */
X return(0);
X }
X else
X#endif
X if ((addr = expand_domain(cryptic)) != NULL) {
X strcpy(expanded, addr); /* into THIS buffer */
X strcat(expanded, comment); /* patch in comment */
X return(0);
X }
X else if (size_of_pathfd == 0) { /* no path database! */
X strcpy(expanded, old_name); /* restore! */
X return(0);
X }
X else { /* We just can't get there! */
X strcpy(expanded, old_name); /* restore! */
X return(-1);
X }
X }
X else { /* search succeeded */
X sprintf(expanded, addr, name);
X strcat(expanded, comment); /* add comment */
X return(0);
X }
X#endif
X}
X
Xint
Xbinary_search(name, address)
Xchar *name, *address;
X{
X /* binary search file for name. Return 0 if found, -1 if not */
X
X char machine[40];
X register long first = 0, last, middle;
X register int compare;
X
X address[0] = '\0';
X
X last = size_of_pathfd;
X
X do {
X
X middle = (long) ((first+last) / 2);
X
X get_entry(machine, address, pathfd, middle);
X
X compare = strcmp(name, machine);
X
X if (compare < 0)
X last = middle - 1;
X else if (compare == 0)
X return(0);
X else /* greater */
X first = middle + 1;
X } while (absolute(last) - absolute(first) > FIND_DELTA);
X
X return(-1);
X}
X
Xget_entry(machine, address, fileid, offset)
Xchar *machine, *address;
XFILE *fileid;
Xlong offset;
X{
X /** get entry...return machine and address immediately
X following given offset in fileid. **/
X
X fseek(fileid, offset, 0);
X
X /* read until we hit an end-of-line */
X
X while (getc(fileid) != '\n')
X ;
X
X fscanf(fileid, "%s\t%s", machine, address);
X}
X
Xinit_findnode()
X{
X /** Initialize the FILE and 'size_of_file' values for the
X findnode procedure **/
X
X struct stat buffer;
X
X if (stat(pathfile, &buffer) == -1) {
X dprint2(1, "Warning: No pathalias file [filename %s] found! (%s)\n",
X pathfile, "init_findnode");
X size_of_pathfd = 0;
X return;
X }
X
X size_of_pathfd = (long) buffer.st_size;
X
X#ifdef USE_DBM
X
X if (dbminit(pathfile) != 0) {
X dprint1(1, "Warning: couldn't initialize DBM database %s\n",
X pathfile);
X dprint2(1, "** %s - %s **\n\n", error_name(errno),
X error_description(errno));
X size_of_pathfd = 0; /* error flag, in this case */
X return;
X }
X
X return;
X#else
X
X if ((pathfd = fopen(pathfile,"r")) == NULL) {
X dprint2(1, "Warning: Can't read pathalias file [filename %s] (%s)\n",
X pathfile, "init_findnode");
X size_of_pathfd = 0;
X }
X else
X dprint2(2, "\nOpened file '%s' as path alias database. (%s)\n\n",
X pathfile, "init_findnode");
X#endif
X}
X
Xchar *find_path_to(machine, printf_format)
Xchar *machine;
Xint printf_format;
X{
X /** Returns either the path to the specified machine or NULL if
X not found. If "printf_format" is TRUE, then it leaves the
X '%s' intact, otherwise it assumes that the address is a uucp
X address for the domain expansion program and removes the
X last three characters of the expanded name ("!%s") since
X they're redundant with the expansion!
X **/
X
X static char buffer[LONG_SLEN]; /* space for path */
X
X if (size_of_pathfd > 0)
X if (binary_search(machine, buffer) != -1) { /* found it! */
X if (! printf_format && strlen(buffer) > 3)
X buffer[strlen(buffer)-3] = '\0';
X return( (char *) buffer);
X }
X
X return(NULL); /* failed if it's here! */
X}
END_OF_src/aliasdb.c
if test 7752 -ne `wc -c <src/aliasdb.c`; then
echo shar: \"src/aliasdb.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/domains.c\" \(7773 characters\)
if test -f src/domains.c ; then
echo shar: Will not over-write existing file \"src/domains.c\"
else
sed "s/^X//" >src/domains.c <<'END_OF_src/domains.c'
X/** domains.c **/
X
X/** This file contains all the code dealing with the expansion of
X domain based addresses in Elm. It uses the file "domains" as
X defined in the sysdefs.h file.
X
X (C) Copyright 1986 Dave Taylor
X
X From a file format and idea in "uumail" - designed by Stan Barber.
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "headers.h"
X
X#ifdef BSD
X# undef toupper
X# undef tolower
X#endif
X
X/** define the various characters that we can encounter after a "%" sign
X in the template file...
X**/
X
X#define USERNAME 'U' /* %U = the name of the remote user */
X#define HOSTNAME 'N' /* %N = the remote machine name */
X#define FULLNAME 'D' /* %D = %N + domain info given */
X#define NPATH 'R' /* %R = path to %N from pathalias */
X#define PPATH 'P' /* %P = path to 'P' from pathalias */
X#define OBSOLETE 'S' /* %S = (used to be suffix string) */
X
X/** and finally some characters that are allowed in user/machine names **/
X
X#define okay_others(c) (c == '-' || c == '^' || c == '$' || c == '_')
X
X/** and some allowed ONLY in the username field **/
X
X#define special_chars(c) (c == '%' || c == ':')
X
Xchar *find_path_to(), *expand_domain(), *match_and_expand_domain();
Xchar *strcpy(), *strcat(), *strtok();
Xunsigned long sleep();
Xvoid rewind();
X
Xopen_domain_file()
X{
X if ((domainfd = fopen(domains, "r")) == NULL) {
X dprint1(1, "Can't open file %s as domains file (open_domain_file)\n",
X domains);
X }
X else {
X dprint1(2,
X "\nOpened '%s' as the domain database. (open_domain_file)\n\n",
X domains);
X }
X
X /* if it fails it'll instantiate domainfd to NULL which is
X exactly what we want to have happen!! */
X}
X
Xchar *expand_domain(buffer)
Xchar *buffer;
X{
X /** Expand the address 'buffer' based on the domain information,
X if any. Returns NULL if it can't expand it for any reason.
X **/
X
X char name[2*NLEN], address[2*NLEN], domain[2*NLEN];
X char *match_and_expand_domain();
X
X if (domainfd == NULL) return(NULL); /* no file present! */
X
X if (explode(buffer, name, address, domain))
X return( match_and_expand_domain(domain, name, address) );
X else { /* invalid format - not "user@host.domain" */
X dprint1(3,
X "Invalid format for domain expansion: %s (expand_domain)\n",
X buffer);
X return(NULL);
X }
X}
X
Xint
Xexplode(buffer, name, address, domain)
Xchar *buffer, *name, *address, *domain;
X{
X /** Break buffer, if in format name@machine.domain, into the
X component parts, otherwise return ZERO and don't worry
X about the values of the parameters!
X **/
X
X register int i, j = 0;
X
X /** First get the name... **/
X
X for (i=0; buffer[i] != '@'; i++) {
X if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) && !
X special_chars(buffer[i]))
X return(0); /* invalid character in string! */
X name[i] = buffer[i];
X }
X
X name[i++] = '\0';
X
X /** now let's get the machinename **/
X
X while (buffer[i] != '.') {
X if (! isalnum(buffer[i]) && ! okay_others(buffer[i]))
X return(0); /* invalid character in string! */
X address[j++] = buffer[i++];
X }
X address[j] = '\0';
X
X j = 0;
X
X /** finally let's get the domain information (there better be some!) **/
X
X while (buffer[i] != '\0') {
X if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) &&
X buffer[i] != '.')
X return(0); /* an you fail again, bozo! */
X domain[j++] = toupper(buffer[i]);
X i++;
X }
X
X domain[j] = '\0';
X
X return(j); /* if j == 0 there's no domain info! */
X}
X
Xchar *match_and_expand_domain(domain, name, machine)
Xchar *domain, *name, *machine;
X{
X /** Given the domain, try to find it in the domain file and
X if found expand the entry and return the result as a
X character string...
X **/
X
X static char address[SLEN];
X char buffer[SLEN], domainbuff[NLEN];
X char field1[2*NLEN], field2[2*NLEN], field3[2*NLEN];
X char *path, *template, *expanded, *mydomain, *strtok();
X int matched = 0, in_percent = 0;
X register int i, j = 0;
X
X address[j] = '\0';
X
X domainbuff[0] = '\0';
X mydomain = (char *) domainbuff; /* set up buffer etc */
X
X do {
X rewind(domainfd); /* back to ground zero! */
X
X if (strlen(mydomain) > 0) { /* already in a domain! */
X mydomain++; /* skip leading '.' */
X while (*mydomain != '.' && *mydomain != ',')
X mydomain++; /* next character */
X if (*mydomain == ',')
X return (NULL); /* didn't find domain! */
X }
X else
X sprintf(mydomain, "%s,", domain); /* match ENTIRELY! */
X
X /* whip through file looking for the entry, please... */
X
X while (fgets(buffer, SLEN, domainfd) != NULL) {
X if (buffer[0] == '#') /* skip comments */
X continue;
X if (strncmp(buffer, mydomain, strlen(mydomain)) == 0) { /* match? */
X matched++; /* Gotcha! Remember this momentous event! */
X break;
X }
X }
X
X if (! matched)
X continue; /* Nothing. Not a sausage! Step through! */
X
X /** We've matched the domain! **/
X
X no_ret(buffer);
X
X (void) strtok(buffer, ","); /* skip the domain info */
X
X strcpy(field1, strtok(NULL, ",")); /* fun */
X strcpy(field2, strtok(NULL, ",")); /* stuff */
X strcpy(field3, strtok(NULL, ",")); /* eh? */
X
X path = (char *) NULL;
X
X /* now we merely need to figure out what permutation this is! */
X
X if (field3 == NULL || strlen(field3) == 0)
X if (field2 == NULL || strlen(field2) == 0)
X template = (char *) field1;
X else {
X path = (char *) field1;
X template = (char *) field2;
X }
X else {
X dprint1(2,"Domain info for %s from file broken into THREE fields!!\n",
X domain);
X dprint3(2, "-> %s\n-> %s\n-> %s\n", field1, field2, field3);
X error1("Warning: domain %s uses a defunct field!!", domain);
X sleep(2);
X path = (char *) field1;
X template = (char *) field3;
X }
X
X if (strlen(path) > 0 && path[0] == '>')
X path++; /* skip the '>' character, okay? */
X
X j = 0; /* address is zero, right now, right?? */
X address[j] = '\0'; /* make sure string is too! */
X
X for (i=0; i < strlen(template); i++) {
X if (template[i] == '%') {
X if (! in_percent) /* just hit a NEW percent! */
X in_percent = 1;
X else { /* just another percent sign on the wall... */
X address[j++] = '%';
X address[j] = '\0'; /* ALWAYS NULL terminate */
X in_percent = 0;
X }
X }
X else if (in_percent) { /* Hey! a real command string */
X in_percent = 0;
X switch (template[i]) {
X case USERNAME: strcat(address, name); break;
X case HOSTNAME: strcat(address, machine); break;
X case FULLNAME: strcat(address, machine);
X strcat(address, domain); break;
X case NPATH :
X
X if ((expanded = find_path_to(machine, FALSE)) == NULL) {
X dprint2(3,"\nCouldn't expand system path '%s' (%s)\n\n",
X machine, "domains");
X error1("Couldn't find a path to %s!", machine);
X sleep(2);
X return(NULL); /* failed!! */
X }
X strcat(address, expanded); /* isn't this fun??? */
X
X break;
X
X case PPATH :
X
X if ((expanded = find_path_to(path, FALSE)) == NULL) {
X dprint2(3,"\nCouldn't expand system path '%s' (%s)\n\n",
X path, "domains");
X error1("I Couldn't find a path to %s!", path);
X sleep(2);
X return(NULL); /* failed!! */
X }
X strcat(address, expanded); /* isn't this fun??? */
X
X break;
X
X case OBSOLETE: /* fall through.. */
X default : dprint2(1,
X "\nError: Bad sequence in template file for domain '%s': %%%c\n\n",
X domain, template[i]);
X }
X j = strlen(address);
X }
X else {
X address[j++] = template[i];
X address[j] = '\0'; /* null terminate */
X }
X }
X
X address[j] = '\0';
X
X } while (strlen(address) < 1);
X
X return( (char *) address);
X}
END_OF_src/domains.c
if test 7773 -ne `wc -c <src/domains.c`; then
echo shar: \"src/domains.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/initialize.c\" \(8292 characters\)
if test -f src/initialize.c ; then
echo shar: Will not over-write existing file \"src/initialize.c\"
else
sed "s/^X//" >src/initialize.c <<'END_OF_src/initialize.c'
X/** initialize.c **/
X
X/***** Initialize - read in all the defaults etc etc
X (C) Copyright 1985 Dave Taylor
X*****/
X
X#include "headers.h"
X
X#ifdef BSD
X# include <sgtty.h>
X#else
X# include <termio.h>
X#endif
X
X#include <pwd.h>
X
X#ifdef BSD
X# include <sys/time.h>
X#else
X# include <time.h>
X#endif
X
X#include <signal.h>
X#include <ctype.h>
X#include <errno.h>
X
X#ifdef BSD
X#undef toupper
X#undef tolower
X#endif
X
Xextern int errno; /* system error number on failure */
X
Xchar *error_name(), *error_description();
X
Xchar *expand_logname(), *getenv(), *getlogin(), *strcpy(), *strcat();
Xunsigned short getgid(), getuid();
Xvoid exit();
X
Xstruct header_rec *malloc();
X
Xinitialize(initscreen_too)
Xint initscreen_too;
X{
X /** initialize the whole ball of wax. If "initscreen_too" then
X call init_screen where appropriate..
X **/
X struct passwd *pass, *getpwnam();
X
X register int i, j;
X int quit_signal(), term_signal(), ill_signal(),
X fpe_signal(), bus_signal(), segv_signal(),
X alarm_signal(), pipe_signal();
X char buffer[SLEN], *cp;
X
X
X userid = getuid();
X groupid = getgid();
X
X strcpy(home,((cp = getenv("HOME")) == NULL)? "" : cp);
X strcpy(shell,((cp = getenv("SHELL")) == NULL)? "" : cp);
X strcpy(pager,((cp = getenv("PAGER")) == NULL)? default_pager : cp);
X
X if (debug) { /* setup for dprintf statements! */
X char newfname[SLEN], filename[SLEN];
X
X sprintf(filename, "%s/%s", home, DEBUG);
X if (access(filename, ACCESS_EXISTS) == 0) { /* already one! */
X sprintf(newfname,"%s/%s", home, OLDEBUG);
X (void) link(filename, newfname);
X }
X
X /* Note what we just did up there: we always save the old
X version of the debug file as OLDEBUG, so users can mail
X copies of bug files without trashing 'em by starting up
X the mailer. Dumb, subtle, but easy enough to do!
X */
X
X if ((debugfile = fopen(filename, "w")) == NULL) {
X debug = 0; /* otherwise 'leave' will try to log! */
X leave(fprintf(stderr,"Could not open file %s for debug output!\n",
X filename));
X }
X chown(filename, userid, groupid); /* file owned by user */
X
X fprintf(debugfile, "Debug output of the ELM program. Version %s\n\n",
X VERSION);
X }
X
X if (initscreen_too) /* don't set up unless we need to! */
X InitScreen();
X
X if (debug < 2) { /* otherwise let the system trap 'em! */
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, quit_signal); /* Quit signal */
X signal(SIGTERM, term_signal); /* Terminate signal */
X signal(SIGILL, ill_signal); /* Illegal instruction */
X signal(SIGFPE, fpe_signal); /* Floating point exception */
X signal(SIGBUS, bus_signal); /* Bus error */
X signal(SIGSEGV, segv_signal); /* Segmentation Violation */
X }
X
X signal(SIGALRM, alarm_signal); /* Process Timer Alarm */
X signal(SIGPIPE, pipe_signal); /* Illegal Pipe Operation */
X
X get_term_chars();
X
X gethostname(hostname, sizeof(hostname));
X
X#ifdef BSD
X if ((cp = getenv("USER")) == NULL)
X#else
X if ((cp = getenv("LOGNAME")) == NULL)
X#endif
X if ((cp = getlogin()) == NULL)
X cuserid(username);
X else
X strcpy(username, cp);
X else
X strcpy(username, cp);
X
X /* now let's get the full username.. */
X
X if ((pass = getpwnam(username)) == NULL) {
X error("Couldn't read password entry??");
X strcpy(full_username, username);
X }
X else {
X /* fix for this section from Don Joslyn of Nova University */
X for (i=0,j=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
X i++)
X if (pass->pw_gecos[i] == '&') {
X full_username[j] = '\0';
X strcat(full_username, expand_logname());
X j = strlen(full_username);
X }
X else
X full_username[j++] = pass->pw_gecos[i];
X full_username[j] = '\0';
X }
X
X if ((cp = getenv("EDITOR")) == NULL)
X strcpy(editor,default_editor);
X else
X strcpy(editor, cp);
X strcpy(alternative_editor, editor); /* this one can't be changed! */
X
X if (! mail_only) {
X mailbox[0] = '\0';
X strcpy(prefixchars, "> "); /* default message prefix */
X sprintf(calendar_file, "%s/%s", home, dflt_calendar_file);
X }
X
X local_signature[0] = remote_signature[0] = '\0'; /* NULL! */
X
X read_rc_file(); /* reading the .elmrc next... */
X
X /** now try to expand the specified filename... **/
X
X if (strlen(infile) > 0) {
X (void) expand_filename(infile);
X if ((errno = can_access(infile, READ_ACCESS))) {
X dprint2(1,"Error: given file %s as mailbox - unreadable (%s)!\n",
X infile, error_name(errno));
X fprintf(stderr,"Can't open mailbox '%s' for reading!\n", infile);
X exit(1);
X }
X }
X
X /** check to see if the user has defined a LINES or COLUMNS
X value different to that in the termcap entry (for
X windowing systems, of course!) **/
X
X ScreenSize(&LINES, &COLUMNS);
X
X if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
X sscanf(cp, "%d", &LINES);
X LINES -= 1; /* kludge for HP Window system? ... */
X }
X
X if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
X sscanf(cp, "%d", &COLUMNS);
X
X /** fix the shell if needed **/
X
X if (shell[0] != '/') {
X sprintf(buffer, "/bin/%s", shell);
X strcpy(shell, buffer);
X }
X
X if (! mail_only) {
X mailbox_defined = (mailbox[0] != '\0');
X
X /* get the cursor control keys... */
X
X cursor_control = FALSE;
X
X if ((cp = return_value_of("ku")) != NULL)
X if (strlen(cp) == 2) {
X strcpy(up, cp);
X if ((cp = return_value_of("kd")) == NULL)
X cursor_control = FALSE;
X else if (strlen(cp) != 2)
X cursor_control = FALSE;
X else {
X strcpy(down, cp);
X cursor_control = TRUE;
X transmit_functions(ON);
X }
X }
X
X strcpy(start_highlight, "->");
X end_highlight[0] = '\0';
X
X if (!arrow_cursor) { /* try to use inverse bar instead */
X if ((cp = return_value_of("so")) != NULL) {
X strcpy(start_highlight, cp);
X if ((cp = return_value_of("se")) == NULL)
X strcpy(start_highlight, "->");
X else {
X strcpy(end_highlight, cp);
X has_highlighting = TRUE;
X }
X }
X }
X }
X
X /** allocate the first KLICK headers... **/
X
X if ((header_table = malloc(KLICK*sizeof(struct header_rec))) == NULL) {
X fprintf(stderr,"\n\r\n\rCouldn't allocate initial headers!\n\r\n");
X leave();
X }
X max_headers = KLICK; /* we have those preallocated */
X
X /** now cruise along... **/
X
X if (! mail_only) {
X if (mini_menu)
X headers_per_page = LINES - 13;
X else
X headers_per_page = LINES - 8; /* 5 more headers! */
X
X newmbox(1,FALSE, TRUE); /* read in the mailbox! */
X }
X
X dprint0(2,"\n-- end of initialization phase --\n");
X
X dprint3(2,"\thostname = %s\n\tusername = %s\n\tfull_username = \"%s\"\n",
X hostname, username, full_username);
X
X dprint3(2,"\thome = %s\n\teditor = %s\n\tmailbox = %s\n",
X home, editor, mailbox);
X
X dprint3(2,"\tinfile = %s\n\tfolder-dir = %s\n\tprintout = \"%s\"\n",
X infile, folders, printout);
X
X dprint3(2,"\tsavefile = %s\n\tprefix = \"%s\"\n\tshell = %s\n",
X savefile, prefixchars, shell);
X
X if (signature)
X dprint2(2,"\tlocal-signature = %s\n\tremote-signature = %s\n",
X local_signature, remote_signature);
X
X dprint0(1,"-- beginning execution phase --\n\n");
X}
X
Xget_term_chars()
X{
X /** This routine sucks out the special terminal characters
X ERASE and KILL for use in the input routine. The meaning
X of the characters are (dare I say it?) fairly obvious... **/
X
X#ifdef BSD
X struct sgttyb term_buffer;
X
X# define TCGETA TIOCGETP
X
X#else
X struct termio term_buffer;
X#endif
X
X if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
X dprint1(1,"Error: %s encountered on ioctl call (get_term_chars)\n",
X error_name(errno));
X /* set to defaults for terminal driver */
X backspace = BACKSPACE;
X kill_line = ctrl('U');
X }
X else {
X#ifdef BSD
X backspace = term_buffer.sg_erase;
X kill_line = term_buffer.sg_kill;
X#else
X backspace = term_buffer.c_cc[VERASE];
X kill_line = term_buffer.c_cc[VKILL];
X#endif
X }
X}
X
Xchar *expand_logname()
X{
X /** Return logname in a nice format (for expanding "&" in the
X /etc/passwd file) **/
X
X static char buffer[SLEN];
X register int i;
X
X if (strlen(username) == 0)
X buffer[0] = '\0';
X else {
X buffer[0] = toupper(username[0]);
X
X for (i=1; username[i] != '\0'; i++)
X buffer[i] = tolower(username[i]);
X
X buffer[i] = '\0';
X }
X
X return( (char *) buffer);
X}
END_OF_src/initialize.c
if test 8292 -ne `wc -c <src/initialize.c`; then
echo shar: \"src/initialize.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/fastmail.c\" \(8167 characters\)
if test -f utils/fastmail.c ; then
echo shar: Will not over-write existing file \"utils/fastmail.c\"
else
sed "s/^X//" >utils/fastmail.c <<'END_OF_utils/fastmail.c'
X/** fastmail.c **/
X
X/** This program is specifically written for group mailing lists and
X such batch type mail processing. It does NOT use aliases at all,
X it does NOT read the /etc/password file to find the From: name
X of the user and does NOT expand any addresses. It is meant
X purely as a front-end for either /bin/mail or /usr/lib/sendmail
X (according to what is available on the current system).
X
X **** This program should be used with CAUTION *****
X
X (C) Copyright 1985 Dave Taylor
X**/
X
X/** The calling sequence for this program is:
X
X fastmail {args} filename full-email-address
X
X where args could be any (or all) of;
X
X -b bcc-list (Blind carbon copies to)
X -c cc-list (carbon copies to)
X -d (debug on)
X -f from (from name)
X -r reply-to-address (Reply-To:)
X -s subject (subject of message)
X**/
X
X#include <stdio.h>
X
X#ifdef BSD
X# ifdef BSD4.1
X# include <time.h>
X# include <sys/types.h>
X# include <sys/timeb.h>
X# else
X# include <sys/time.h>
X# endif
X#else
X# include <time.h>
X#endif
X
X#include "defs.h"
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define binrmail "/bin/rmail"
X#define temphome "/tmp/fastmail."
X
X#define DONE 0
X#define ERROR -1
X
Xchar *optional_arg; /* optional argument as we go */
Xint opt_index; /* argnum + 1 when we leave */
X
Xchar *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
X "Fri", "Sat", "" };
X
Xchar *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
X
Xchar *get_arpa_date();
X
X#ifdef BSD
X char *timezone();
X#else
X extern char *tzname[];
X#endif
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X FILE *tempfile;
X char hostname[NLEN], username[NLEN], from_string[SLEN], subject[SLEN];
X char filename[SLEN], tempfilename[SLEN], command_buffer[256];
X char replyto[SLEN], cc_list[SLEN], bcc_list[SLEN], to_list[SLEN];
X int c, sendmail_available, debug = 0;
X
X replyto[0] = '\0';
X cc_list[0] = '\0';
X bcc_list[0] = '\0';
X
X while ((c = get_options(argc, argv, "b:c:df:r:s:")) > 0) {
X switch (c) {
X case 'b' : strcpy(bcc_list, optional_arg); break;
X case 'c' : strcpy(cc_list, optional_arg); break;
X case 'd' : debug++; break;
X case 'f' : strcpy(from_string, optional_arg); break;
X case 'r' : strcpy(replyto, optional_arg); break;
X case 's' : strcpy(subject, optional_arg); break;
X }
X }
X
X if (c == ERROR) {
X fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X fprintf(stderr, " where {args} can be;\n");
X fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X exit(1);
X }
X
X if (opt_index > argc) {
X fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X fprintf(stderr, " where {args} can be;\n");
X fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X exit(1);
X }
X
X strcpy(filename, argv[opt_index++]);
X
X if (opt_index > argc) {
X fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X fprintf(stderr, " where {args} can be;\n");
X fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X exit(1);
X }
X
X gethostname(hostname, sizeof(hostname));
X strcpy(username, getlogin());
X if (strlen(username) == 0)
X cuserid(username);
X
X if (access(filename, READ_ACCESS) == -1)
X exit(fprintf(stderr, "Error: can't find file %s!\n", filename));
X
X sprintf(tempfilename, "%s%d", temphome, getpid());
X
X if ((tempfile = fopen(tempfilename, "w")) == NULL)
X exit(fprintf(stderr, "Couldn't open temp file %s\n", tempfilename));
X
X if (strlen(from_string) > 0)
X fprintf(tempfile, "From: %s!%s (%s)\n",
X hostname, username, from_string);
X else
X fprintf(tempfile, "From: %s!%s\n", hostname, username);
X
X fprintf(tempfile, "Date: %s\n", get_arpa_date());
X
X if (strlen(subject) > 0)
X fprintf(tempfile, "Subject: %s\n", subject);
X
X if (strlen(replyto) > 0)
X fprintf(tempfile, "Reply-To: %s\n", replyto);
X
X while (opt_index < argc)
X sprintf(to_list, "%s%s%s", to_list, (strlen(to_list) > 0? ", ":""),
X argv[opt_index++]);
X
X fprintf(tempfile, "To: %s\n", to_list);
X
X if (strlen(cc_list) > 0)
X fprintf(tempfile, "Cc: %s\n", cc_list);
X
X if (strlen(bcc_list) > 0)
X fprintf(tempfile, "Bcc: %s\n", bcc_list); /* trust xport */
X
X fprintf(tempfile, "X-Mailer: fastmail [version %s]\n", VERSION);
X fprintf(tempfile, "\n");
X
X fclose(tempfile);
X
X /** now we'll cat both files to /bin/rmail or sendmail... **/
X
X sendmail_available = (access(sendmail, EXECUTE_ACCESS) != -1);
X
X printf("Mailing to %s%s%s%s%s [via %s]\n", to_list,
X (strlen(cc_list) > 0 ? " ":""), cc_list,
X (strlen(bcc_list) > 0 ? " ":""), bcc_list,
X sendmail_available? "sendmail" : "rmail");
X
X sprintf(command_buffer, "cat %s %s | %s '%s %s %s'",
X tempfilename, filename,
X sendmail_available? sendmail : mailer,
X to_list, cc_list, bcc_list);
X
X if (debug)
X printf("%s\n", command_buffer);
X
X system(command_buffer);
X
X unlink(tempfilename);
X}
X
X
Xchar *get_arpa_date()
X{
X /** returns an ARPA standard date. The format for the date
X according to DARPA document RFC-822 is exemplified by;
X
X Mon, 12 Aug 85 6:29:08 MST
X
X **/
X
X static char buffer[SLEN]; /* static character buffer */
X struct tm *the_time, /* Time structure, see CTIME(3C) */
X *localtime();
X long junk; /* time in seconds.... */
X#ifdef BSD
X# ifdef BSD4.1
X struct timeb loc_time; /* of course this is different! */
X# else
X struct timeval time_val;
X struct timezone time_zone;
X# endif
X#endif
X
X#ifdef BSD
X# ifdef BSD4.1
X junk = (long) time((long *) 0);
X ftime(&loc_time);
X# else
X gettimeofday(&time_val, &time_zone);
X junk = time_val.tv_sec;
X# endif
X#else
X junk = time(0); /* this must be here for it to work! */
X#endif
X the_time = localtime(&junk);
X
X sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
X arpa_dayname[the_time->tm_wday],
X the_time->tm_mday % 32,
X arpa_monname[the_time->tm_mon],
X the_time->tm_year % 100,
X the_time->tm_hour % 24,
X the_time->tm_min % 61,
X the_time->tm_sec % 61,
X#ifdef BSD
X# ifdef BSD4.1
X timezone(loc_time.time_zone, the_time->tz_isdst));
X# else
X timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
X# endif
X#else
X tzname[the_time->tm_isdst]);
X#endif
X
X return( (char *) buffer);
X}
X
X/** Starting argument parsing routine.
X
X Called as "get_options(argc, argv, options)" where options is a string
X of the form "abc:d" indicating that 'a' 'b' and 'd' are flags and
X 'c' is a flag with a trailing argument. Optional arguments are
X returned in the external char * variable "optional_arg", and the
X external int "opt_index" is set to the first entry in the argv list
X that wasn't processed (ie after the flags).
X
X For example, the C compiler would have something of the form
X getopt(argc, argv, "Oo:l:") to allow "cc -O -o output -l lib file.c"
X
X (C) Copyright 1986, Dave Taylor
X**/
X
Xint _indx = 1, _argnum = 1;
X
Xint
Xget_options(argc, argv, options)
Xint argc;
Xchar *argv[], *options;
X{
X /** Returns the character argument next, and optionally instantiates
X "argument" to the argument associated with the particular option
X **/
X
X char *word, *strchr();
X
X if (_indx >= strlen(argv[_argnum])) {
X _argnum++;
X _indx = 1; /* zeroeth char is '-' */
X }
X
X if (_argnum >= argc) {
X opt_index = argc;
X return(DONE);
X }
X
X if (argv[_argnum][0] != '-') {
X opt_index = _argnum;
X return(DONE);
X }
X
X word = strchr(options, argv[_argnum][_indx++]);
X
X if (strlen(word) == 0)
X return(ERROR);
X
X if (word[1] == ':') {
X
X /** Two possibilities - either tailing end of this argument or the
X next argument in the list **/
X
X if (_indx < strlen(argv[_argnum])) { /* first possibility */
X optional_arg = (char *) (argv[_argnum] + _indx);
X _argnum++;
X _indx = 1;
X }
X else { /* second choice */
X if (++_argnum >= argc)
X return(ERROR); /* no argument!! */
X
X optional_arg = (char *) argv[_argnum++];
X _indx = 1;
X }
X }
X
X return((int) word[0]);
X}
END_OF_utils/fastmail.c
if test 8167 -ne `wc -c <utils/fastmail.c`; then
echo shar: \"utils/fastmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/newmail.c\" \(7989 characters\)
if test -f utils/newmail.c ; then
echo shar: Will not over-write existing file \"utils/newmail.c\"
else
sed "s/^X//" >utils/newmail.c <<'END_OF_utils/newmail.c'
X/** newmail.c **/
X
X/** Keep track of the mail for the current user...if new mail
X arrives, output a line of the form;
X
X New mail from <name> - <subject>
X
X where <name> is either the persons full name, or machine!login.
X If there is no subject, it will say.
X
X Added: you can specify a file other than the mailbox to keep
X track of - if an argument is given, the program will try
X to use it as a filename...
X
X Also, the program will quit when you log off of the machine.
X
X (C) Copyright 1986, Dave Taylor
X**/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "defs.h"
X
X#ifdef AUTO_BACKGROUND
X#include <signal.h> /* background jobs ignore some signals... */
X#endif
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define LINEFEED (char) 10
X#define BEGINNING 0 /* seek fseek(3S) */
X#define SLEEP_TIME 60
X
X#define NO_SUBJECT "(No Subject Specified)"
X
XFILE *mailfile;
X
Xlong bytes();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char filename[LONG_SLEN];
X long size, newsize;
X
X if (argc > 2)
X fprintf(stderr, "Usage: %s [filename] &\n", argv[0]);
X else if (argc == 2) {
X strcpy(filename, argv[1]);
X if (access(filename, ACCESS_EXISTS) == -1) {
X fprintf(stderr,"%s: Can't open file %s to keep track of!\n",
X argv[0], filename);
X exit(1);
X }
X }
X else
X sprintf(filename,"%s%s",mailhome, getlogin());
X
X#ifdef AUTO_BACKGROUND
X if (fork()) /* automatically puts this task in background! */
X exit(0);
X
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, SIG_IGN);
X signal(SIGHUP, SIG_DFL); /* so we exit when logged out */
X#endif
X
X size = bytes(filename);
X
X mailfile = (FILE *) NULL;
X
X while (1) {
X
X#ifndef AUTO_BACKGROUND /* won't work if we're nested this deep! */
X if (getppid() == 1) /* we've lost our shell! */
X exit();
X#endif
X if (! isatty(1)) /* we're not sending output to a tty any more */
X exit();
X
X /** Note the lack of error checking on the fopen() (Philip Peake
X did!) - this is okay since if it fails we don't have any
X mail and we can sleep(60) and try again later...
X **/
X
X if (mailfile == (FILE *) NULL)
X mailfile = fopen(filename,"r");
X
X if ((newsize = bytes(filename)) > size) { /* new mail */
X fseek(mailfile, size, BEGINNING); /* skip all current mail */
X size = newsize;
X printf("\n\r"); /* blank lines surrounding message */
X read_headers();
X printf("\n\r");
X }
X else if (newsize != size) {
X size = newsize; /* mail's been removed... */
X (void) fclose(mailfile); /* close it and ... */
X mailfile = (FILE *) NULL; /* let's reopen the file */
X }
X
X sleep(SLEEP_TIME);
X }
X}
X
Xint
Xread_headers()
X{
X /** read the headers, output as found **/
X
X char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
X register int subj = 0, in_header = 1, count = 0, priority=0;
X
X while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
X if (first_word(buffer,"From ")) {
X if (real_from(buffer, from_whom)) {
X subj = 0;
X in_header = 1;
X }
X }
X else if (in_header) {
X if (first_word(buffer,">From"))
X forwarded(buffer, from_whom); /* return address */
X else if (first_word(buffer,"Subject:") ||
X first_word(buffer,"Re:")) {
X if (! subj++) {
X remove_first_word(buffer);
X strcpy(subject, buffer);
X }
X }
X else if (first_word(buffer,"Priority:"))
X priority++;
X else if (first_word(buffer,"From:"))
X parse_arpa_from(buffer, from_whom);
X else if (buffer[0] == LINEFEED) {
X in_header = 0; /* in body of message! */
X show_header(priority, from_whom, subject);
X from_whom[0] = 0;
X subject[0] = 0;
X count++;
X }
X }
X }
X return(count);
X}
X
Xint
Xreal_from(buffer, who)
Xchar *buffer, *who;
X{
X /***** returns true iff 's' has the seven 'from' fields,
X initializing the who to the sender *****/
X
X char junk[80];
X
X junk[0] = '\0';
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
X who, junk);
X return(junk[0] != '\0');
X}
X
Xforwarded(buffer, who)
Xchar *buffer, *who;
X{
X /** change 'from' and date fields to reflect the ORIGINATOR of
X the message by iteratively parsing the >From fields... **/
X
X char machine[80], buff[80];
X
X machine[0] = '\0';
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
X who, machine);
X
X if (machine[0] == '\0') /* try for srm address */
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
X who, machine);
X
X if (machine[0] == '\0')
X sprintf(buff,"anonymous");
X else
X sprintf(buff,"%s!%s", machine, who);
X
X strncpy(who, buff, 80);
X}
X
X
Xremove_first_word(string)
Xchar *string;
X{ /** removes first word of string, ie up to first non-white space
X following a white space! **/
X
X register int loc;
X
X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
X ;
X
X while (string[loc] == ' ' || string[loc] == '\t')
X loc++;
X
X move_left(string, loc);
X}
X
Xmove_left(string, chars)
Xchar string[];
Xint chars;
X{
X /** moves string chars characters to the left DESTRUCTIVELY **/
X
X register int i;
X
X chars--; /* index starting at zero! */
X
X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
X string[i-chars] = string[i];
X
X string[i-chars] = '\0';
X}
X
Xshow_header(priority, from, subject)
Xint priority;
Xchar *from, *subject;
X{
X /** output header in clean format, including abbreviation
X of return address if more than one machine name is
X contained within it! **/
X char buffer[SLEN];
X int loc, i=0, exc=0;
X
X#ifdef PREFER_UUCP
X
X if (chloc(from, '!') != -1 && in_string(from, BOGUS_INTERNET))
X from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0';
X
X#endif
X
X loc = strlen(from);
X
X while (exc < 2 && loc > 0)
X if (from[--loc] == '!')
X exc++;
X
X if (exc == 2) { /* lots of machine names! Get last one */
X loc++;
X while (loc < strlen(from) && loc < SLEN)
X buffer[i++] = from[loc++];
X buffer[i] = '\0';
X strcpy(from, buffer);
X }
X
X if (strlen(subject) < 2)
X strcpy(subject, NO_SUBJECT);
X
X printf(">> %s mail from %s - %s\n\r",
X priority? "PRIORITY" : "New", from, subject);
X}
X
Xparse_arpa_from(buffer, newfrom)
Xchar *buffer, *newfrom;
X{
X /** try to parse the 'From:' line given... It can be in one of
X two formats:
X From: Dave Taylor <hpcnou!dat>
X or From: hpcnou!dat (Dave Taylor)
X Change 'newfrom' ONLY if sucessfully parsed this entry and
X the resulting name is non-null!
X **/
X
X char temp_buffer[SLEN], *temp;
X register int i, j = 0;
X
X temp = (char *) temp_buffer;
X temp[0] = '\0';
X
X no_ret(buffer); /* blow away '\n' char! */
X
X if (lastch(buffer) == '>') {
X for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
X buffer[i] != '('; i++)
X temp[j++] = buffer[i];
X temp[j] = '\0';
X }
X else if (lastch(buffer) == ')') {
X for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
X buffer[i] != '<'; i--)
X temp[j++] = buffer[i];
X temp[j] = '\0';
X reverse(temp);
X }
X
X if (strlen(temp) > 0) { /* mess with buffer... */
X
X /* remove leading spaces... */
X
X while (whitespace(temp[0]))
X temp = (char *) (temp + 1); /* increment address! */
X
X /* remove trailing spaces... */
X
X i = strlen(temp) - 1;
X
X while (whitespace(temp[i]))
X temp[i--] = '\0';
X
X /* if anything is left, let's change 'from' value! */
X
X if (strlen(temp) > 0)
X strcpy(newfrom, temp);
X }
X}
X
Xreverse(string)
Xchar *string;
X{
X /** reverse string... pretty trivial routine, actually! **/
X
X char buffer[SLEN];
X register int i, j = 0;
X
X for (i = strlen(string)-1; i >= 0; i--)
X buffer[j++] = string[i];
X
X buffer[j] = '\0';
X
X strcpy(string, buffer);
X}
X
Xlong
Xbytes(name)
Xchar *name;
X{
X /** return the number of bytes in the specified file. This
X is to check to see if new mail has arrived.... **/
X
X int ok = 1;
X extern int errno; /* system error number! */
X struct stat buffer;
X
X if (stat(name, &buffer) != 0)
X if (errno != 2)
X exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
X else
X ok = 0;
X
X return(ok ? buffer.st_size : 0);
X}
END_OF_utils/newmail.c
if test 7989 -ne `wc -c <utils/newmail.c`; then
echo shar: \"utils/newmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/wnewmail.c\" \(8080 characters\)
if test -f utils/wnewmail.c ; then
echo shar: Will not over-write existing file \"utils/wnewmail.c\"
else
sed "s/^X//" >utils/wnewmail.c <<'END_OF_utils/wnewmail.c'
X/** wnewmail.c **/
X
X/** Same as newmail.c but for a windowing system...
X
X (C) Copyright 1986, Dave Taylor
X**/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "defs.h"
X
X#ifdef AUTO_BACKGROUND
X#include <signal.h> /* background jobs ignore some signals... */
X#endif
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define LINEFEED (char) 10
X#define BEGINNING 0 /* seek fseek(3S) */
X#define SLEEP_TIME 10
X
X#define NO_SUBJECT "(No Subject Specified)"
X
XFILE *mailfile;
X
Xlong bytes();
Xchar *getusername();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char filename[LONG_SLEN];
X long size, newsize;
X
X if (argc > 2)
X fprintf(stderr, "Usage: %s [filename] &\n", argv[0]);
X else if (argc == 2) {
X strcpy(filename, argv[1]);
X if (access(filename, ACCESS_EXISTS) == -1) {
X fprintf(stderr,
X "%s: Can't open file %s to keep track of incoming mail.\n",
X argv[0], filename);
X exit(1);
X }
X }
X else
X sprintf(filename,"%s%s",mailhome, getusername());
X
X#ifdef AUTO_BACKGROUND
X if (fork()) /* automatically puts this task in background! */
X exit(0);
X
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, SIG_IGN);
X signal(SIGHUP, SIG_DFL); /* so we exit when logged out */
X#endif
X
X size = bytes(filename);
X
X mailfile = (FILE *) NULL;
X
X printf("Incoming Mail;\n");
X
X while (1) {
X
X#ifndef AUTO_BACKGROUND /* won't work if we're nested this deep! */
X if (getppid() == 1) /* we've lost our shell! */
X exit();
X#endif
X if (! isatty(1)) /* we're not talking to the screen any more */
X exit();
X
X /** Note the lack of error checking on the fopen() (Philip Peake
X did!) - this is okay since if it fails we don't have any
X mail and we can sleep(60) and try again later...
X **/
X
X if (mailfile == (FILE *) NULL)
X mailfile = fopen(filename,"r");
X
X if ((newsize = bytes(filename)) > size) { /* new mail */
X fseek(mailfile, size, BEGINNING); /* skip all current mail */
X size = newsize;
X printf("%c", 007); /* beep for new mail! */
X read_headers();
X }
X else if (newsize != size) {
X size = newsize; /* mail's been removed... */
X (void) fclose(mailfile); /* close it and ... */
X mailfile = (FILE *) NULL; /* let's reopen the file */
X }
X
X sleep(SLEEP_TIME);
X }
X}
X
Xint
Xread_headers()
X{
X /** read the headers, output as found **/
X
X char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
X register int subj = 0, in_header = 1, count = 0, priority = 0;
X
X while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
X if (first_word(buffer,"From ")) {
X if (real_from(buffer, from_whom)) {
X subj = 0;
X priority = 0;
X in_header = 1;
X }
X }
X else if (in_header) {
X if (first_word(buffer,">From"))
X forwarded(buffer, from_whom); /* return address */
X else if (first_word(buffer,"Subject:") ||
X first_word(buffer,"Re:")) {
X if (! subj++) {
X remove_first_word(buffer);
X strcpy(subject, buffer);
X }
X }
X else if (first_word(buffer,"From:"))
X parse_arpa_from(buffer, from_whom);
X else if (first_word(buffer, "Priority:"))
X priority++;
X else if (buffer[0] == LINEFEED) {
X in_header = 0; /* in body of message! */
X show_header(priority, from_whom, subject);
X from_whom[0] = 0;
X subject[0] = 0;
X count++;
X }
X }
X }
X return(count);
X}
X
Xint
Xreal_from(buffer, who)
Xchar *buffer, *who;
X{
X /***** returns true iff 's' has the seven 'from' fields,
X initializing the who to the sender *****/
X
X char junk[80];
X
X junk[0] = '\0';
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
X who, junk);
X return(junk[0] != '\0');
X}
X
Xforwarded(buffer, who)
Xchar *buffer, *who;
X{
X /** change 'from' and date fields to reflect the ORIGINATOR of
X the message by iteratively parsing the >From fields... **/
X
X char machine[80], buff[80];
X
X machine[0] = '\0';
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
X who, machine);
X
X if (machine[0] == '\0') /* try for srm address */
X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
X who, machine);
X
X if (machine[0] == '\0')
X sprintf(buff,"anonymous");
X else
X sprintf(buff,"%s!%s", machine, who);
X
X strncpy(who, buff, 80);
X}
X
X
Xremove_first_word(string)
Xchar *string;
X{ /** removes first word of string, ie up to first non-white space
X following a white space! **/
X
X register int loc;
X
X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
X ;
X
X while (string[loc] == ' ' || string[loc] == '\t')
X loc++;
X
X move_left(string, loc);
X}
X
Xmove_left(string, chars)
Xchar string[];
Xint chars;
X{
X /** moves string chars characters to the left DESTRUCTIVELY **/
X
X register int i;
X
X chars--; /* index starting at zero! */
X
X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
X string[i-chars] = string[i];
X
X string[i-chars] = '\0';
X}
X
Xshow_header(priority, from, subject)
Xint priority;
Xchar *from, *subject;
X{
X /** Output header in clean format, including abbreviation
X of return address if more than one machine name is
X contained within it! **/
X
X char buffer[SLEN];
X int loc, i=0, exc=0;
X
X#ifdef PREFER_UUCP
X
X if (chloc(from,'!') != -1 && in_string(from, BOGUS_INTERNET))
X from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0';
X
X#endif
X
X loc = strlen(from);
X
X while (exc < 2 && loc > 0)
X if (from[--loc] == '!')
X exc++;
X
X if (exc == 2) { /* lots of machine names! Get last one */
X loc++;
X while (loc < strlen(from) && loc < SLEN)
X buffer[i++] = from[loc++];
X buffer[i] = '\0';
X strcpy(from, buffer);
X }
X
X if (strlen(subject) < 2)
X strcpy(subject, NO_SUBJECT);
X
X if (strlen(from) > 0) /* last final check... */
X printf("%sMail from %s -- %s\n",
X priority? "PRIORITY ": "", from, subject);
X}
X
Xparse_arpa_from(buffer, newfrom)
Xchar *buffer, *newfrom;
X{
X /** Try to parse the 'From:' line given... It can be in one of
X two formats:
X From: Dave Taylor <hpcnou!dat>
X or From: hpcnou!dat (Dave Taylor)
X Change 'newfrom' ONLY if sucessfully parsed this entry and
X the resulting name is non-null!
X **/
X
X char temp_buffer[SLEN], *temp;
X register int i, j = 0;
X
X temp = (char *) temp_buffer;
X temp[0] = '\0';
X
X no_ret(buffer); /* blow away '\n' char! */
X
X if (lastch(buffer) == '>') {
X for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
X buffer[i] != '('; i++)
X temp[j++] = buffer[i];
X temp[j] = '\0';
X }
X else if (lastch(buffer) == ')') {
X for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
X buffer[i] != '<'; i--)
X temp[j++] = buffer[i];
X temp[j] = '\0';
X reverse(temp);
X }
X
X if (strlen(temp) > 0) { /* mess with buffer... */
X
X /* remove leading spaces... */
X
X while (whitespace(temp[0]))
X temp = (char *) (temp + 1); /* increment address! */
X
X /* remove trailing spaces... */
X
X i = strlen(temp) - 1;
X
X while (whitespace(temp[i]))
X temp[i--] = '\0';
X
X /* if anything is left, let's change 'from' value! */
X
X if (strlen(temp) > 0)
X strcpy(newfrom, temp);
X }
X}
X
Xreverse(string)
Xchar *string;
X{
X /** reverse string... pretty trivial routine, actually! **/
X
X char buffer[SLEN];
X register int i, j = 0;
X
X for (i = strlen(string)-1; i >= 0; i--)
X buffer[j++] = string[i];
X
X buffer[j] = '\0';
X
X strcpy(string, buffer);
X}
X
Xlong
Xbytes(name)
Xchar *name;
X{
X /** return the number of bytes in the specified file. This
X is to check to see if new mail has arrived.... **/
X
X int ok = 1;
X extern int errno; /* system error number! */
X struct stat buffer;
X
X if (stat(name, &buffer) != 0)
X if (errno != 2)
X exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
X else
X ok = 0;
X
X return(ok ? (long) buffer.st_size : 0L);
X}
X
Xchar *getusername()
X{
X /** Getting the username on some systems is a real pain, so...
X This routine is guaranteed to return a usable username **/
X
X char *return_value, *cuserid(), *getlogin();
X
X if ((return_value = cuserid(NULL)) == NULL)
X if ((return_value = getlogin()) == NULL)
X exit(printf("Newmail: I can't get username!\n"));
X
X return( (char *) return_value);
X}
END_OF_utils/wnewmail.c
if test 8080 -ne `wc -c <utils/wnewmail.c`; then
echo shar: \"utils/wnewmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 19\).
cp /dev/null ark7isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
if test ! -f ark${I}isdone ; then
echo shar: You still need to run archive ${I}.
DONE=false
fi
done
if test "$DONE" = "true" ; then
echo You have unpacked all 19 archives.
echo "See the Instructions file"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
fi
## End of shell archive.
exit 0