122696Sdist /* 222696Sdist ** Sendmail 322696Sdist ** Copyright (c) 1983 Eric P. Allman 422696Sdist ** Berkeley, California 522696Sdist ** 622696Sdist ** Copyright (c) 1983 Regents of the University of California. 722696Sdist ** All rights reserved. The Berkeley software License Agreement 822696Sdist ** specifies the terms and conditions for redistribution. 922696Sdist */ 1022696Sdist 1122696Sdist #ifndef lint 12*24955Seric static char SccsId[] = "@(#)clock.c 5.3 (Berkeley) 09/19/85"; 1322696Sdist #endif not lint 1422696Sdist 157358Seric # include "sendmail.h" 1611728Seric # include <signal.h> 177358Seric 187358Seric /* 197684Seric ** SETEVENT -- set an event to happen at a specific time. 207684Seric ** 219373Seric ** Events are stored in a sorted list for fast processing. 229373Seric ** An event only applies to the process that set it. 239373Seric ** 247684Seric ** Parameters: 257684Seric ** intvl -- intvl until next event occurs. 267684Seric ** func -- function to call on event. 277684Seric ** arg -- argument to func on event. 287684Seric ** 297684Seric ** Returns: 307684Seric ** none. 317684Seric ** 327684Seric ** Side Effects: 337684Seric ** none. 347684Seric */ 357684Seric 367684Seric EVENT * 377684Seric setevent(intvl, func, arg) 387684Seric time_t intvl; 397684Seric int (*func)(); 407684Seric int arg; 417684Seric { 427684Seric register EVENT **evp; 437684Seric register EVENT *ev; 447684Seric auto time_t now; 457684Seric extern tick(); 467684Seric 477757Seric # ifdef DEBUG 487757Seric if (intvl <= 0) 497757Seric { 507757Seric syserr("setevent: intvl=%ld\n", intvl); 519346Seric return (NULL); 527757Seric } 537757Seric # endif DEBUG 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 737684Seric # ifdef DEBUG 748063Seric if (tTd(5, 5)) 757684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 767684Seric intvl, now + intvl, func, arg, ev); 777684Seric # endif DEBUG 787684Seric 797939Seric tick(); 807684Seric return (ev); 817684Seric } 827684Seric /* 837684Seric ** CLREVENT -- remove an event from the event queue. 847684Seric ** 857684Seric ** Parameters: 867684Seric ** ev -- pointer to event to remove. 877684Seric ** 887684Seric ** Returns: 897684Seric ** none. 907684Seric ** 917684Seric ** Side Effects: 927684Seric ** arranges for event ev to not happen. 937684Seric */ 947684Seric 957684Seric clrevent(ev) 967684Seric register EVENT *ev; 977684Seric { 987684Seric register EVENT **evp; 997684Seric 1007684Seric # ifdef DEBUG 1018063Seric if (tTd(5, 5)) 1027684Seric printf("clrevent: ev=%x\n", ev); 1037684Seric # endif DEBUG 1047757Seric if (ev == NULL) 1057757Seric return; 1067684Seric 1077684Seric /* find the parent event */ 1089373Seric (void) signal(SIGALRM, SIG_IGN); 1097684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1107684Seric { 1117684Seric if (*evp == ev) 1127684Seric break; 1137684Seric } 1147684Seric 1157684Seric /* now remove it */ 1167939Seric if (*evp != NULL) 1177939Seric { 1187939Seric *evp = ev->ev_link; 1199346Seric free((char *) ev); 1207939Seric } 1217862Seric 1227862Seric /* restore clocks and pick up anything spare */ 1237862Seric tick(); 1247684Seric } 1257684Seric /* 1267358Seric ** TICK -- take a clock tick 1277358Seric ** 1287684Seric ** Called by the alarm clock. This routine runs events as needed. 1297358Seric ** 1307358Seric ** Parameters: 1317358Seric ** none. 1327358Seric ** 1337358Seric ** Returns: 1347684Seric ** none. 1357358Seric ** 1367358Seric ** Side Effects: 1377684Seric ** calls the next function in EventQueue. 1387358Seric */ 1397358Seric 1407358Seric tick() 1417358Seric { 1427889Seric register time_t now; 1437684Seric register EVENT *ev; 144*24955Seric int mypid = getpid(); 1457684Seric 1469373Seric (void) signal(SIGALRM, SIG_IGN); 1479373Seric (void) alarm(0); 1487889Seric now = curtime(); 1497684Seric 1507358Seric # ifdef DEBUG 1518063Seric if (tTd(5, 4)) 1527684Seric printf("tick: now=%ld\n", now); 1537358Seric # endif DEBUG 1547684Seric 1558128Seric while ((ev = EventQueue) != NULL && 156*24955Seric (ev->ev_time <= now || ev->ev_pid != mypid)) 1577684Seric { 15816141Seric int (*f)(); 15916141Seric int arg; 16016141Seric int pid; 1617862Seric 1627684Seric /* process the event on the top of the queue */ 1637684Seric ev = EventQueue; 1647684Seric EventQueue = EventQueue->ev_link; 1657684Seric # ifdef DEBUG 1668063Seric if (tTd(5, 6)) 1677931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1687931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1697684Seric # endif DEBUG 1707862Seric 1717862Seric /* we must be careful in here because ev_func may not return */ 1729373Seric (void) signal(SIGALRM, tick); 17320844Seric #ifdef SIGVTALRM 17420844Seric /* reset 4.2bsd signal mask to allow future alarms */ 17520844Seric (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 17620844Seric #endif SIGVTALRM 17720844Seric 1787862Seric f = ev->ev_func; 17916141Seric arg = ev->ev_arg; 18016141Seric pid = ev->ev_pid; 1819346Seric free((char *) ev); 18216141Seric if (pid != getpid()) 1837931Seric continue; 1847862Seric if (EventQueue != NULL) 1857862Seric { 1867862Seric if (EventQueue->ev_time > now) 18712635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1887862Seric else 1897889Seric (void) alarm(3); 1907862Seric } 19116141Seric (*f)(arg); 1927862Seric (void) alarm(0); 1937889Seric now = curtime(); 1947684Seric } 1959373Seric (void) signal(SIGALRM, tick); 1967889Seric if (EventQueue != NULL) 19712635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1987358Seric } 1997690Seric /* 2007690Seric ** SLEEP -- a version of sleep that works with this stuff 2017690Seric ** 2027690Seric ** Because sleep uses the alarm facility, I must reimplement 2037690Seric ** it here. 2047690Seric ** 2057690Seric ** Parameters: 2067690Seric ** intvl -- time to sleep. 2077690Seric ** 2087690Seric ** Returns: 2097690Seric ** none. 2107690Seric ** 2117690Seric ** Side Effects: 2127690Seric ** waits for intvl time. However, other events can 2137690Seric ** be run during that interval. 2147690Seric */ 2157690Seric 2167690Seric static bool SleepDone; 2177690Seric 2187690Seric sleep(intvl) 2197690Seric int intvl; 2207690Seric { 2217690Seric extern endsleep(); 2227690Seric 2237757Seric if (intvl == 0) 2247757Seric return; 2257690Seric SleepDone = FALSE; 22612635Seric (void) setevent((time_t) intvl, endsleep, 0); 2277690Seric while (!SleepDone) 2287690Seric pause(); 2297690Seric } 2307690Seric 2317690Seric static 2327690Seric endsleep() 2337690Seric { 2347690Seric SleepDone = TRUE; 2357690Seric } 236