home *** CD-ROM | disk | FTP | other *** search
- /*
- fromwho -- 'from' with extras
-
- This is a new 'from' program. Instead of just listing who your mail is
- from, it tells you how many total messages, how many are new, and
- for each person you have mail from, tells how many messages they sent,
- how many are new, and lists the subjects of the messages.
-
- This code is public domain. I might keep updating it, or I might forget
- about it ]:) But feel free to mail comments / suggestions to me at
- jearls@data.acs.calpoly.edu
-
- Usage:
- fromwho [-l] [-s] [-n] [-f [<mailbox>]]
-
- -l Turns listing of users/subjects off.
- -s Turns listing of subjects off.
- -f Sets the mailbox to read from.
- -n List only new mail
-
- REVISION INFORMATION
-
- $Revision: 1.3 $
-
- $Author: jearls $
- $Date: 91/12/03 11:14:33 $
-
- Modification Log:
-
- $Log: fromwho.c,v $
- Revision 1.3 91/12/03 11:14:33 jearls
- PATCH3: Added `-v' option to display the version number.
-
- Revision 1.2 91/11/23 12:49:37 jearls
- PATCH2: Fixed miscellanous bugs, added '-n' option to
- PATCH2: list only new mail.
-
- Revision 1.1 91/10/19 17:05:17 jearls
- PATCH1: Added support for AIX and other systems that don't
- PATCH1: use a mail spool.
-
- Revision 1.0 91/10/19 14:40:24 jearls
- Initial revision
-
- */
-
- #include <stdio.h>
- #include <pwd.h>
- #include <utmp.h>
- #include <strings.h>
-
- #include "patchlevel.h"
-
- #ifndef MAILDIR
- #define MAILDIR "/usr/spool/mail/"
- #endif MAILDIR
-
- typedef struct {
- int msgs; int new;
- } mailinfo;
-
- typedef struct subjnode {
- char *subj;
- int new;
- struct subjnode *next;
- } subjnode;
-
- typedef struct userinfo {
- char *name;
- mailinfo info;
-
- subjnode *subjs, *lastsub;
-
- struct userinfo *next;
- } userinfo;
-
- char *strdup(char *p)
- {
- char *s = (char *)malloc(1+strlen(p));
- if (s)
- (void)strcpy(s, p);
- return(s);
- }
-
- char *strdup2(char *p, char *q)
- {
- char *s = (char *)malloc(1+strlen(p)+strlen(q));
- if (s)
- (void)strcat(strcpy(s, p), q);
- return(s);
- }
-
- /* translate MAILFILE into a real path */
- char *translate(char *mf, char *n, char *h)
- {
- int len;
- char *s, *p, *q;
-
- len = strlen(mf);
- if (*mf == '~')
- len += strlen(h) - 1;
- p = mf;
- while (p = index(p, '*')) {
- p++;
- len += strlen(n)-1;
- }
- if (s = (char *)malloc(len+1)) {
- p = s;
- if (*mf == '~') {
- while (*h)
- *(p++) = *(h++);
- mf++;
- } else
- p = s;
- while (*mf)
- if ((*p = *(mf++)) == '*') {
- q = n;
- while (*q)
- *(p++) = *(q++);
- } else
- p++;
- *p = '\0';
- }
- return(s);
- }
-
- mailinfo mailstats(FILE *f, userinfo **ui)
- {
- mailinfo *mp, mi;
- char buf[1024];
- int stat, lp;
- userinfo *p, *b, *n;
-
- mi.msgs = mi.new = 0;
-
- stat = 0;
- while (fgets(buf, 1024, f)) {
- if ((!stat) && (!strncmp(buf, "From ", 5))) {
- for (lp=0; buf[lp+5] != ' '; lp++)
- buf[lp] = buf[lp+5];
- buf[lp] = '\0';
- stat = 1;
- mi.msgs++;
- p = *ui; b = (userinfo *)NULL;
- while (p && (strcmp(buf, p->name) > 0))
- p = (b=p)->next;
- if (!p || (strcmp(buf, p->name))) {
- n = (userinfo *)malloc(sizeof(userinfo));
- n->name = strdup(buf);
- n->info.msgs = n->info.new = 0;
- n->subjs = n->lastsub = (subjnode *)NULL;
- n->next = p;
- if (b)
- b->next = n;
- else
- *ui = n;
- p = n;
- }
- mp = &(p->info);
- mp->msgs++;
- if (p->lastsub)
- p->lastsub = (p->lastsub->next = (subjnode *)malloc(sizeof(subjnode)));
- else
- p->subjs = p->lastsub = (subjnode *)malloc(sizeof(subjnode));
- p->lastsub->subj = (char *)NULL;
- p->lastsub->new = 0;
- p->lastsub->next = (subjnode *)NULL;
- }
- if ((stat) && (!strncmp(buf, "Subject:", 8)))
- if (!p->lastsub->subj) {
- buf[strlen(buf)-1] = '\0';
- p->lastsub->subj = strdup(buf+9);
- }
- if ((stat) && (!strncmp(buf, "Status:", 7))) {
- stat++;
- }
- if ((stat) && (*buf == '\n')) {
- if (stat == 1) {
- mi.new++;
- mp->new++;
- p->lastsub->new = 1;
- }
- stat = 0;
- }
- }
-
- return(mi);
- }
-
- void usage(char *name)
- {
- fprintf(stderr, "usage: %s [-l] [-s] [-n] [-f [<filename>]]\n", name);
- exit(-1);
- }
-
- int main(int argc, char **argv)
- {
- mailinfo mi;
- userinfo *ui = (userinfo *)NULL, *p;
- char *mbox, *prog, myname[9], *home;
- extern char *getenv(char *);
- int flag, listflag = 1, subjflag = 1, newflag = 0;
- int lp;
- FILE *f;
- subjnode *sp, *tp;
-
- extern int errno;
-
- /* get user name and home directory */
- f=(FILE *)fopen("/etc/utmp", "r");
- if (f==(FILE *)NULL) {
- perror("Can't open /etc/utmp");
- exit(1);
- }
- fseek(f, 8+sizeof(struct utmp)*ttyslot(), 0);
- myname[8]='\0';
- if (fread(myname, 8, 1, f) < 8) {
- if (!(home = getenv("USER")))
- if (!(home = getenv("USERNAME")))
- if (!(home = getenv("LOGNAME"))) {
- fprintf(stderr, "%s: Who are you?\n", *argv);
- exit(1);
- }
- (void)strcpy(myname, home);
- }
- fclose(f);
-
- if (getpwnam(myname))
- home = strdup(getpwnam(myname)->pw_dir);
- else
- fprintf(stderr, "%s: Who are you?\n", *argv);
-
- #ifdef MAILFILE
- mbox = translate(MAILFILE, myname, home);
- #else
- mbox = strdup2(MAILDIR, myname);
- #endif
-
- /* parse arguments */
- prog = *argv;
- while ((--argc) && (**(++argv) == '-')) {
- switch(*(*argv+1)) {
- case 'f' : (void)free(mbox);
- if (--argc)
- mbox = strdup(*(++argv));
- else {
- mbox = strdup2(home, "/mbox");
- argc++;
- }
- break;
- case 's' : subjflag = 0;
- break;
- case 'l' : listflag = 0;
- break;
- case 'n' : newflag = 1;
- break;
- case 'v' : puts("fromwho, by johnson earls. $Revision: 1.3 $");
- exit(0);
- default : free(home);
- free(mbox);
- usage(prog);
- }
- }
-
- /* open the file */
- f = (FILE *)fopen(mbox, "r");
- if (f == (FILE *)NULL) {
- perror(mbox);
- free(home);
- free(mbox);
- exit(errno);
- }
-
- /* get the info */
- mi = mailstats(f, &ui);
-
- (void)fclose(f);
-
- /* print everything out */
- if (newflag)
- printf("%s contains %d new messages.\n", mbox, mi.new);
- else
- printf("%s contains %d messages, %d new.\n", mbox, mi.msgs, mi.new);
- while (ui) {
- if (listflag && (!newflag || ui->info.new))
- if (newflag)
- printf(" %-36s: %d new messages.\n", ui->name, ui->info.new);
- else
- printf(" %-36s: %d messages, %d new.\n", ui->name, ui->info.msgs, ui->info.new);
- for (sp = ui->subjs; sp; ) {
- if (sp->subj) {
- if (listflag && subjflag)
- if (sp->new || !newflag)
- printf(" %c %s\n", (sp->new ? '>' : ' '), sp->subj);
- free(sp->subj);
- } else
- if (listflag && subjflag)
- if (sp->new || !newflag)
- printf(" %c <none>\n", (sp->new ? '>' : ' '));
- sp = (tp=sp) -> next;
- free(tp);
- }
- ui = (p=ui)->next;
- free(p->name);
- free(p);
- }
-
- free(home);
- free(mbox);
-
- exit(0);
- }
-