checkmail program
devine at asgb.UUCP
devine at asgb.UUCP
Tue Nov 20 04:54:23 AEST 1984
Here is a little program that I have used for a while and thought
other folks may want to use. The idea came from Brian Kernighan and
Rob Pike's book "The Unix Programming Environment". They gave a
little program that checked for a growing mailbox. The assumption
is that a larger mailbox means that one (or more) message have been
appended to it since the last time its size was checked.
It was fine for the simple case. However, if you are reading mail
when a new message comes in and you delete an existing message, there
is no way to determine if a new message arrived by size checking alone.
I've also added all sorts of bells and whistles to the original.
In the latest incarnation of 'checkail' it will asynchronously tell
you when mail has arrived, giving the sender's name and the 'Subject:'
line, if any. BUT, if you don't like it breaking through when you are editing,
you'll have to modify it to wait with a message (some suggestions are setting
the eXecute bit for your TTY line or using a LCK.TERM file to mean
"don't bother me with mail now!").
Environment stuff: I use it for System V.2 Unix, it MAY still work
for BSD Unixes -- it has been modified greatly since it last ran on 4.1.
There are #ifdef BSD sections included. Run 'checkmail' in the background.
Use the command sh -c "checkmail &" if you don't like the process number to
be displayed. For BSD, you will have to kill the process when you logout,
so keep that PID or just make sure that it is the first job and kill it
using %1. If you are worried about everyone running their own copy or
checkmail and gobbling up needed process slots, change it to run like 'biff'
to check everyone's mailbox who wants it done (exercise left to the reader...).
One more thing, change the NOISE string to whatever you want to be
bothered by. Postnews will probably chew up the current string "escape#>".
Bob Devine Burroughs-ASG {sdcsvax || sdcrdcf}!bmcg!asgb!moloch!devine
---------------- cut ------ here ------------------------
/* checkmail : program to watch a user's mailbox */
/* Oct. 84 Bob Devine */
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <time.h>
#ifdef BSD
#include <sys/timeb.h>
#endif
#include <sys/stat.h>
#define WHO_LENGTH 15 /* assume max user_name is 15 chars (safe)*/
#ifdef BSD
#define POST_OFFICE "/usr/spool/mail"
#else
#define POST_OFFICE "/usr/mail"
#endif
/**** GLOBAL VARIABLES ****/
unsigned char line[512]; /* working space throughout program */
char *prog_name; /* what this program is called */
struct tm * prev_tm;
FILE *outfile, *mailfp;
char *NOISE = "#>"; /* vt100 style keyclick --
-- should use BEL from terminfo/cap */
main (argc, argv)
char **argv;
{
struct stat mail_box; /* the user's mailbox */
struct tm temp_tm; /* used at program start up */
char *user_name;
char *getlogin(); /* used for finding correct mailbox */
long last_time_checked;
long time();
int last_size, snooze_amount;
prog_name = argv[0];
if ((outfile = fopen("/dev/tty", "w")) == NULL)
die("error opening /dev/tty for output", (char *) 0);
if ((user_name = getlogin()) == NULL) /* find out who is running this */
die("can't get your login name", (char *) 0);
if (chdir(POST_OFFICE) == -1)
die("can't cd to %s", POST_OFFICE);
prev_tm = &temp_tm; /* start with it zeroed out */
#ifdef BSD
/* ignore the TOSTOP signal for running in background */
signal(SIGTTOU, SIG_IGN);
#endif
while (1) /* run until gets [kill, intr, hup, ETC] sig) */
{
while (stat(user_name, &mail_box) == -1) /* no mailbox found */
if (errno == ENOENT)
sleep(300); /* wait 5 min & try again */
else
die("error with the mail file", (char *) 0);
if ((mailfp = fopen(user_name, "r")) == NULL)
die("error opening mail file for read\n", (char *) 0);
/* Any new mail? */
if (mail_box.st_size != last_size)
{
/* examine EVERY message to see if it is new */
lseek(fileno(mailfp), 0L, 0);
check_for_new_msgs();
}
fclose(mailfp);
last_size = mail_box.st_size;
time(&last_time_checked);
prev_tm = localtime(&last_time_checked);
/* sleep until the 'top-of-the-minute' */
snooze_amount = 59 - prev_tm->tm_sec;
if (snooze_amount < 20) /* for efficiency sake && */
snooze_amount += 60; /* avoiding sleeps of zero */
sleep(snooze_amount);
}
}
/* has_a : tells if the 'string' has 'word' at beginning */
has_a(word, string)
register char *word, *string;
{
while(*word)
if (*word++ != *string++) return(0);
return(1);
}
/* is_a_new_msg : check the From line for the date (kludge, kludge) */
is_a_new_msg(from_line)
char *from_line;
{
register char *p;
int day, hour, min;
/* the date has format "Mon Oct 8 10:48 1984" */
for (p = from_line+12; *p!=':' && *p!='\0'; p++) ;
if (! *p) return(0); /* if colon not found, assume old mesg */
p = p - 5; /* back into the DAY field */
day=0;
if (*p >= '\060') /* ignore if blank */
day = ((int) *p - 060);
p++;
day = day * 10 + ((int) *p - 060); p = p + 2;
hour = ((int) *p++ - 060) * 10 + ((int) *p - 060); p = p + 2;
min = ((int) *p++ - 060) * 10 + ((int) *p - 060);
/* check to see if this message is older than the last time checked */
/* NOTE: best resolution is 1 min */
if ((min >= prev_tm->tm_min) && (hour == prev_tm->tm_hour))
return(1);
if ((hour > prev_tm->tm_hour) && (day == prev_tm->tm_mday))
return(1);
if (day > prev_tm->tm_mday) /* if program is run after midnight */
return(1); /*-- or program has just started */
return(0);
}
check_for_new_msgs()
{
int i; /* loop variable */
char who_sent[WHO_LENGTH];
while (fgets(line, sizeof(line), mailfp) != NULL)
if (has_a("From ", line))
if (is_a_new_msg(line))
{
int count = 0;
for (i=0; i < WHO_LENGTH; i++)
if ((who_sent[i] = line[i+5]) == ' ') break;
who_sent[i] = '\0';
fprintf(outfile, "\n New mail from %s - ", who_sent);
fgets(line, sizeof(line), mailfp); /* eat 'To' line */
fgets(line, sizeof(line), mailfp); /* subject line? */
while ((count < 4) && (! has_a("Subject: ", line)))
{
fgets(line, sizeof(line), mailfp);
count++;
}
if (has_a("Subject: ", line))
fprintf(outfile, "%s%s", line, NOISE);
else
fprintf(outfile, "(no subject)%s\n", NOISE);
fflush(outfile);
}
}
/* die : print error message and die */
die(s1, s2)
char *s1, *s2;
{
extern int errno, sys_nerr;
extern char *sys_errlist[], *prog_name;
if (prog_name) fprintf(stderr, "%s: ", prog_name);
(void)fprintf(stderr, s1, s2);
if (errno > 0 && errno < sys_nerr)
fprintf(stderr, " (%s)", sys_errlist[errno]);
(void)fprintf(stderr, "\n");
exit(1);
}
More information about the Comp.sources.unix
mailing list