X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=idle.c;h=04c191847870798f96634cf793f273724ce3c701;hb=87bcf29364c4640edb87cc2186b965d1a564d70c;hp=67b52b565fbe4a7fa93ad613c1d55c268c0cccb6;hpb=f34b0b77094710429baf281a4f567aaff526a756;p=~andy%2Ffetchmail diff --git a/idle.c b/idle.c index 67b52b56..04c19184 100644 --- a/idle.c +++ b/idle.c @@ -1,23 +1,32 @@ -/* - * idle.c -- pause code for fetchmail - * - * For license terms, see the file COPYING in this directory. - */ -#include "config.h" +/***************************************************************************** + +NAME: + idle.c -- code for interruptible delays without sleep(3). + +ENTRY POINTS: + interruptible_idle() -- delay for some time, interruptible by signal. +THEORY: + Sometimes you need more than one time delay per program, so alarm(3) +won't cut it. This code illustrates time delays with select(2). + +AUTHOR: + Eric S. Raymond , 1997. This source code example +is part of fetchmail and the Unix Cookbook, and are released under the +MIT license. Compile with -DMAIN to build the demonstrator. + +******************************************************************************/ #include -#if defined(STDC_HEADERS) #include -#endif -#if defined(HAVE_UNISTD_H) #include -#endif #include #include -#include +#include /* for ROOT_UID */ -#include "fetchmail.h" -#include "i18n.h" +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif volatile int lastsig; /* last signal received */ @@ -27,62 +36,25 @@ volatile int lastsig; /* last signal received */ * SIGALRM can hose the code (ALARM is triggered *before* pause() is called). * This is a bit of a kluge; the real right thing would use sigprocmask(), * sigsuspend(). This workaround lets the interval timer trigger the first - * alarm after the required interval and will then generate alarms all 5 - * seconds, until it is certain, that the critical section (ie., the window) - * is left. + * alarm after the required interval and will then generate alarms + * seconds until it is certain that the critical section (ie., the window) + * is exited. */ -#if defined(STDC_HEADERS) static sig_atomic_t alarm_latch = FALSE; -#else -/* assume int can be written in one atomic operation on non ANSI-C systems */ -static int alarm_latch = FALSE; -#endif -RETSIGTYPE gotsigalrm(sig) -int sig; +void gotsigalrm(int sig) { - signal(sig, gotsigalrm); + set_signal_handler(sig, gotsigalrm); lastsig = sig; alarm_latch = TRUE; } #endif /* SLEEP_WITH_ALARM */ -#ifdef __EMX__ -/* Various EMX-specific definitions */ -static int itimerflag; - -void itimerthread(void* dummy) -{ - if (outlevel >= O_VERBOSE) - report(stderr, - _("fetchmail: thread sleeping for %d sec.\n"), poll_interval); - while(1) - { - _sleep2(poll_interval*1000); - kill((getpid()), SIGALRM); - } -} -#endif - -RETSIGTYPE donothing(int sig) {signal(sig, donothing); lastsig = sig;} - int interruptible_idle(int seconds) /* time for a pause in the action; return TRUE if awakened by signal */ { int awoken = FALSE; - /* - * With this simple hack, we make it possible for a foreground - * fetchmail to wake up one in daemon mode. What we want is the - * side effect of interrupting any sleep that may be going on, - * forcing fetchmail to re-poll its hosts. The second line is - * for people who think all system daemons wake up on SIGHUP. - */ - signal(SIGUSR1, donothing); - if (!getuid()) - signal(SIGHUP, donothing); - -#ifndef __EMX__ #ifdef SLEEP_WITH_ALARM /* not normally on */ /* * We can't use sleep(3) here because we need an alarm(3) @@ -118,20 +90,19 @@ int interruptible_idle(int seconds) ntimeout.it_value.tv_sec = seconds; ntimeout.it_value.tv_usec = 0; - siginterrupt(SIGALRM, 1); alarm_latch = FALSE; - signal(SIGALRM, gotsigalrm); /* first trap signals */ + set_signal_handler(SIGALRM, gotsigalrm); /* first trap signals */ setitimer(ITIMER_REAL,&ntimeout,NULL); /* then start timer */ /* there is a very small window between the next two lines */ /* which could result in a deadlock. But this will now be */ - /* caught by periodical alarms (see it_interval) */ + /* caught by periodic alarms (see it_interval) */ if (!alarm_latch) pause(); /* stop timer */ ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0; ntimeout.it_value.tv_sec = ntimeout.it_value.tv_usec = 0; setitimer(ITIMER_REAL,&ntimeout,NULL); /* now stop timer */ - signal(SIGALRM, SIG_IGN); + set_signal_handler(SIGALRM, SIG_IGN); } #else /* @@ -147,7 +118,7 @@ int interruptible_idle(int seconds) { struct timeval timeout; - timeout.tv_sec = run.poll_interval; + timeout.tv_sec = seconds; timeout.tv_usec = 0; do { lastsig = 0; @@ -155,24 +126,27 @@ int interruptible_idle(int seconds) } while (lastsig == SIGCHLD); } #endif -#else /* EMX */ - alarm_latch = FALSE; - signal(SIGALRM, gotsigalrm); - _beginthread(itimerthread, NULL, 32768, NULL); - /* see similar code above */ - if (!alarm_latch) - pause(); - signal(SIGALRM, SIG_IGN); -#endif /* ! EMX */ - if (lastsig == SIGUSR1 || ((seconds && !getuid()) && lastsig == SIGHUP)) + if (lastsig == SIGUSR1 || ((seconds && getuid() == ROOT_UID) + && lastsig == SIGHUP)) awoken = TRUE; /* now lock out interrupts again */ - signal(SIGUSR1, SIG_IGN); - if (!getuid()) - signal(SIGHUP, SIG_IGN); + set_signal_handler(SIGUSR1, SIG_IGN); + if (getuid() == ROOT_UID) + set_signal_handler(SIGHUP, SIG_IGN); return(awoken ? lastsig : 0); } +#ifdef MAIN +int main(int argc, char **argv) +{ + for (;;) + { + printf("How may I serve you, master?\n"); + interruptible_idle(5); + } +} +#endif /* MAIN */ + /* idle.c ends here */