diff -ru xbiff-4.3.99.902/Mailbox.c xbiff/Mailbox.c --- xbiff-4.3.99.902/Mailbox.c Mon Feb 2 13:51:41 2004 +++ xbiff/Mailbox.c Mon Feb 2 23:21:24 2004 @@ -53,6 +53,11 @@ #include /* for stat() ** needs types.h ***/ #include /* for printing error messages */ #include +#include /* for socket() &c. */ +#include /* for getaddrinfo() */ +#include /* for struct in_addr, sockaddr_in */ +#include /* for htons(), ntohl() */ +#include /* for select(), timeval */ #ifndef X_NOT_POSIX #ifdef _POSIX_SOURCE @@ -136,6 +141,8 @@ offset (filename), XtRString, NULL }, { XtNcheckCommand, XtCCheckCommand, XtRString, sizeof(char*), offset (check_command), XtRString, NULL}, + { XtNrfc1339Mailbox, XtCRfc1339Mailbox, XtRString, sizeof(char*), + offset (rfc1339_mailbox), XtRString, NULL}, { XtNvolume, XtCVolume, XtRInt, sizeof(int), offset (volume), XtRString, "33"}, { XtNonceOnly, XtCBoolean, XtRBoolean, sizeof(Boolean), @@ -161,6 +168,8 @@ static void check_mailbox(), redraw_mailbox(), beep(); static void Initialize(), Realize(), Destroy(), Redisplay(); static Boolean SetValues(); +static void Rfc1339Init(); +static int Rfc1339Check(); MailboxClassRec mailboxClassRec = { { /* core fields */ @@ -251,6 +260,7 @@ w->mailbox.flag_up = FALSE; w->mailbox.last_size = 0; if (!w->mailbox.filename) GetMailFile (w); + if (w->mailbox.rfc1339_mailbox) Rfc1339Init(w); return; } @@ -461,7 +471,19 @@ long mailboxsize = 0; Boolean readSinceLastWrite = FALSE; - if (w->mailbox.check_command != NULL) { + if (w->mailbox.rfc1339_mailbox != NULL) { + switch(Rfc1339Check(w)) { + case 0: + mailboxsize = w->mailbox.last_size + 1; + break; + case 2: + mailboxsize = 0; + break; + default: /* treat everything else as no change */ + /* case 1 is no change */ + mailboxsize = w->mailbox.last_size; + } + } else if (w->mailbox.check_command != NULL) { waitType wait_status; int check_status; #ifdef INTWAITTYPE @@ -684,4 +706,153 @@ { XBell (XtDisplay (w), w->mailbox.volume); return; +} + + +/* + * Functions for doing RFC1339 remote mailbox checks. + * Tim Deegan , June 2002. + */ + +static void Rfc1339Init (w) + MailboxWidget w; +{ + char *host, *user, *req, *service; + struct addrinfo *ai, *ais, ai_hint; + ssize_t reqlen; + int rv, sock; + + user = w->mailbox.rfc1339_mailbox; + + if ((host = strchr (user, '@')) == NULL + || host == user + || host[1] == '\0') + { + fprintf (stderr, "%s: rfc1339 mailbox should be 'user@host'.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + + /* Separate username from host, and check it will fit in a UDP packet */ + *host++ = '\0'; + if (strlen(user) > 65502) { + fprintf (stderr, "%s: rfc1339 username too long.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + + /* Check if the service name is in /etc/services */ + if ((rv = getaddrinfo (NULL, "re-mail-ck", NULL, &ais)) == 0) + { + service = "re-mail-ck"; + freeaddrinfo (ais); + } else { + service = "50"; + } + + /* Translate the hostname */ + memset (&ai_hint, 0, sizeof ai_hint); + ai_hint.ai_family = PF_UNSPEC; + ai_hint.ai_socktype = SOCK_DGRAM; + if ((rv = getaddrinfo (host, service, &ai_hint, &ais)) != 0) + { + fprintf (stderr, "%s: unable to resolve rfc1339 hostname (%s).\n", + "Mailbox widget", gai_strerror(rv)); + CloseDown (w, 1); + } + + /* Prepare a socket */ + sock = -1; + for (ai = ais; ai; ai = ai->ai_next) + { + sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) continue; + if (connect (sock, ai->ai_addr, ai->ai_addrlen)) { + close (sock); + sock = -1; + } + if (sock > 0) break; + } + if (sock < 0) { + fprintf (stderr, "%s: unable to make a connection for rfc1339.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + + /* Free storage allocated by getaddrinfo() */ + freeaddrinfo (ais); + + /* Prepare a request: 4 null bytes and an ASCII username */ + reqlen = strlen (user) + 5; + if ((req = malloc (reqlen)) == NULL) { + fprintf (stderr, "%s: unable to malloc space for rfc1339 packet.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + req[0] = req[1] = req[2] = req[3] = '\0'; + strcpy (req+4, user); + + /* Record everything in the widget */ + w->mailbox.rfc1339_socket = sock; + w->mailbox.rfc1339_packet = req; + w->mailbox.rfc1339_packet_len = reqlen; + + /* RFC 1339 says we mustn't poll above once a minute */ + if (w->mailbox.update < 60) w->mailbox.update = 60; + + return; +} + + +static int Rfc1339Check (w) + MailboxWidget w; +{ + char reply[12]; + unsigned long old, new; + fd_set fds; + struct timeval tv; + + /* Send an RFC1339 request packet: return value as for CheckCommand */ + if (send (w->mailbox.rfc1339_socket, + w->mailbox.rfc1339_packet, w->mailbox.rfc1339_packet_len, 0) + != w->mailbox.rfc1339_packet_len) + { + /* Already failed */ + return (3); + } + + /* Wait */ + FD_ZERO(&fds); FD_SET(w->mailbox.rfc1339_socket, &fds); + tv.tv_sec = 10; tv.tv_usec = 0; + if (select (w->mailbox.rfc1339_socket+1, &fds, NULL, NULL, &tv) != 1) + return (3); /* No reply */ + + /* Read the reply */ + if (recv(w->mailbox.rfc1339_socket, &reply[0], 12, 0) != 12) + { + fprintf (stderr, "%s: bad response to rfc1339 request.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + + if (reply[0] || reply[1] || reply[2] || reply[3]) + { + /* Not a reply, an authentication request. We're done for. */ + fprintf (stderr, "%s: rfc1339 authentication unsupported.\n", + "Mailbox widget"); + CloseDown (w, 1); + } + + /* Parse the reply */ + new = ntohl(*(unsigned long *)(reply + 4)); + old = ntohl(*(unsigned long *)(reply + 8)); + + /* Special cases */ + if (!new && !old) return (2); + if (new && !old) return (0); + if (!new && old) return (1); + + /* Compare timestamps */ + if (new < old) return (0); + return (1); } diff -ru xbiff-4.3.99.902/Mailbox.h xbiff/Mailbox.h --- xbiff-4.3.99.902/Mailbox.h Mon Feb 2 13:51:41 2004 +++ xbiff/Mailbox.h Wed Jun 12 15:59:59 2002 @@ -45,6 +45,7 @@ /* command to exec */ #define XtNcheckCommand "checkCommand" #define XtNonceOnly "onceOnly" +#define XtNrfc1339Mailbox "rfc1339Mailbox" /* Int: volume for bell */ #define XtNvolume "volume" @@ -56,6 +57,7 @@ #define XtNshapeWindow "shapeWindow" #define XtCCheckCommand "CheckCommand" +#define XtCRfc1339Mailbox "Rfc1339Mailbox" #define XtCVolume "Volume" #define XtCPixmapMask "PixmapMask" #define XtCFlip "Flip" diff -ru xbiff-4.3.99.902/MailboxP.h xbiff/MailboxP.h --- xbiff-4.3.99.902/MailboxP.h Mon Feb 2 13:51:41 2004 +++ xbiff/MailboxP.h Wed Jun 12 17:43:30 2002 @@ -36,6 +36,11 @@ #include "Mailbox.h" #include +#include +#include +#include + + #if defined(SYSV) #define MAILBOX_DIRECTORY "/usr/mail" #elif defined(SVR4) @@ -59,6 +64,7 @@ Pixel foreground_pixel; /* color index of normal state fg */ String filename; /* filename to watch */ String check_command; /* command to exec for mail check */ + String rfc1339_mailbox; /* remote mailbox to check */ Boolean flipit; /* do flip of full pixmap */ int volume; /* bell volume */ Boolean once_only; /* ring bell only once on new mail */ @@ -77,6 +83,9 @@ Pixmap mask; int x, y; } shape_cache; /* last set of info */ + char *rfc1339_packet; /* request packet for rfc1339 check */ + ssize_t rfc1339_packet_len; /* length of packet */ + int rfc1339_socket; /* socket to send it on */ } MailboxPart; typedef struct _MailboxRec { /* full instance record */ diff -ru xbiff-4.3.99.902/xbiff.man xbiff/xbiff.man --- xbiff-4.3.99.902/xbiff.man Mon Feb 2 13:51:41 2004 +++ xbiff/xbiff.man Wed Jun 12 18:23:39 2002 @@ -121,6 +121,14 @@ has been no change in size, and 2 indicates that the mail has been cleared. By default, no shell command is provided. .TP 8 +.B rfc1339Mailbox (\fPclass\fB Rfc1339Mailbox) +Specifies a remote mailbox to check using the RFC 1339 remote mail +checking protocol, rather than examining the size of \fBfile\fP. +The mailbox should be of the form user@host. If +\fBcheckCommand\fP and \fBrfc1339Mailbox\fP are both specified, +\fBrfc1339Mailbox\fP takes precedence. +By default, no remote mailbox is specified. +.TP 8 .B file (\fPclass\fB File) Specifies the name of the file to monitor. The default is as described above for the @@ -214,3 +222,5 @@ Jim Fulton, MIT X Consortium .br Additional hacks by Ralph Swick, DEC/MIT Project Athena +.br +RFC 1339 client support by Tim Deegan