Subject: Externally forced check for new mail

From: Chuck Goodhart <[email-masked]>
Date: Wed, 9 Dec 1998 11:46:29 -0800 (PST)

This email includes a patch to provide a way for another process to force
a running PINE process to check for new mail.

My incoming email is sorted (by procmail) into various local files, which
PINE monitors as Incoming-Folders.  If the procmail process could force
a new mail check after delivery, I could increase my mail-check-interval
from 15 and yet get instant notification of new mail.

The patch adds a handler for SIGUSR1.  Patterned after the handler for
SIGWINCH, receipt of the SIGUSR1 signal causes the next check for input
(or the currently active one, if any) to return a NO_OP_IDLE, simulating a
mail-check-interval timeout.  Additionally, the "new_mail" code is flagged
to force a check regardless of the actual timeout status.

======== begin patch ========
--- pine4.05/pine/osdep/termin.unx.orig	Tue Mar 31 12:09:12 1998
+++ pine4.05/pine/osdep/termin.unx	Sun Dec  6 12:09:58 1998
@@ -175,6 +175,9 @@
 int     ready_for_winch = 0;
 #endif
 
+extern jmp_buf usr1_state;
+extern int     ready_for_usr1, usr1_progress;
+
 /*----------------------------------------------------------------------
      This checks whether or not a character			(UNIX)
      is ready to be read, or it times out.
@@ -212,6 +215,27 @@
       ready_for_winch = 1;
 #endif /* RESIZING */
 
+    if(usr1_progress <= 1){
+	if(setjmp(usr1_state) != 0){
+	    usr1_progress = 2;
+	    ready_for_usr1 = 0;
+
+	    /*
+	     * Need to unblock signal after longjmp from handler, because
+	     * signal is normally unblocked upon routine exit from the handler.
+	     */
+	    our_sigunblock(SIGUSR1);
+	}
+	else
+	  ready_for_usr1 = 1;
+    }
+
+    if(usr1_progress > 1){
+	ready_for_usr1 = 0;
+	usr1_progress = 1;	/* one more step: force "new_mail()" */
+	return(NO_OP_IDLE);
+    }
+
     switch(res=input_ready(time_out)){
       case BAIL_OUT:
 	read_bail();			/* non-tragic exit */
@@ -231,6 +255,7 @@
 #ifdef RESIZING
 	ready_for_winch = 0;
 #endif
+	ready_for_usr1 = 0;
 	return(res);
     }
 }
--- pine4.05/pine/signals.c.orig	Tue Sep  1 12:48:42 1998
+++ pine4.05/pine/signals.c	Sun Dec  6 09:48:37 1998
@@ -46,6 +46,7 @@
        - Not much to do for SIGHUP
        - Not much to do for SIGTERM
        - turn SIGWINCH into a KEY_RESIZE command
+       - turn SIGUSR1 into a NO_OP_IDLE with "new_mail()" forced
        - No signals for ^Z/suspend, but do it here anyway
        - Also set up the signal handlers, and hold signals for
          critical imap sections of code.
@@ -67,6 +68,7 @@
               /* SigType is defined in os.h and is either int or void */
 static	SigType	auger_in_signal SIG_PROTO((int));
 static	SigType	winch_signal SIG_PROTO((int));
+static	SigType	usr1_signal SIG_PROTO((int));
 static	SigType	usr2_signal SIG_PROTO((int));
 static	SigType	alarm_signal SIG_PROTO((int));
 static	SigType	intr_signal SIG_PROTO((int));
@@ -111,6 +113,8 @@
     
     init_sigwinch();
 
+    signal(SIGUSR1, usr1_signal);
+
     /*
      * Set up SIGUSR2 to catch signal from other software using the 
      * c-client to tell us that other access to the folder is being 
@@ -462,6 +466,37 @@
 }

+#if !defined(DOS) && !defined(OS2)
+/*----------------------------------------------------------------------
+   Handle check mail signal -- SIGUSR1
+  
+   Similarly to SIGWINCH, the signal is processed by causing a fake key
+  event to be injected into the command stream.  In this case the fake key
+  is NO_OP_IDLE.  In addition, the next call to "new_mail" will behave as
+  if called with "force" set to 1.
+   The comments above "winch_signal" regarding setjmp/longjmp also apply
+  to this function.
+  ----------------------------------------------------------------------*/
+jmp_buf  usr1_state;
+int      ready_for_usr1 = 0;
+int      usr1_progress = 0;
+
+SigType
+static usr1_signal SIG_PROTO((int sig))
+{
+    dprint(9,(debugfile, "SIGUSR1 ready_for_usr1: %d usr1_progress:%d\n",
+               ready_for_usr1, usr1_progress));
+    signal(SIGUSR1, usr1_signal);
+    if(ready_for_usr1)
+      longjmp(usr1_state, 1);
+    else
+      usr1_progress = 2;	/* two steps in processing:	*/
+				/* (1) inject NO_OP_IDLE	*/
+				/* (2) force "new_mail()"	*/
+}
+#endif
+
+
 #ifdef	SIGCHLD
 /*----------------------------------------------------------------------
    Handle child status change -- SIGCHLD
@@ -1107,6 +1142,7 @@
 SigType (*hold_term) SIG_PROTO((int));
 #if !defined(DOS) && !defined(OS2)
 SigType (*hold_hup) SIG_PROTO((int));
+SigType (*hold_usr1) SIG_PROTO((int));
 SigType (*hold_usr2) SIG_PROTO((int));
 #endif
 
@@ -1123,6 +1159,7 @@
     stream = stream; /* For compiler complaints that this isn't used */
 #if !defined(DOS) && !defined(OS2)
     hold_hup  = signal(SIGHUP, SIG_IGN);
+    hold_usr1 = signal(SIGUSR1, SIG_IGN);
     hold_usr2 = signal(SIGUSR2, SIG_IGN);
 #endif
     hold_int  = signal(SIGINT, SIG_IGN);
@@ -1144,6 +1181,7 @@
 
 #if !defined(DOS) && !defined(OS2)
     (void)signal(SIGHUP, hold_hup);
+    (void)signal(SIGUSR1, hold_usr1);
     (void)signal(SIGUSR2, hold_usr2);
 #endif
     (void)signal(SIGINT, hold_int);
--- pine4.05/pine/newmail.c.orig	Fri Aug 21 19:33:02 1998
+++ pine4.05/pine/newmail.c	Sun Dec  6 10:51:07 1998
@@ -108,6 +108,18 @@
     if(!force && pine_state->unsorted_newmail)
       force = !(flags & NM_DEFER_SORT);
 
+#if !defined(DOS) && !defined(OS2)
+    {
+      extern int usr1_progress;
+
+      if(usr1_progress != 0){
+	/* finish SIGUSR1 handling */
+	usr1_progress = 0;
+	force = 1;
+      }
+    }
+#endif
+
     /*
      * only check every 15 seconds, unless we're compelled to
      */
======== end patch ========

-- 
Chuck Goodhart <[email-masked]>

-----------------------------------------------------------------
 For information about this mailing list, and its archives, see: 
 http://www.washington.edu/pine/pine-info/
-----------------------------------------------------------------