122696Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 362522Sbostic * Copyright (c) 1988, 1993 462522Sbostic * The Regents of the University of California. All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822696Sdist 922696Sdist #ifndef lint 10*64035Seric static char sccsid[] = "@(#)clock.c 8.5 (Berkeley) 07/26/93"; 1133728Sbostic #endif /* not lint */ 1222696Sdist 137358Seric # include "sendmail.h" 147358Seric 1560601Seric # ifndef sigmask 1660601Seric # define sigmask(s) (1 << ((s) - 1)) 1760601Seric # endif 1860601Seric 197358Seric /* 207684Seric ** SETEVENT -- set an event to happen at a specific time. 217684Seric ** 229373Seric ** Events are stored in a sorted list for fast processing. 239373Seric ** An event only applies to the process that set it. 249373Seric ** 257684Seric ** Parameters: 267684Seric ** intvl -- intvl until next event occurs. 277684Seric ** func -- function to call on event. 287684Seric ** arg -- argument to func on event. 297684Seric ** 307684Seric ** Returns: 317684Seric ** none. 327684Seric ** 337684Seric ** Side Effects: 347684Seric ** none. 357684Seric */ 367684Seric 3746928Sbostic static void tick(); 3846928Sbostic 397684Seric EVENT * 407684Seric setevent(intvl, func, arg) 417684Seric time_t intvl; 427684Seric int (*func)(); 437684Seric int arg; 447684Seric { 457684Seric register EVENT **evp; 467684Seric register EVENT *ev; 477684Seric auto time_t now; 487684Seric 497757Seric if (intvl <= 0) 507757Seric { 5158151Seric syserr("554 setevent: intvl=%ld\n", intvl); 529346Seric return (NULL); 537757Seric } 547757Seric 557684Seric (void) time(&now); 567684Seric 577684Seric /* search event queue for correct position */ 587684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 597684Seric { 607684Seric if (ev->ev_time >= now + intvl) 617684Seric break; 627684Seric } 637684Seric 647684Seric /* insert new event */ 657684Seric ev = (EVENT *) xalloc(sizeof *ev); 667684Seric ev->ev_time = now + intvl; 677684Seric ev->ev_func = func; 687684Seric ev->ev_arg = arg; 697931Seric ev->ev_pid = getpid(); 707684Seric ev->ev_link = *evp; 717684Seric *evp = ev; 727684Seric 738063Seric if (tTd(5, 5)) 747684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 757684Seric intvl, now + intvl, func, arg, ev); 767684Seric 777939Seric tick(); 787684Seric return (ev); 797684Seric } 807684Seric /* 817684Seric ** CLREVENT -- remove an event from the event queue. 827684Seric ** 837684Seric ** Parameters: 847684Seric ** ev -- pointer to event to remove. 857684Seric ** 867684Seric ** Returns: 877684Seric ** none. 887684Seric ** 897684Seric ** Side Effects: 907684Seric ** arranges for event ev to not happen. 917684Seric */ 927684Seric 937684Seric clrevent(ev) 947684Seric register EVENT *ev; 957684Seric { 967684Seric register EVENT **evp; 977684Seric 988063Seric if (tTd(5, 5)) 997684Seric printf("clrevent: ev=%x\n", ev); 1007757Seric if (ev == NULL) 1017757Seric return; 1027684Seric 1037684Seric /* find the parent event */ 104*64035Seric (void) setsignal(SIGALRM, SIG_IGN); 1057684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1067684Seric { 1077684Seric if (*evp == ev) 1087684Seric break; 1097684Seric } 1107684Seric 1117684Seric /* now remove it */ 1127939Seric if (*evp != NULL) 1137939Seric { 1147939Seric *evp = ev->ev_link; 1159346Seric free((char *) ev); 1167939Seric } 1177862Seric 1187862Seric /* restore clocks and pick up anything spare */ 1197862Seric tick(); 1207684Seric } 1217684Seric /* 1227358Seric ** TICK -- take a clock tick 1237358Seric ** 1247684Seric ** Called by the alarm clock. This routine runs events as needed. 1257358Seric ** 1267358Seric ** Parameters: 1277358Seric ** none. 1287358Seric ** 1297358Seric ** Returns: 1307684Seric ** none. 1317358Seric ** 1327358Seric ** Side Effects: 1337684Seric ** calls the next function in EventQueue. 1347358Seric */ 1357358Seric 13646979Sbostic static void 1377358Seric tick() 1387358Seric { 1397889Seric register time_t now; 1407684Seric register EVENT *ev; 14124955Seric int mypid = getpid(); 14263787Seric #ifdef SIG_UNBLOCK 14363787Seric sigset_t ss; 14463787Seric #endif 1457684Seric 146*64035Seric (void) setsignal(SIGALRM, SIG_IGN); 1479373Seric (void) alarm(0); 1487889Seric now = curtime(); 1497684Seric 1508063Seric if (tTd(5, 4)) 1517684Seric printf("tick: now=%ld\n", now); 1527684Seric 1538128Seric while ((ev = EventQueue) != NULL && 15424955Seric (ev->ev_time <= now || ev->ev_pid != mypid)) 1557684Seric { 15616141Seric int (*f)(); 15716141Seric int arg; 15816141Seric int pid; 1597862Seric 1607684Seric /* process the event on the top of the queue */ 1617684Seric ev = EventQueue; 1627684Seric EventQueue = EventQueue->ev_link; 1638063Seric if (tTd(5, 6)) 1647931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1657931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1667862Seric 1677862Seric /* we must be careful in here because ev_func may not return */ 168*64035Seric (void) setsignal(SIGALRM, tick); 16963787Seric #ifdef SIG_UNBLOCK 17063787Seric /* unblock SIGALRM signal */ 17163787Seric sigemptyset(&ss); 17263787Seric sigaddset(&ss, SIGALRM); 17363787Seric sigprocmask(SIG_UNBLOCK, &ss, NULL); 17463787Seric #else 17520844Seric #ifdef SIGVTALRM 17620844Seric /* reset 4.2bsd signal mask to allow future alarms */ 17720844Seric (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 17856795Seric #endif /* SIGVTALRM */ 17963787Seric #endif /* SIG_UNBLOCK */ 18020844Seric 1817862Seric f = ev->ev_func; 18216141Seric arg = ev->ev_arg; 18316141Seric pid = ev->ev_pid; 1849346Seric free((char *) ev); 18516141Seric if (pid != getpid()) 1867931Seric continue; 1877862Seric if (EventQueue != NULL) 1887862Seric { 1897862Seric if (EventQueue->ev_time > now) 19012635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1917862Seric else 1927889Seric (void) alarm(3); 1937862Seric } 19416141Seric (*f)(arg); 1957862Seric (void) alarm(0); 1967889Seric now = curtime(); 1977684Seric } 198*64035Seric (void) setsignal(SIGALRM, tick); 1997889Seric if (EventQueue != NULL) 20012635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 2017358Seric } 2027690Seric /* 2037690Seric ** SLEEP -- a version of sleep that works with this stuff 2047690Seric ** 2057690Seric ** Because sleep uses the alarm facility, I must reimplement 2067690Seric ** it here. 2077690Seric ** 2087690Seric ** Parameters: 2097690Seric ** intvl -- time to sleep. 2107690Seric ** 2117690Seric ** Returns: 2127690Seric ** none. 2137690Seric ** 2147690Seric ** Side Effects: 2157690Seric ** waits for intvl time. However, other events can 2167690Seric ** be run during that interval. 2177690Seric */ 2187690Seric 2197690Seric static bool SleepDone; 22063937Seric static int endsleep(); 2217690Seric 22263968Seric #ifndef SLEEP_T 22363968Seric # define SLEEP_T unsigned int 22463968Seric #endif 22563968Seric 22663968Seric SLEEP_T 2277690Seric sleep(intvl) 22825615Seric unsigned int intvl; 2297690Seric { 2307757Seric if (intvl == 0) 2317757Seric return; 2327690Seric SleepDone = FALSE; 23312635Seric (void) setevent((time_t) intvl, endsleep, 0); 2347690Seric while (!SleepDone) 2357690Seric pause(); 2367690Seric } 2377690Seric 2387690Seric static 2397690Seric endsleep() 2407690Seric { 2417690Seric SleepDone = TRUE; 2427690Seric } 243