home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.3pl11 / utils / newmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-05  |  20.2 KB  |  790 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: newmail.c,v 4.1.1.3 90/12/05 15:05:39 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.3 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    newmail.c,v $
  17.  * Revision 4.1.1.3  90/12/05  15:05:39  syd
  18.  * Remove unused opterr variable, some getopts dont define it
  19.  * From: Syd via Peter King
  20.  * 
  21.  * Revision 4.1.1.2  90/10/07  21:10:35  syd
  22.  * newmail did not correctly present sender name if the source
  23.  * of the mail is local from the system.
  24.  * From: JT McDuffie <guardian!jt@Sun.COM>
  25.  * 
  26.  * Revision 4.1.1.1  90/10/07  19:43:44  syd
  27.  * Fixes when newmail detects that the mail folder has grown in size it prints a newline, even
  28.  * if there were no new subjects in the folder.
  29.  * From: Uwe Doering <gemini%geminix.mbx.sub.org@RELAY.CS.NET>
  30.  * 
  31.  * Revision 4.1  90/04/28  22:44:48  syd
  32.  * checkin of Elm 2.3 as of Release PL0
  33.  * 
  34.  *
  35.  ******************************************************************************/
  36.  
  37. /** This is actually two programs folded into one - 'newmail()' and
  38.     'wnewmail()'.  They perform essentially the same function, to
  39.     monitor the mail arriving in a set of/a mailbox or folder, but
  40.     newmail is designed to run in background on a terminal, and
  41.     wnewmail is designed to have a window of its own to run in.
  42.  
  43.     The main difference is that wnewmail checks for mail more often.
  44.  
  45.     The usage parameters are:
  46.  
  47.     -i <interval>          how often to check for mail
  48.                 (default: 60 secs if newmail,
  49.                       10 secs if wnewmail)
  50.  
  51.     <filename>        name of a folder to monitor
  52.                 (can prefix with '+'/'=', or can
  53.                  default to the incoming mailbox)
  54.  
  55.     <filename>=prefix    file to monitor, output with specified
  56.                 prefix when mail arrives.
  57.  
  58.     If we're monitoring more than one mailbox the program will prefix
  59.     each line output (if 'newmail') or each cluster of mail (if 'wnewmail')
  60.     with the basename of the folder the mail has arrived in.  In the 
  61.     interest of exhaustive functionality, you can also use the "=prefix"
  62.     suffix (eh?) to specify your own strings to prefix messages with.
  63.  
  64.     The output format is either:
  65.  
  66.       newmail:
  67.          >> New mail from <user> - <subject>
  68.          >> Priority mail from <user> - <subject>
  69.  
  70.          >> <folder>: from <user> - <subject>
  71.          >> <folder>: Priority from <user> - <subject>
  72.  
  73.       wnewmail:
  74.          <user> - <subject>
  75.          Priority: <user> - <subject>
  76.  
  77.          <folder>: <user> - <subject>
  78.          <folder>: Priority: <user> - <subject>\fR
  79.  
  80. **/
  81.  
  82. #include <stdio.h>
  83. #include <errno.h>
  84. #include <sys/types.h>
  85. #include <sys/stat.h>
  86.  
  87. #include "defs.h"
  88.  
  89. #include <signal.h>    /* background jobs ignore some signals... */
  90.  
  91. static char ident[] = { WHAT_STRING };
  92.  
  93. #define LINEFEED        (char) 10
  94. #define BEGINNING        0            /* seek fseek(3S) */
  95. #define DEFAULT_INTERVAL    60
  96.  
  97. #define MAX_FOLDERS        25        /* max we can keep track of */
  98.  
  99. #define NO_SUBJECT    "(No Subject Specified)"
  100.  
  101. #define metachar(c)    (c == '+' || c == '=' || c == '%')
  102.  
  103. char  *getusername();
  104. long  bytes();
  105.  
  106. struct folder_struct {
  107.       char        foldername[SLEN];
  108.       char        prefix[NLEN];
  109.       FILE         *fd;
  110.       long        filesize;
  111.        } folders[MAX_FOLDERS];
  112.  
  113. int  interval_time,        /* how long to sleep between checks */
  114.      debug = 0,            /* include verbose debug output?    */
  115.      in_window = 0,        /* are we running as 'wnewmail'?    */
  116.      total_folders = 0,        /* # of folders we're monitoring    */
  117.      current_folder = 0;    /* struct pointer for looping       */
  118.  
  119. #ifdef PIDCHECK
  120. int  parent_pid;        /* See if sucide should be attempt  */
  121. #endif /* PIDCHECK */
  122.  
  123. char hostname[SLEN],            /* name of machine we're on         */
  124.      hostdomain[SLEN];          /* name of domain we're in          */
  125.  
  126. #ifdef BSD
  127. extern int errno;
  128. #endif
  129.  
  130. main(argc, argv)
  131. int argc;
  132. char *argv[];
  133. {
  134.     extern char *optarg;
  135.     extern int   optind;
  136.     char *ptr;
  137.     int c, i, done;
  138.     long lastsize,
  139.          newsize;            /* file size for comparison..      */
  140.  
  141. #ifdef HOSTCOMPILED
  142.     strncpy(hostname, HOSTNAME, sizeof(hostname));
  143. #else
  144.     gethostname(hostname, sizeof(hostname));
  145. #endif
  146.     gethostdomain(hostdomain, sizeof(hostdomain));
  147.  
  148. #ifdef PIDCHECK                /* This will get the pid that         */
  149.     parent_pid = getppid();        /* started the program, ie: /bin/sh   */
  150.                     /* If it dies for some reason (logout)*/
  151. #endif /* PIDCHECK */            /* Then exit the program if PIDCHECK  */
  152.  
  153.     interval_time = DEFAULT_INTERVAL;
  154.  
  155.     /** let's see if the first character of the basename of the
  156.         command invoked is a 'w' (e.g. have we been called as
  157.         'wnewmail' rather than just 'newmail'?)
  158.     **/
  159.  
  160.     for (i=0, ptr=(argv[0] + strlen(argv[0])-1); !i && ptr > argv[0]; ptr--)
  161.       if (*ptr == '/') {
  162.         in_window = (*(ptr+1) == 'w');
  163.         i++;
  164.       }
  165.  
  166.     if (ptr == argv[0] && i == 0 && argv[0][0] == 'w')
  167.       in_window = 1;
  168.  
  169.     while ((c = getopt(argc, argv, "di:w")) != EOF) {
  170.       switch (c) {
  171.         case 'd' : debug++;                    break;
  172.         case 'i' : interval_time = atoi(optarg);        break;
  173.         case 'w' : in_window = 1;                break;
  174.         default  : usage(argv[0]);                exit(1);
  175.      }
  176.     }
  177.  
  178.     if (interval_time < 10)
  179.       fprintf(stderr,
  180. "Warning: interval set to %d second%s.  I hope you know what you're doing!\n",
  181.       interval_time, interval_time == 1 ? "" : "s");
  182.  
  183.     /* now let's parse the foldernames, if any are given */
  184.  
  185.     if (optind >= argc) /* get default */
  186.       add_default_folder();
  187.     else {
  188.       while (optind < argc)
  189.         add_folder(argv[optind++]);
  190.       pad_prefixes();            /* for nice output...*/
  191.     }
  192.  
  193. #ifdef AUTO_BACKGROUND
  194.     if (! in_window) {
  195.       if (fork())        /* automatically puts this task in background! */
  196.         exit(0);
  197.  
  198.       (void) signal(SIGINT, SIG_IGN);
  199.       (void) signal(SIGQUIT, SIG_IGN);
  200.     }
  201. #endif
  202.     (void) signal(SIGHUP, SIG_DFL);
  203.  
  204.     if (in_window && ! debug)
  205.       printf("Incoming mail:\n");
  206.  
  207.     while (1) {
  208.  
  209. #ifdef PIDCHECK
  210.     if ( kill(parent_pid,0))
  211.         exit(0);
  212. #else
  213. #ifndef AUTO_BACKGROUND        /* won't work if we're nested this deep! */
  214.       if (getppid() == 1)     /* we've lost our shell! */
  215.         exit();
  216. #endif /* AUTO_BACKGROUND */
  217. #endif /* PIDCHECK */
  218.  
  219.       if (! isatty(1))    /* we're not sending output to a tty any more */
  220.          exit();
  221.  
  222.       if (debug) printf("\n----\n");
  223.  
  224.       for (i = 0; i < total_folders; i++) {
  225.  
  226.         if (debug)
  227.           printf("[checking folder #%d: %s]\n", i, folders[i].foldername);
  228.  
  229.         if (folders[i].fd == (FILE *) NULL) {
  230.  
  231.           if ((folders[i].fd = fopen(folders[i].foldername,"r")) == NULL)
  232.             if (errno == EACCES) {
  233.            fprintf(stderr, "\nPermission to monitor %s denied!\n\n",
  234.              folders[i].foldername);
  235.                sleep(5);
  236.                exit(1);
  237.             }
  238.         }
  239.  
  240.         if ((newsize = bytes(folders[i].foldername)) > 
  241.             folders[i].filesize) {    /* new mail has arrived! */
  242.  
  243.           if (debug)
  244.             printf(
  245.            "\tnew mail has arrived!  old size = %ld, new size=%ld\n",
  246.            folders[i].filesize, newsize);
  247.  
  248.           /* skip what we've read already... */
  249.  
  250.           if (fseek(folders[i].fd, folders[i].filesize, 
  251.             BEGINNING) != 0)
  252.             perror("fseek()");
  253.  
  254.           folders[i].filesize = newsize;
  255.  
  256.           /* read and display new mail! */
  257.           if (read_headers(i) && ! in_window)
  258.             printf("\n\r");
  259.         }
  260.         else if (newsize != folders[i].filesize) {    /* file SHRUNK! */
  261.  
  262.           folders[i].filesize = bytes(folders[i].foldername);
  263.           (void) fclose(folders[i].fd);    /* close it and ...         */
  264.           folders[i].fd = (FILE *) NULL;    /* let's reopen the file    */
  265.  
  266.           lastsize = folders[i].filesize;
  267.           done     = 0;
  268.  
  269.           while (! done) {
  270.             sleep(0);    /* basically gives up our CPU slice */
  271.             newsize = bytes(folders[i].foldername);
  272.             if (newsize != lastsize)
  273.               lastsize = newsize;
  274.         else
  275.               done++;
  276.           } 
  277.             
  278.           folders[i].filesize = newsize;
  279.         }
  280.       }
  281.  
  282.       sleep(interval_time);
  283.     }
  284. }
  285.  
  286. int
  287. read_headers(current_folder)
  288. int current_folder;
  289. {
  290.     /** read the headers, output as found given current_folder,
  291.         the prefix of that folder, and whether we're in a window
  292.         or not.
  293.     **/
  294.  
  295.     char buffer[SLEN], from_whom[SLEN], subject[SLEN];
  296.     register int subj = 0, in_header = 0, count = 0, priority=0;
  297. #ifdef MMDF
  298.     int newheader = 0;
  299. #endif /* MMDF */
  300.  
  301.     from_whom[0] = '\0';
  302.  
  303.     while (fgets(buffer, SLEN, folders[current_folder].fd) != NULL) {
  304. #ifdef MMDF
  305.           if (strcmp(buffer, MSG_SEPERATOR) == 0) {
  306.             newheader = !newheader;
  307.             if (newheader) {
  308. #else
  309.       if (first_word(buffer,"From ")) {
  310.         if (real_from(buffer, from_whom)) {
  311. #endif /* MMDF */
  312.           subj = 0;
  313.           priority = 0;
  314.           in_header = 1;
  315.           subject[0] ='\0';
  316.           if (in_window)
  317.             putchar((char) 007);        /* BEEP!*/
  318.           else
  319.             printf("\n\r");    /* blank lines surrounding message */
  320.  
  321.         }
  322.       }
  323.       else if (in_header) {
  324. #ifdef MMDF
  325.             if (first_word(buffer,"From "))
  326.               real_from(buffer, from_whom);
  327. #endif /* MMDF */
  328.         if (first_word(buffer,">From")) 
  329.           forwarded(buffer, from_whom); /* return address */
  330.         else if (first_word(buffer,"Subject:") ||
  331.              first_word(buffer,"Re:")) {
  332.           if (! subj++) {
  333.             remove_first_word(buffer);
  334.         strcpy(subject, buffer);
  335.           }
  336.         }
  337.         else if (first_word(buffer,"Priority:")) 
  338.           priority++;
  339.         else if (first_word(buffer,"From:")) 
  340.           parse_arpa_from(buffer, from_whom);
  341.         else if (buffer[0] == LINEFEED) {
  342.           in_header = 0;    /* in body of message! */
  343. #ifdef MMDF
  344.               if (*from_whom == '\0')
  345.                 strcpy(from_whom,getusername());
  346. #endif /* MMDF */
  347.           show_header(priority, from_whom, subject, current_folder);
  348.           count++;
  349.           from_whom[0] = '\0';
  350.         }
  351.       }
  352.     }
  353.     return(count);
  354. }
  355.  
  356. add_folder(name)
  357. char *name;
  358. {
  359.     /* add the specified folder to the list of folders...ignore any
  360.        problems we may having finding it (user could be monitoring
  361.        a mailbox that doesn't currently exist, for example)
  362.     */
  363.  
  364.     char *cp, buf[SLEN];
  365.  
  366.     if (current_folder > MAX_FOLDERS) {
  367.       fprintf(stderr,
  368.               "Sorry, but I can only keep track of %d folders.\n", MAX_FOLDERS);
  369.       exit(1);
  370.     }
  371.  
  372.     /* now let's rip off the suffix "=<string>" if it's there... */
  373.  
  374.     for (cp = name + strlen(name); cp > name+1 && *cp != '=' ; cp--)
  375.       /* just keep stepping backwards */ ;
  376.  
  377.     /* if *cp isn't pointing to the first character we'e got something! */
  378.  
  379.     if (cp > name+1) {
  380.  
  381.       *cp++ = '\0';        /* null terminate the filename & get prefix */
  382.  
  383.       if (metachar(*cp)) cp++;
  384.  
  385.       strcpy(folders[current_folder].prefix, cp);
  386.     }
  387.     else {            /* nope, let's get the basename of the file */
  388.       for (cp = name + strlen(name); cp > name && *cp != '/'; cp--)
  389.         /* backing up a bit... */ ;
  390.  
  391.       if (metachar(*cp)) cp++;
  392.       if (*cp == '/') cp++;
  393.  
  394.       strcpy(folders[current_folder].prefix, cp);
  395.     }
  396.  
  397.     /* and next let's see what kind of weird prefix chars this user
  398.        might be testing us with.  We can have '+'|'='|'%' to expand
  399.        or a file located in the incoming mail dir...
  400.     */
  401.  
  402.     if (metachar(name[0]))
  403.       expand_filename(name, folders[current_folder].foldername);
  404.     else if (access(name, 00) == -1) {
  405.       /* let's try it in the mail home directory */
  406.       sprintf(buf, "%s%s", mailhome, name);
  407.       if (access(buf, 00) != -1)         /* aha! */
  408.         strcpy(folders[current_folder].foldername, buf);
  409.       else
  410.         strcpy(folders[current_folder].foldername, name);
  411.     }
  412.     else
  413.       strcpy(folders[current_folder].foldername, name);
  414.  
  415.     /* now let's try to actually open the file descriptor and grab
  416.        a size... */
  417.  
  418.     if ((folders[current_folder].fd = 
  419.           fopen(folders[current_folder].foldername, "r")) == NULL)
  420.           if (errno == EACCES) {
  421.         fprintf(stderr, "\nPermission to monitor \"%s\" denied!\n\n",
  422.              folders[current_folder].foldername);
  423.         exit(1);
  424.       }
  425.  
  426.     folders[current_folder].filesize = 
  427.           bytes(folders[current_folder].foldername);
  428.  
  429.     /* and finally let's output what we did */
  430.  
  431.     if (debug)
  432.       printf("folder %d: \"%s\" <%s> %s, size = %ld\n",
  433.           current_folder,
  434.           folders[current_folder].foldername,
  435.           folders[current_folder].prefix,
  436.           folders[current_folder].fd == NULL? "not found" : "opened",
  437.           folders[current_folder].filesize);
  438.  
  439.     /* and increment current-folder please! */
  440.  
  441.     current_folder++;
  442.     total_folders++;
  443. }
  444.  
  445. add_default_folder()
  446. {
  447.     char    *cp;
  448.  
  449.     /* this routine will add the users home mailbox as the folder
  450.      * to monitor.  Since there'll only be one folder we'll never
  451.      * prefix it either...
  452.      *    determine mail file from environment variable if found,
  453.      *    else use password entry
  454.      */
  455.     if ((cp = getenv("MAIL")) == NULL)
  456.       sprintf(folders[0].foldername, "%s%s", mailhome, getusername());
  457.     else
  458.       strcpy(folders[0].foldername, cp);
  459.     
  460.     folders[0].fd       = fopen(folders[0].foldername, "r");
  461.     folders[0].filesize = bytes(folders[0].foldername);
  462.  
  463.     if (debug)
  464.       printf("default folder: \"%s\" <%s> %s, size = %ld\n",
  465.           folders[0].foldername,
  466.           folders[0].prefix,
  467.           folders[0].fd == NULL? "not found" : "opened",
  468.           folders[0].filesize);
  469.  
  470.     total_folders = 1;
  471. }
  472.  
  473. int
  474. real_from(buffer, who)
  475. char *buffer, *who;
  476. {
  477.     /***** returns true iff 's' has the seven 'from' fields,
  478.            initializing the who to the sender *****/
  479.  
  480.     char junk[SLEN], who_tmp[SLEN];
  481.  
  482.     junk[0] = '\0';
  483.     who_tmp[0] = '\0';
  484.  
  485.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  486.             who_tmp, junk);
  487.  
  488.     if (junk[0] != '\0')
  489.         strcpy(who, who_tmp);
  490.  
  491.     return(junk[0] != '\0');
  492. }
  493.  
  494. forwarded(buffer, who)
  495. char *buffer, *who;
  496. {
  497.     /** change 'from' and date fields to reflect the ORIGINATOR of 
  498.         the message by iteratively parsing the >From fields... **/
  499.  
  500.     char machine[SLEN], buff[SLEN];
  501.  
  502.     machine[0] = '\0';
  503.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %*s %s",
  504.                 who, machine);
  505.  
  506.     if(machine[0] == '\0')    /* try for address with timezone in date */
  507.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  508.                 who, machine);
  509.  
  510.     if (machine[0] == '\0') /* try for srm address */
  511.       sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  512.                 who, machine);
  513.  
  514.     if (machine[0] == '\0')
  515.       sprintf(buff,"anonymous");
  516.     else
  517.       sprintf(buff,"%s!%s", machine, who);
  518.  
  519.     strncpy(who, buff, SLEN);
  520. }
  521.  
  522.  
  523. remove_first_word(string)
  524. char *string;
  525. {    /** removes first word of string, ie up to first non-white space
  526.         following a white space! **/
  527.  
  528.     register int loc;
  529.  
  530.     for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  531.         ;
  532.  
  533.     while (string[loc] == ' ' || string[loc] == '\t')
  534.       loc++;
  535.     
  536.     move_left(string, loc);
  537. }
  538.  
  539. move_left(string, chars)
  540. char string[];
  541. int  chars;
  542. {
  543.     /** moves string chars characters to the left DESTRUCTIVELY **/
  544.  
  545.     register int i;
  546.  
  547.     chars--; /* index starting at zero! */
  548.  
  549.     for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  550.       string[i-chars] = string[i];
  551.  
  552.     string[i-chars] = '\0';
  553. }
  554.  
  555. show_header(priority, from, subject, current_folder)
  556. int   priority;
  557. char *from, *subject;
  558. int   current_folder;
  559. {
  560.     /** output header in clean format, including abbreviation
  561.         of return address if more than one machine name is
  562.         contained within it! **/
  563.     char buffer[SLEN];
  564.     int  loc, i=0, exc=0, len;
  565.  
  566. #ifndef INTERNET
  567.     /* Remove bogus "@host.domain" string. */
  568.  
  569.     sprintf(buffer, "@%s%s", hostname, hostdomain);
  570.  
  571.     if (chloc(from, '!') != -1 && in_string(from, buffer))
  572.       from[strlen(from) - strlen(buffer)] = '\0';
  573. #endif
  574.  
  575.     loc = strlen(from);
  576.  
  577.     while (exc < 2 && loc > 0)
  578.       if (from[--loc] == '!')
  579.         exc++;
  580.  
  581.     if (exc == 2) { /* lots of machine names!  Get last one */
  582.       loc++;
  583.       len = strlen(from);
  584.       while (loc < len && loc < SLEN)
  585.         buffer[i++] = from[loc++];
  586.       buffer[i] = '\0';
  587.       strcpy(from, buffer);
  588.     }
  589.  
  590.     if (strlen(subject) < 2)
  591.       strcpy(subject, NO_SUBJECT);
  592.     
  593.     if (in_window)
  594.       if (total_folders > 1)
  595.         printf("%s: %s%s -- %s\n",
  596.            folders[current_folder].prefix,
  597.            priority? "Priority " : "", from, subject);
  598.       else
  599.         printf("%s%s -- %s\n",
  600.            priority? "Priority " : "", from, subject);
  601.     else
  602.       if (total_folders > 1)
  603.         printf(">> %s: %sail from %s - %s\n\r", 
  604.           folders[current_folder].prefix,
  605.           priority? "Priority m" : "M", from, subject);
  606.       else
  607.         printf(">> %sail from %s - %s\n\r", 
  608.           priority? "Priority m" : "M", from, subject);
  609. }    
  610.  
  611. parse_arpa_from(buffer, newfrom)
  612. char *buffer, *newfrom;
  613. {
  614.     /** try to parse the 'From:' line given... It can be in one of
  615.         three formats:
  616.         From: Dave Taylor <hpcnou!dat>
  617.         or  From: hpcnou!dat (Dave Taylor)
  618.         or  From: hpcnou!dat
  619.         Change 'newfrom' ONLY if sucessfully parsed this entry and
  620.         the resulting name is non-null! 
  621.     **/
  622.  
  623.     char temp_buffer[SLEN], *temp;
  624.     register int i, j = 0, in_parens;
  625.  
  626.     temp = (char *) temp_buffer;
  627.     temp[0] = '\0';
  628.  
  629.     no_ret(buffer);        /* blow away '\n' char! */
  630.  
  631.     if (lastch(buffer) == '>') {
  632.       for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  633.            buffer[i] != '('; i++)
  634.         temp[j++] = buffer[i];
  635.       temp[j] = '\0';
  636.     }
  637.     else if (lastch(buffer) == ')') {
  638.       in_parens = 1;
  639.       for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '<'; i--) {
  640.         switch(buffer[i]) {
  641.         case ')':    in_parens++;
  642.             break;
  643.         case '(':    in_parens--;
  644.             break;
  645.         }
  646.         if(!in_parens) break;
  647.         temp[j++] = buffer[i];
  648.       }
  649.       temp[j] = '\0';
  650.       reverse(temp);
  651.     }
  652.     else
  653.     /* Unusual to have address like -  From: hpcnou!dat
  654.      * but valid */
  655.     {
  656.       for (i=strlen("From: "); buffer[i] != '\0'; i++)
  657.         temp[j++] = buffer[i];
  658.       temp[j] = '\0';
  659.     }        
  660.     
  661.     if (strlen(temp) > 0) {        /* mess with buffer... */
  662.  
  663.       /* remove leading spaces... */
  664.  
  665.       while (whitespace(temp[0]))
  666.         temp = (char *) (temp + 1);        /* increment address! */
  667.  
  668.       /* remove trailing spaces... */
  669.  
  670.       i = strlen(temp) - 1;
  671.  
  672.       while (whitespace(temp[i]))
  673.        temp[i--] = '\0';
  674.  
  675.       /* if anything is left, let's change 'from' value! */
  676.  
  677.       if (strlen(temp) > 0)
  678.         strcpy(newfrom, temp);
  679.     }
  680. }
  681.  
  682. reverse(string)
  683. char *string;
  684. {
  685.     /** reverse string... pretty trivial routine, actually! **/
  686.  
  687.     char buffer[SLEN];
  688.     register int i, j = 0;
  689.  
  690.     for (i = strlen(string)-1; i >= 0; i--)
  691.       buffer[j++] = string[i];
  692.  
  693.     buffer[j] = '\0';
  694.  
  695.     strcpy(string, buffer);
  696. }
  697.  
  698. long
  699. bytes(name)
  700. char *name;
  701. {
  702.     /** return the number of bytes in the specified file.  This
  703.         is to check to see if new mail has arrived....  **/
  704.  
  705.     int ok = 1;
  706.     extern int errno;    /* system error number! */
  707.     struct stat buffer;
  708.  
  709.     if (stat(name, &buffer) != 0)
  710.       if (errno != 2) {
  711.         fprintf(stderr,"Error %d attempting fstat on %s", errno, name);
  712.         exit(1);
  713.       }
  714.       else
  715.         ok = 0;
  716.     
  717.     return(ok ? buffer.st_size : 0);
  718. }
  719.  
  720. char  *getusername()
  721. {
  722.     /** Getting the username on some systems is a real pain, so...
  723.        This routine is guaranteed to return a usable username **/
  724.  
  725.     char *return_value, *getlogin(), *cuserid();
  726.  
  727.     if ((return_value = getlogin()) == NULL)
  728.       if ((return_value = cuserid(NULL)) == NULL) {
  729.         printf("Newmail: I can't get username!\n");
  730.         exit(1);
  731.       }
  732.  
  733.     return( (char *) return_value);
  734. }
  735.  
  736. usage(name)
  737. char *name;
  738. {
  739.     /* print a nice friendly usage message */
  740.  
  741.     fprintf(stderr, 
  742. "\nUsage: %s [-d] [-i interval] [-w] {folders}\n", name);
  743.     fprintf(stderr, "\nWhere:\n");
  744.     fprintf(stderr, "  -d\tturns on debugging output\n");
  745.     fprintf(stderr,
  746. "  -i D\tsets the interval checking time to 'D' seconds\n");
  747.     fprintf(stderr,
  748. "  -w\tforces 'window'-style output, and bypasses auto-background\n\n");
  749.     fprintf(stderr,
  750. "folders can be specified by relative or absolute path names, can be the name\n");
  751.     fprintf(stderr,
  752. "of a mailbox in the incoming mail directory to check, or can have one of the\n");
  753.     fprintf(stderr,
  754. "standard Elm mail directory prefix chars (e.g. '+', '=' or '%').\n");
  755.     fprintf(stderr,
  756. "Furthermore, any folder can have '=string' as a suffix to indicate a folder\n");
  757.     fprintf(stderr,
  758. "identifier other than the basename of the file\n\n");
  759. }
  760.  
  761.  
  762. expand_filename(name, store_space)
  763. char *name, *store_space;
  764. {
  765.     strcpy(store_space, name);
  766.     if (expand(store_space) == 0) {
  767.       fprintf(stderr,"Sorry, but I couldn't expand \"%s\"\n",name);
  768.       exit(1);
  769.     }
  770. }
  771.  
  772. pad_prefixes()
  773. {
  774.     /** This simple routine is to ensure that we have a nice
  775.         output format.  What it does is whip through the different
  776.         prefix strings we've been given, figures out the maximum
  777.         length, then space pads the other prefixes to match.
  778.     **/
  779.  
  780.     register int i, j, len = 0;
  781.  
  782.     for (i=0; i < total_folders; i++)
  783.       if (len < (j=strlen(folders[i].prefix)))
  784.         len = j;
  785.     
  786.     for (i=0; i < total_folders; i++)
  787.       for (j = strlen(folders[i].prefix); j < len; j++)
  788.         strcat(folders[i].prefix, " ");
  789. }
  790.