From 64ba6ef391d3d3101f66b665e2330ce5f192c0fd Mon Sep 17 00:00:00 2001 From: "C. Anthony DellaFera" Date: Tue, 21 Jul 1987 10:43:39 +0000 Subject: Initial revision --- clients/zmailnotify/zmailwatch.c | 690 +++++++++++++++++++++++++++++++++++++++ clients/zmailnotify/zmwnotify.c | 301 +++++++++++++++++ 2 files changed, 991 insertions(+) create mode 100644 clients/zmailnotify/zmailwatch.c create mode 100644 clients/zmailnotify/zmwnotify.c (limited to 'clients/zmailnotify') diff --git a/clients/zmailnotify/zmailwatch.c b/clients/zmailnotify/zmailwatch.c new file mode 100644 index 0000000..dfb629e --- /dev/null +++ b/clients/zmailnotify/zmailwatch.c @@ -0,0 +1,690 @@ +/* + * $Source$ + * $Header$ + */ + +#ifndef lint +static char *rcsid_mailwatch_c = "$Header$"; +#endif lint + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOTOK (-1) +#define OK 0 +#define DONE 1 + +int Pfd; +FILE *sfi; +FILE *sfo; +char Errmsg[128]; +FILE *logf; + +static int debug = 0; +static int Shutdown = 0; + +struct mailsav { + struct iovec m_iov[3]; + int m_iovcnt; + int m_seen; +} *Mailsav[64]; + +int MailIndex; +int MailSize; + +main() +{ + char *host; + char *user; + char *display; + register int xs; + register int xsmask; + int readfds; + struct timeval timeout; + register int curtime; + register int i; + char *getenv(); + int cleanup(); + + user = getenv("USER"); + host = getenv("MAILHOST"); + display = getenv("DISPLAY"); + if (user == NULL) + fatal("no USER defined"); + if (host == NULL) + fatal("no MAILHOST defined"); + if (display == NULL) + fatal("no DISPLAY defined"); + + if (!debug) background(); + + logf = fopen("/usr/adm/mailwatch.log", "a"); + setlinebuf(logf); + log("startup"); + xs = XNotifyInit(display); + xsmask = (1 << xs); + timeout.tv_usec = 0; + + signal(SIGHUP, cleanup); + signal(SIGTERM, cleanup); + + check_mail(host, user); + XDisplayNewWindows(); + i = 59 - (time(0) % 60); + timeout.tv_sec = i; + while (1) + { + readfds = xsmask; + if (select(xs+1, &readfds, 0, 0, &timeout) > 0) + { + if (readfds & xsmask) + { + XProcessEvent(); + display_unseen(); + XDisplayNewWindows(); + } + } + else + { + check_mail(host, user); + XDisplayNewWindows(); + } + if (Shutdown) + { + log("shutdown"); + fclose(logf); + XNotifyClose(); + exit(0); + } + i = 60 - (time(0) % 60); + timeout.tv_sec = i; + } +} + +background() +{ + register int i; + + if (fork()) exit(0); + for (i = 0; i < 10; i++) close(i); + open("/", 0); + dup2(0, 1); + dup2(0, 2); + i = open("/dev/tty", 2); + if (i >= 0) + { + ioctl(i, TIOCNOTTY, 0); + close(i); + } +} + +check_mail(host, user) + char *host; + char *user; +{ + static int LastNmsgs = -1; + static int LastNbytes = -1; + int nmsgs; + int nbytes; + static char tempname[40]; + static FILE *mbf = NULL; + register int mbfi; + register int i; + register int next_msg; + struct mailsav *ms; + struct mailsav *build_mailsav(); + + if (pop_init(host) == NOTOK) + { + log("pop_init: %s", Errmsg); + error(Errmsg); + return(1); + } + + if (pop_command("USER %s", user) == NOTOK || + pop_command("RPOP %s", user) == NOTOK) + { + error(Errmsg); + log("USER|RPOP: %s", Errmsg); + pop_command("QUIT"); + pop_close(); + return(1); + } + + if (pop_stat(&nmsgs, &nbytes) == NOTOK) + { + error(Errmsg); + log("pop_stat: %s", Errmsg); + pop_command("QUIT"); + pop_close(); + return(1); + } + + if (nmsgs == 0) + { + pop_command("QUIT"); + pop_close(); + return(0); + } + + if (mbf == NULL) + { + strcpy(tempname, "/tmp/pmXXXXXX"); + mbfi = mkstemp(tempname); + if (mbfi < 0) + { + log("mkstemp"); + pop_command("QUIT"); + pop_close(); + return(1); + } + mbf = fdopen(mbfi, "w+"); + } + + next_msg = 1; + if (nmsgs == LastNmsgs && nbytes == LastNbytes) + { + if (get_message(1, mbf) != 0) return(1); + ms = build_mailsav(mbf); + if (mail_compare(ms, Mailsav[0]) == 0) + { + pop_command("QUIT"); + pop_close(); + return(0); + } + else + { + display_mail_header(ms, 0); + rewind(mbf); + next_msg = 2; + } + } + + for (i = next_msg; i <= nmsgs; i++) + { + if (get_message(i, mbf) != 0) return(1); + ms = build_mailsav(mbf); + display_mail_header(ms, i-1); + rewind(mbf); + } + + LastNmsgs = nmsgs; + LastNbytes = nbytes; + + pop_command("QUIT"); + pop_close(); + if (Shutdown) + { + fclose(mbf); + unlink(tempname); + } + + return(0); +} + +cleanup() +{ + Shutdown = 1; +} + +get_message(i, mbf) + int i; + FILE *mbf; +{ + int mbx_write(); + + if (pop_retr(i, mbx_write, mbf) != OK) + { + error(Errmsg); + log("pop_retr: %s", Errmsg); + pop_command("QUIT"); + pop_close(); + return(1); + } + ftruncate(fileno(mbf), ftell(mbf)); + return(0); +} + +free_all_mailsav() +{ + register struct mailsav **msp; + register struct mailsav *ms; + register struct iovec *iov; + register int iovcnt; + + for (msp = Mailsav; ms = *msp; msp++) { + iov = ms->m_iov; + iovcnt = ms->m_iovcnt; + while (--iovcnt >= 0) { + free(iov->iov_base); + iov++; + } + free(ms); + *msp = NULL; + } +} + +free_mailsav(ms) +register struct mailsav *ms; +{ + register struct iovec *iov; + register int iovcnt; + + iov = ms->m_iov; + iovcnt = ms->m_iovcnt; + while (--iovcnt >= 0) { + free(iov->iov_base); + iov++; + } + free(ms); +} + +pop_init(host) +char *host; +{ + static struct hostent *hp = NULL; + static struct servent *sp = NULL; + static struct sockaddr_in sin; + static int initialized = 0; + int lport = IPPORT_RESERVED - 1; + char response[128]; + char *get_errmsg(); + + if (!initialized) { + + hp = gethostbyname(host); + if (hp == NULL) { + sprintf(Errmsg, "MAILHOST unknown: %s", host); + return(NOTOK); + } + + sp = getservbyname("pop", "tcp"); + if (sp == 0) { + strcpy(Errmsg, "tcp/pop: unknown service"); + return(NOTOK); + } + + sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); + sin.sin_port = sp->s_port; + + initialized = 1; + } + + Pfd = rresvport(&lport); + if (Pfd < 0) { + sprintf(Errmsg, "error creating socket: %s", get_errmsg()); + return(NOTOK); + } + + if (connect(Pfd, (char *)&sin, sizeof sin) < 0) { + sprintf(Errmsg, "error during connect: %s", get_errmsg()); + close(Pfd); + return(NOTOK); + } + + sfi = fdopen(Pfd, "r"); + sfo = fdopen(Pfd, "w"); + if (sfi == NULL || sfo == NULL) { + sprintf(Errmsg, "error in fdopen: %s", get_errmsg()); + close(Pfd); + return(NOTOK); + } + + if (getline(response, sizeof response, sfi) != OK || (*response != '+')) { + strcpy(Errmsg, response); + return(NOTOK); + } + + return(OK); +} + +pop_close() +{ + if (sfi != NULL) fclose(sfi); + if (sfi != NULL) fclose(sfo); + close(Pfd); +} + +pop_command(fmt, a, b, c, d) +char *fmt; +{ + char buf[128]; + + sprintf(buf, fmt, a, b, c, d); + + if (debug) fprintf(stderr, "---> %s\n", buf); + if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + + if (debug) fprintf(stderr, "<--- %s\n", buf); + if (*buf != '+') { + strcpy(Errmsg, buf); + return(NOTOK); + } else { + return(OK); + } +} + + +pop_stat(nmsgs, nbytes) +int *nmsgs, *nbytes; +{ + char buf[128]; + + if (debug) fprintf(stderr, "---> STAT\n"); + if (putline("STAT", Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + + if (debug) fprintf(stderr, "<--- %s\n", buf); + if (*buf != '+') { + strcpy(Errmsg, buf); + return(NOTOK); + } else { + sscanf(buf, "+OK %d %d", nmsgs, nbytes); + return(OK); + } +} + +pop_retr(msgno, action, arg) +int (*action)(); +{ + char buf[128]; + int end_of_header; + + sprintf(buf, "RETR %d", msgno); + if (debug) fprintf(stderr, "%s\n", buf); + if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + + end_of_header = 0; + while (1) { + switch (multiline(buf, sizeof buf, sfi)) { + case OK: + if (!end_of_header) + { + (*action)(buf, arg); + if (*buf == 0) end_of_header = 1; + } + break; + case DONE: + return (OK); + case NOTOK: + strcpy(Errmsg, buf); + return (NOTOK); + } + } +} + +getline(buf, n, f) +char *buf; +register int n; +FILE *f; +{ + register char *p; + register int c; + + p = buf; + while (--n > 0 && (c = fgetc(f)) != EOF) + if ((*p++ = c) == '\n') break; + + if (ferror(f)) { + strcpy(buf, "error on connection"); + return (NOTOK); + } + + if (c == EOF && p == buf) { + strcpy(buf, "connection closed by foreign host"); + return (DONE); + } + + *p = NULL; + if (*--p == '\n') *p = NULL; + if (*--p == '\r') *p = NULL; + return(OK); +} + +multiline(buf, n, f) +register char *buf; +register int n; +FILE *f; +{ + if (getline(buf, n, f) != OK) return (NOTOK); + if (*buf == '.') { + if (*(buf+1) == NULL) { + return (DONE); + } else { + strcpy(buf, buf+1); + } + } + return(OK); +} + +putline(buf, err, f) +char *buf; +char *err; +FILE *f; +{ + fprintf(f, "%s\r\n", buf); + fflush(f); + if (ferror(f)) { + strcpy(err, "lost connection"); + return(NOTOK); + } + return(OK); +} + +mbx_write(line, mbf) +char *line; +FILE *mbf; +{ + fputs(line, mbf); + fputc(0x0a, mbf); +} + +struct mailsav * +build_mailsav(mbf) + register FILE *mbf; +{ + char line[128]; + char from[80]; + char to[80]; + char subj[80]; + register struct mailsav *ms; + register int i; + register char *c; + register struct iovec *iov; + + ms = (struct mailsav *)malloc(sizeof (struct mailsav)); + ms->m_seen = 0; + + from[0] = 0; + to[0] = 0; + subj[0] = 0; + + rewind(mbf); + while (fgets(line, 128, mbf) != NULL) + { + if (*line == '\n') break; + if (!strncmp(line, "From:", 5)) + strcpy(from, line); + else if (!strncmp(line, "To:", 3)) + strcpy(to, line); + else if (!strncmp(line, "Subject:", 8)) + strcpy(subj, line); + } + + /* add elipsis at end of "To:" field if it continues onto */ + /* more than one line */ + i = strlen(to) - 2; + c = &to[i]; + if (*c++ == ',') + { + *c++ = ' '; + *c++ = '.'; + *c++ = '.'; + *c++ = '.'; + *c++ = '\n'; + *c = 0; + } + + i = 0; + if (from[0] != 0) + { + iov = &ms->m_iov[i]; + iov->iov_len = strlen(from); + iov->iov_base = (char *)malloc(iov->iov_len); + bcopy(from, iov->iov_base, iov->iov_len); + iov->iov_base[--iov->iov_len] = 0; /* remove LF */ + i++; + } + + if (to[0] != 0) + { + iov = &ms->m_iov[i]; + iov->iov_len = strlen(to); + iov->iov_base = (char *)malloc(iov->iov_len); + bcopy(to, iov->iov_base, iov->iov_len); + iov->iov_base[--iov->iov_len] = 0; /* remove LF */ + i++; + } + + if (subj[0] != 0) + { + iov = &ms->m_iov[i]; + iov->iov_len = strlen(subj); + iov->iov_base = (char *)malloc(iov->iov_len); + bcopy(subj, iov->iov_base, iov->iov_len); + iov->iov_base[--iov->iov_len] = 0; /* remove LF */ + i++; + } + + ms->m_iovcnt = i; + return(ms); +} + +display_mail_header(ms, mi) + register struct mailsav *ms; + register int mi; +{ + /* This is a little tricky. If the current mail number (mi) is greater */ + /* than the last saved mail index (MailIndex), then this is new mail and */ + /* mi = MailIndex + 1. (MailIndex is incremented each time new mail is */ + /* saved.) Similarly, if mi is less than or equal to MailIndex and the */ + /* mail is different, then it is new mail, and MailIndex is set back to */ + /* mi. */ + + if (mi > MailIndex || mail_compare(ms, Mailsav[mi])) + { + if (Mailsav[mi] != NULL) free_mailsav(Mailsav[mi]); + MailIndex = mi; + Mailsav[mi] = ms; + log("new mail"); + } + else + { + free_mailsav(ms); + ms = Mailsav[mi]; + } + if (!ms->m_seen) + { + if (notify_user(ms->m_iov, ms->m_iovcnt) == 0) ms->m_seen = 1; + } +} + +display_unseen() +{ + register int i; + register struct mailsav *ms; + + for (i = 0; i <= MailIndex; i++) + { + ms = Mailsav[i]; + if (ms->m_seen == 0) + { + if (notify_user(ms->m_iov, ms->m_iovcnt) != 0) return; + ms->m_seen = 1; + } + } +} + +mail_compare(m1, m2) +register struct mailsav *m1, *m2; +{ + register struct iovec *iov1, *iov2; + register int iovcnt; + + if (m1->m_iovcnt != m2->m_iovcnt) return(1); + iov1 = m1->m_iov; + iov2 = m2->m_iov; + iovcnt = m1->m_iovcnt; + while (--iovcnt >= 0) { + if (strcmp(iov1->iov_base, iov2->iov_base)) return(1); + iov1++; + iov2++; + } + return(0); +} + +error(msg) +{ + fprintf(stderr, "mailwatch: %s\n"); +} + +fatal(msg) +{ + error(msg); + exit(1); +} + +char * +get_errmsg() +{ + extern int errno, sys_nerr; + extern char *sys_errlist[]; + char *s; + + if (errno < sys_nerr) + s = sys_errlist[errno]; + else + s = "unknown error"; + return(s); +} + +char *Months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +log(message, a1, a2) +char *message; +{ + struct tm *tm; + int clock; + char buf[64]; + + clock = time(0); + tm = localtime(&clock); + sprintf(buf, message, a1, a2); + fprintf(logf, "%s %2d %02d:%02d:%02d -- %s\n", + Months[tm->tm_mon], tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + buf); +} diff --git a/clients/zmailnotify/zmwnotify.c b/clients/zmailnotify/zmwnotify.c new file mode 100644 index 0000000..6395fd9 --- /dev/null +++ b/clients/zmailnotify/zmwnotify.c @@ -0,0 +1,301 @@ +/* + * $Source$ + * $Header$ + */ + +#ifndef lint +static char *rcsid_mwnotify_c = "$Header$"; +#endif lint + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char **environ; + +short cursor[] = {0x0000, 0x7ffe, 0x4fc2, 0x4ffe, 0x7ffe, + 0x7ffe, 0x781e, 0x7ffe , 0x7ffe, 0x0000}; + +#define NW_TOP 5 +#define DEFAULT_WINDOWS 16 +#define MAX_WINDOWS 32 + +WindowInfo Winfo; +FontInfo Finfo; +Font NoteFont; +int Timeout = 0; +int Bwidth = 2; +int Inner = 2; +int Volume = 0; +int Forepix = BlackPixel; +int Backpix = WhitePixel; +int Brdrpix = BlackPixel; +int Mouspix = BlackPixel; +int Offset = NW_TOP; +int VPos = NW_TOP; +int WindowMask = 0; +int WindowCount; +int WindowMax = DEFAULT_WINDOWS; + +struct wsav { + Window w_window; + struct iovec *w_iov; + int w_iovcnt; + int w_flags; +} Wsav[MAX_WINDOWS]; + +#define W_MAPPED 1 + +extern int errno; + +notify_user(iov, iovcnt) +register struct iovec *iov; +register int iovcnt; +{ + register int i; + register struct wsav *w; + + if (WindowCount == WindowMax) + return(1); + + w = &Wsav[WindowCount]; + w->w_flags = 0; + w->w_iov = (struct iovec *)malloc(sizeof (struct iovec) * iovcnt); + w->w_iovcnt = iovcnt; + for (i = iovcnt; --i >= 0; ) { + w->w_iov[i].iov_base = (char *)malloc(iov[i].iov_len+1); + bcopy(iov[i].iov_base, w->w_iov[i].iov_base, iov[i].iov_len+1); + w->w_iov[i].iov_len = iov[i].iov_len; + } + w->w_window = XNotifySetup(iov, iovcnt, &VPos); + WindowMask |= (1 << WindowCount); + WindowCount++; + return(0); +} + +XProcessEvent() +{ + XEvent rep; + register struct wsav *w; + register int i; + + do { + XNextEvent(&rep); + + /* find the window */ + w = Wsav; + for (i = 0; i < WindowMax; w++, i++) + if (rep.window == w->w_window) break; + if (i == WindowMax) return; + + /* process the event */ + switch (rep.type) { + case ButtonPressed: + for (; i >= 0; w--, i--) { + if (w->w_window != NULL) { + XDestroyWindow(w->w_window); + w->w_window = NULL; + free_iov(w->w_iov, w->w_iovcnt); + WindowMask &= ~(1 << i); + } + } + if (WindowMask == 0) { + VPos = Offset; + WindowCount = 0; + } + break; + + case ExposeWindow: + case ExposeRegion: + XClear(w->w_window); + display_notice(w->w_window, w->w_iov, w->w_iovcnt); + XFlush(); + break; + + } + } while (XPending() > 0); +} + +free_iov(iov, iovcnt) +register struct iovec *iov; +register int iovcnt; +{ + register struct iovec *iovbase = iov; + + while (--iovcnt >= 0) { + free(iov->iov_base); + iov++; + } + free(iovbase); +} + + +XNotifyInit(dname) +char *dname; +{ + struct passwd *pwent; + char *envbuf[2]; + char homebuf[280]; + int reverse = 0; + char *option; + char *font_name = "6x13"; + char *fore_color = NULL; + char *back_color = NULL; + char *brdr_color = NULL; + char *mous_color = NULL; + Color cdef; + char *getlogin(); + + if (!XOpenDisplay(dname)) + exit(0); + if (pwent = getpwnam(getlogin())) { + strcpy(homebuf, "HOME="); + strcat(homebuf, pwent->pw_dir); + envbuf[0] = homebuf; + envbuf[1] = NULL; + environ = envbuf; + if (option = XGetDefault("mailwatch", "BodyFont")) + font_name = option; + fore_color = XGetDefault("mailwatch", "Foreground"); + back_color = XGetDefault("mailwatch", "Background"); + brdr_color = XGetDefault("mailwatch", "Border"); + mous_color = XGetDefault("mailwatch", "Mouse"); + if (option = XGetDefault("mailwatch", "BorderWidth")) + Bwidth = atoi(option); + if (option = XGetDefault("mailwatch", "InternalBorder")) + Inner = atoi(option); + if (option = XGetDefault("mailwatch", "Timeout")) + Timeout = atoi(option); + if (option = XGetDefault("mailwatch", "Volume")) + Volume = atoi(option); + if (option = XGetDefault("mailwatch", "Offset")) + Offset = atoi(option); + if ((option = XGetDefault("mailwatch", "ReverseVideo")) && + strcmp(option, "on") == 0) + reverse = 1; + if (option = XGetDefault("mailwatch", "MaxNotices")) + WindowMax = atoi(option); + } + if (reverse) { + Brdrpix = Backpix; + Backpix = Forepix; + Forepix = Brdrpix; + Mouspix = Forepix; + } + + if ((NoteFont = XGetFont(font_name)) == NULL) + exit(0); + if (DisplayCells() > 2) { + if (back_color && XParseColor(back_color, &cdef) && + XGetHardwareColor(&cdef)) + Backpix = cdef.pixel; + if (fore_color && XParseColor(fore_color, &cdef) && + XGetHardwareColor(&cdef)) + Forepix = cdef.pixel; + if (brdr_color && XParseColor(brdr_color, &cdef) && + XGetHardwareColor(&cdef)) + Brdrpix = cdef.pixel; + if (mous_color && XParseColor(mous_color, &cdef) && + XGetHardwareColor(&cdef)) + Mouspix = cdef.pixel; + } + XQueryFont(NoteFont, &Finfo); + XQueryWindow (RootWindow, &Winfo); + VPos = Offset; + return(dpyno()); +} + +XNotifyClose() +{ + register int i; + register struct wsav *w; + + for (i = WindowMax, w = Wsav; --i >= 0; w++) + if (w->w_window != NULL) XDestroyWindow(w->w_window); + +} + +XDisplayNewWindows() +{ + register int i; + register struct wsav *w; + register int feepcount = 0; + + for (i = 0, w = Wsav; i < WindowMax; w++, i++) + if (w->w_window != NULL && !(w->w_flags & W_MAPPED)) { + XMapWindow(w->w_window); + feepcount++; + w->w_flags |= W_MAPPED; + } + XFlush(); + /* Now feep for each window, s l o w l y */ + while (--feepcount >= 0) { + XFeep(Volume); + XFlush(); + } +} + +XNotifySetup (iov, iovcnt, vpos) +struct iovec *iov; +int iovcnt; +register int *vpos; +{ + register int i; + register int n; + register int width; + register int height; + int vertical; + register Window w; + + width = 0; + for (i = iovcnt; --i >= 0; ) { + n = XQueryWidth (iov[i].iov_base, NoteFont); + if (n > width) width = n; + } + + width += Inner * 2; + height = iovcnt * Finfo.height + (Inner * 2); + vertical = *vpos; + *vpos += height + (Finfo.height / 2); + + w = XCreateWindow(RootWindow, (Winfo.width - width - (Bwidth * 2)) / 2, + vertical, width, height, Bwidth, + XMakeTile(Brdrpix), XMakeTile(Backpix)); + XStoreName(w, "mail-notice"); + XSelectInput(w, ButtonPressed|ButtonReleased|ExposeWindow|ExposeRegion); + XDefineCursor(w, XCreateCursor(16, 10, cursor, NULL, 7, 5, + Mouspix, Backpix, GXcopy)); + return(w); +} + +display_notice(w, iov, iovcnt) +Window w; +register struct iovec *iov; +register int iovcnt; +{ + register int in; + register int y; + register int height; + + in = Inner - 1; + if (in <= 0) in = 1; + + height = Finfo.height; + y = in; + while (--iovcnt >= 0) { + XText(w, in, y, iov->iov_base, iov->iov_len, + NoteFont, Forepix, Backpix); + y += height; + iov++; + } +} -- cgit v1.2.3