122696Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822696Sdist 922696Sdist #ifndef lint 10*58151Seric static char sccsid[] = "@(#)clock.c 6.2 (Berkeley) 02/23/93"; 1133728Sbostic #endif /* not lint */ 1222696Sdist 137358Seric # include "sendmail.h" 1411728Seric # include <signal.h> 157358Seric 167358Seric /* 177684Seric ** SETEVENT -- set an event to happen at a specific time. 187684Seric ** 199373Seric ** Events are stored in a sorted list for fast processing. 209373Seric ** An event only applies to the process that set it. 219373Seric ** 227684Seric ** Parameters: 237684Seric ** intvl -- intvl until next event occurs. 247684Seric ** func -- function to call on event. 257684Seric ** arg -- argument to func on event. 267684Seric ** 277684Seric ** Returns: 287684Seric ** none. 297684Seric ** 307684Seric ** Side Effects: 317684Seric ** none. 327684Seric */ 337684Seric 3446928Sbostic static void tick(); 3546928Sbostic 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 467757Seric if (intvl <= 0) 477757Seric { 48*58151Seric syserr("554 setevent: intvl=%ld\n", intvl); 499346Seric return (NULL); 507757Seric } 517757Seric 527684Seric (void) time(&now); 537684Seric 547684Seric /* search event queue for correct position */ 557684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 567684Seric { 577684Seric if (ev->ev_time >= now + intvl) 587684Seric break; 597684Seric } 607684Seric 617684Seric /* insert new event */ 627684Seric ev = (EVENT *) xalloc(sizeof *ev); 637684Seric ev->ev_time = now + intvl; 647684Seric ev->ev_func = func; 657684Seric ev->ev_arg = arg; 667931Seric ev->ev_pid = getpid(); 677684Seric ev->ev_link = *evp; 687684Seric *evp = ev; 697684Seric 708063Seric if (tTd(5, 5)) 717684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 727684Seric intvl, now + intvl, func, arg, ev); 737684Seric 747939Seric tick(); 757684Seric return (ev); 767684Seric } 777684Seric /* 787684Seric ** CLREVENT -- remove an event from the event queue. 797684Seric ** 807684Seric ** Parameters: 817684Seric ** ev -- pointer to event to remove. 827684Seric ** 837684Seric ** Returns: 847684Seric ** none. 857684Seric ** 867684Seric ** Side Effects: 877684Seric ** arranges for event ev to not happen. 887684Seric */ 897684Seric 907684Seric clrevent(ev) 917684Seric register EVENT *ev; 927684Seric { 937684Seric register EVENT **evp; 947684Seric 958063Seric if (tTd(5, 5)) 967684Seric printf("clrevent: ev=%x\n", ev); 977757Seric if (ev == NULL) 987757Seric return; 997684Seric 1007684Seric /* find the parent event */ 1019373Seric (void) signal(SIGALRM, SIG_IGN); 1027684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1037684Seric { 1047684Seric if (*evp == ev) 1057684Seric break; 1067684Seric } 1077684Seric 1087684Seric /* now remove it */ 1097939Seric if (*evp != NULL) 1107939Seric { 1117939Seric *evp = ev->ev_link; 1129346Seric free((char *) ev); 1137939Seric } 1147862Seric 1157862Seric /* restore clocks and pick up anything spare */ 1167862Seric tick(); 1177684Seric } 1187684Seric /* 1197358Seric ** TICK -- take a clock tick 1207358Seric ** 1217684Seric ** Called by the alarm clock. This routine runs events as needed. 1227358Seric ** 1237358Seric ** Parameters: 1247358Seric ** none. 1257358Seric ** 1267358Seric ** Returns: 1277684Seric ** none. 1287358Seric ** 1297358Seric ** Side Effects: 1307684Seric ** calls the next function in EventQueue. 1317358Seric */ 1327358Seric 13346979Sbostic static void 1347358Seric tick() 1357358Seric { 1367889Seric register time_t now; 1377684Seric register EVENT *ev; 13824955Seric int mypid = getpid(); 1397684Seric 1409373Seric (void) signal(SIGALRM, SIG_IGN); 1419373Seric (void) alarm(0); 1427889Seric now = curtime(); 1437684Seric 1448063Seric if (tTd(5, 4)) 1457684Seric printf("tick: now=%ld\n", now); 1467684Seric 1478128Seric while ((ev = EventQueue) != NULL && 14824955Seric (ev->ev_time <= now || ev->ev_pid != mypid)) 1497684Seric { 15016141Seric int (*f)(); 15116141Seric int arg; 15216141Seric int pid; 1537862Seric 1547684Seric /* process the event on the top of the queue */ 1557684Seric ev = EventQueue; 1567684Seric EventQueue = EventQueue->ev_link; 1578063Seric if (tTd(5, 6)) 1587931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1597931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1607862Seric 1617862Seric /* we must be careful in here because ev_func may not return */ 1629373Seric (void) signal(SIGALRM, tick); 16320844Seric #ifdef SIGVTALRM 16420844Seric /* reset 4.2bsd signal mask to allow future alarms */ 16520844Seric (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 16656795Seric #endif /* SIGVTALRM */ 16720844Seric 1687862Seric f = ev->ev_func; 16916141Seric arg = ev->ev_arg; 17016141Seric pid = ev->ev_pid; 1719346Seric free((char *) ev); 17216141Seric if (pid != getpid()) 1737931Seric continue; 1747862Seric if (EventQueue != NULL) 1757862Seric { 1767862Seric if (EventQueue->ev_time > now) 17712635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1787862Seric else 1797889Seric (void) alarm(3); 1807862Seric } 18116141Seric (*f)(arg); 1827862Seric (void) alarm(0); 1837889Seric now = curtime(); 1847684Seric } 1859373Seric (void) signal(SIGALRM, tick); 1867889Seric if (EventQueue != NULL) 18712635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1887358Seric } 1897690Seric /* 1907690Seric ** SLEEP -- a version of sleep that works with this stuff 1917690Seric ** 1927690Seric ** Because sleep uses the alarm facility, I must reimplement 1937690Seric ** it here. 1947690Seric ** 1957690Seric ** Parameters: 1967690Seric ** intvl -- time to sleep. 1977690Seric ** 1987690Seric ** Returns: 1997690Seric ** none. 2007690Seric ** 2017690Seric ** Side Effects: 2027690Seric ** waits for intvl time. However, other events can 2037690Seric ** be run during that interval. 2047690Seric */ 2057690Seric 2067690Seric static bool SleepDone; 2077690Seric 2087690Seric sleep(intvl) 20925615Seric unsigned int intvl; 2107690Seric { 21146928Sbostic static int endsleep(); 2127690Seric 2137757Seric if (intvl == 0) 2147757Seric return; 2157690Seric SleepDone = FALSE; 21612635Seric (void) setevent((time_t) intvl, endsleep, 0); 2177690Seric while (!SleepDone) 2187690Seric pause(); 2197690Seric } 2207690Seric 2217690Seric static 2227690Seric endsleep() 2237690Seric { 2247690Seric SleepDone = TRUE; 2257690Seric } 226