home *** CD-ROM | disk | FTP | other *** search
- /* newmail(1L), check for new, unread, and total mail messages */
- /* Steve Creps, October 24, 1988 */
- /* Last modified, July 19, 1991 */
-
- /****************************************************************/
- /* #include standard copyright notice: */
- /* This program copyright Steve Creps on the above date. Do */
- /* pretty much what you want with it; HOWEVER: */
- /* 1) Don't accept any money for it. */
- /* 2) Do leave my notices intact. */
- /* 3) Do document your changes before passing it on. */
- /****************************************************************/
-
- #ifndef lint
- static char ID[] = "Newmail, version 3.0, (c) 1991 Steve Creps";
- #endif
-
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <malloc.h>
-
- #define Fprintf (void)fprintf
- #define Printf (void)printf
- #define NEW 1
- #define UNREAD 2
- #define OLD 3
- #define DEF_INTERVAL 30 /* Default sleep time between checks */
- #define MIN_INTERVAL 5 /* Min must be > 0 */
- #ifdef BSD
- #define MAILDIR "/usr/spool/mail"
- #define ENV_USER "USER"
- #else
- #define MAILDIR "/usr/mail"
- #define ENV_USER "LOGNAME"
- #endif
-
- int optn = 0, optt = 0, optv = 1, opti = 0, optd = 0;
- int optb = 0;
- int ncount, ucount, tcount, old_ncount = -1;
- int nextmsg(), type;
-
- char *getenv(), *getln();
- int getopt();
- unsigned int sleep();
- void exit();
- extern int opterr, optind;
- extern char *optarg;
- pid_t fork(), getpid();
-
- int
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char *mailfile;
- int c;
- FILE *mailfp;
- pid_t child_id = 0;
-
- opterr = 0;
- while ((c = getopt(argc, argv, "bdi:nstv")) != EOF) {
- switch (c) {
- case 'b':
- optb = 1;
- break;
-
- case 'd':
- optd = optn = 1;
- opti = DEF_INTERVAL;
- break;
-
- case 'i':
- if ((opti = atoi(optarg)) < MIN_INTERVAL) {
- Fprintf(stderr,
- "newmail: time interval is too small\n");
- exit(-1);
- }
- break;
-
- case 'n':
- optn = 1;
- optt = 0;
- break;
-
- case 's':
- optt = optv = 0;
- break;
-
- case 't':
- optt = 1;
- optn = optv = 0;
- break;
-
- case 'v':
- optv = 1;
- optt = 0;
- break;
-
- case '?':
- Fprintf(stderr, "newmail: invalid option: %s\n",
- argv[optind - 1]);
- exit(-1);
- }
- }
-
- if (argc > optind + 1) {
- Fprintf(stderr, "Usage: newmail [ -b -d -i interval -n -s -t -v ] [ mailbox ]\n");
- exit(-1);
- }
-
- if (optd == 0 || (child_id = fork()) == 0) {
- if (optd && child_id == 0) {
- Printf("newmail daemon started, pid == %d\n", getpid());
- }
-
- if (argc == optind) {
- char *u = getenv(ENV_USER);
- mailfile = (char *)malloc(sizeof(MAILDIR) + sizeof("/") +
- sizeof(u) + 1);
- (void)sprintf(mailfile, "%s/%s", MAILDIR, u);
- } else {
- #ifdef SYSV
- mailfile = strdup(argv[optind]);
- #else
- /* No strdup() on Ultrix; sigh. Don't try to free this below. */
- mailfile = argv[optind];
- #endif
- }
-
- do {
- ncount = ucount = tcount = 0;
- if ((mailfp = fopen(mailfile, "r")) == NULL) {
- if (errno != ENOENT || argc > optind) {
- Fprintf(stderr, "newmail: cannot open %s\n",
- mailfile);
- return -1;
- }
- } else {
- while (type = nextmsg(mailfp)) {
- switch (type) {
- case NEW:
- ncount++;
-
- case UNREAD:
- ucount++;
-
- case OLD:
- tcount++;
- break;
-
- default:
- continue;
- }
- }
- }
-
- if (ncount > old_ncount) {
- if (optv) {
- if (optb && ncount > 0) putchar(0x07);
- if (tcount == 0) {
- if (!optn) Printf("%s: no messages.\n",
- mailfile);
- } else {
- Printf("%s: ", mailfile);
- if (ncount) Printf("%d new, ", ncount);
- if (ucount && ucount != ncount)
- Printf("%d unread, ", ucount);
- Printf("%d message%s total.\n", tcount,
- tcount > 1 ? "s" : "");
- }
- } else if (optt)
- Printf("%d\t%d\t%d\n", ncount, ucount, tcount);
- }
- old_ncount = ncount;
- (void)fclose(mailfp);
- #ifdef BSD
- if (opti > 0) (void)sleep((unsigned)opti);
- #else
- if (opti > 0) (void)sleep((unsigned long)opti);
- #endif
- } while (opti > 0);
- }
- #ifdef SYSV
- /* Just to be neat. See comment after strdup() above. */
- free((void *)mailfile);
- #endif
-
- return optd > 0 ? child_id : ncount;
- }
-
- #define MAXLEN 12 /* we're discarding most of the end of the line */
- static char line[MAXLEN] = NULL;
-
- int
- nextmsg(fp)
- FILE *fp;
- {
- int mtype = NEW, past_header = 0;
- while (strncmp(line, "From ", 5) != 0)
- if (getln(fp, line, MAXLEN) == NULL) return 0;
- do {
- if (strlen(line) == 1) {
- past_header++;
- while (strlen(line) == 1)
- (void)getln(fp, line, MAXLEN);
- if (strncmp(line, "From ", 5) == 0) {
- return mtype;
- }
- }
- if (strncmp(line, "Status: O", 9) == 0) {
- if (!past_header) mtype = UNREAD;
- continue;
- }
- if (strncmp(line, "Status: RO", 10) == 0) {
- if (!past_header) mtype = OLD;
- continue;
- }
- } while (getln(fp, line, MAXLEN));
-
- return mtype;
- }
-
- /* Read a line from given stream, return in line. If line is too */
- /* long, truncate and read past next \n. Terminate with (char)0. */
- char *
- getln(fp, msgline, maxlen)
- FILE *fp;
- char msgline[];
- int maxlen;
- {
- int i, maxc = maxlen - 2;
- char c;
- for (i = 0; i < maxc && (msgline[i] = getc(fp)) != '\n'; i++) {
- if ((int)msgline[i] == EOF) {
- msgline[0] = (char)0;
- return NULL;
- }
- }
-
- if (i == maxc) {
- msgline[maxc++] = '\n';
- msgline[maxc] = (char)0;
- while ((c = getc(fp)) != '\n') {
- if ((int)c == EOF) {
- msgline[0] = (char)0;
- return NULL;
- }
- }
- } else {
- msgline[i++] = '\n';
- msgline[i] = (char)0;
- }
-
- return msgline;
- }
-