sources-request@mirror.TMC.COM (03/09/87)
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