122696Sdist /* 2*33728Sbostic * Copyright (c) 1988 Regents of the University of California. 3*33728Sbostic * All rights reserved. 4*33728Sbostic * 5*33728Sbostic * Redistribution and use in source and binary forms are permitted 6*33728Sbostic * provided that this notice is preserved and that due credit is given 7*33728Sbostic * to the University of California at Berkeley. The name of the University 8*33728Sbostic * may not be used to endorse or promote products derived from this 9*33728Sbostic * software without specific prior written permission. This software 10*33728Sbostic * is provided ``as is'' without express or implied warranty. 11*33728Sbostic * 12*33728Sbostic * Sendmail 13*33728Sbostic * Copyright (c) 1983 Eric P. Allman 14*33728Sbostic * Berkeley, California 15*33728Sbostic */ 1622696Sdist 1722696Sdist #ifndef lint 18*33728Sbostic static char sccsid[] = "@(#)clock.c 5.5 (Berkeley) 03/13/88"; 19*33728Sbostic #endif /* not lint */ 2022696Sdist 217358Seric # include "sendmail.h" 2211728Seric # include <signal.h> 237358Seric 247358Seric /* 257684Seric ** SETEVENT -- set an event to happen at a specific time. 267684Seric ** 279373Seric ** Events are stored in a sorted list for fast processing. 289373Seric ** An event only applies to the process that set it. 299373Seric ** 307684Seric ** Parameters: 317684Seric ** intvl -- intvl until next event occurs. 327684Seric ** func -- function to call on event. 337684Seric ** arg -- argument to func on event. 347684Seric ** 357684Seric ** Returns: 367684Seric ** none. 377684Seric ** 387684Seric ** Side Effects: 397684Seric ** none. 407684Seric */ 417684Seric 427684Seric EVENT * 437684Seric setevent(intvl, func, arg) 447684Seric time_t intvl; 457684Seric int (*func)(); 467684Seric int arg; 477684Seric { 487684Seric register EVENT **evp; 497684Seric register EVENT *ev; 507684Seric auto time_t now; 517684Seric extern tick(); 527684Seric 537757Seric # ifdef DEBUG 547757Seric if (intvl <= 0) 557757Seric { 567757Seric syserr("setevent: intvl=%ld\n", intvl); 579346Seric return (NULL); 587757Seric } 597757Seric # endif DEBUG 607757Seric 617684Seric (void) time(&now); 627684Seric 637684Seric /* search event queue for correct position */ 647684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 657684Seric { 667684Seric if (ev->ev_time >= now + intvl) 677684Seric break; 687684Seric } 697684Seric 707684Seric /* insert new event */ 717684Seric ev = (EVENT *) xalloc(sizeof *ev); 727684Seric ev->ev_time = now + intvl; 737684Seric ev->ev_func = func; 747684Seric ev->ev_arg = arg; 757931Seric ev->ev_pid = getpid(); 767684Seric ev->ev_link = *evp; 777684Seric *evp = ev; 787684Seric 797684Seric # ifdef DEBUG 808063Seric if (tTd(5, 5)) 817684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 827684Seric intvl, now + intvl, func, arg, ev); 837684Seric # endif DEBUG 847684Seric 857939Seric tick(); 867684Seric return (ev); 877684Seric } 887684Seric /* 897684Seric ** CLREVENT -- remove an event from the event queue. 907684Seric ** 917684Seric ** Parameters: 927684Seric ** ev -- pointer to event to remove. 937684Seric ** 947684Seric ** Returns: 957684Seric ** none. 967684Seric ** 977684Seric ** Side Effects: 987684Seric ** arranges for event ev to not happen. 997684Seric */ 1007684Seric 1017684Seric clrevent(ev) 1027684Seric register EVENT *ev; 1037684Seric { 1047684Seric register EVENT **evp; 1057684Seric 1067684Seric # ifdef DEBUG 1078063Seric if (tTd(5, 5)) 1087684Seric printf("clrevent: ev=%x\n", ev); 1097684Seric # endif DEBUG 1107757Seric if (ev == NULL) 1117757Seric return; 1127684Seric 1137684Seric /* find the parent event */ 1149373Seric (void) signal(SIGALRM, SIG_IGN); 1157684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1167684Seric { 1177684Seric if (*evp == ev) 1187684Seric break; 1197684Seric } 1207684Seric 1217684Seric /* now remove it */ 1227939Seric if (*evp != NULL) 1237939Seric { 1247939Seric *evp = ev->ev_link; 1259346Seric free((char *) ev); 1267939Seric } 1277862Seric 1287862Seric /* restore clocks and pick up anything spare */ 1297862Seric tick(); 1307684Seric } 1317684Seric /* 1327358Seric ** TICK -- take a clock tick 1337358Seric ** 1347684Seric ** Called by the alarm clock. This routine runs events as needed. 1357358Seric ** 1367358Seric ** Parameters: 1377358Seric ** none. 1387358Seric ** 1397358Seric ** Returns: 1407684Seric ** none. 1417358Seric ** 1427358Seric ** Side Effects: 1437684Seric ** calls the next function in EventQueue. 1447358Seric */ 1457358Seric 1467358Seric tick() 1477358Seric { 1487889Seric register time_t now; 1497684Seric register EVENT *ev; 15024955Seric int mypid = getpid(); 1517684Seric 1529373Seric (void) signal(SIGALRM, SIG_IGN); 1539373Seric (void) alarm(0); 1547889Seric now = curtime(); 1557684Seric 1567358Seric # ifdef DEBUG 1578063Seric if (tTd(5, 4)) 1587684Seric printf("tick: now=%ld\n", now); 1597358Seric # endif DEBUG 1607684Seric 1618128Seric while ((ev = EventQueue) != NULL && 16224955Seric (ev->ev_time <= now || ev->ev_pid != mypid)) 1637684Seric { 16416141Seric int (*f)(); 16516141Seric int arg; 16616141Seric int pid; 1677862Seric 1687684Seric /* process the event on the top of the queue */ 1697684Seric ev = EventQueue; 1707684Seric EventQueue = EventQueue->ev_link; 1717684Seric # ifdef DEBUG 1728063Seric if (tTd(5, 6)) 1737931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1747931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1757684Seric # endif DEBUG 1767862Seric 1777862Seric /* we must be careful in here because ev_func may not return */ 1789373Seric (void) signal(SIGALRM, tick); 17920844Seric #ifdef SIGVTALRM 18020844Seric /* reset 4.2bsd signal mask to allow future alarms */ 18120844Seric (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 18220844Seric #endif SIGVTALRM 18320844Seric 1847862Seric f = ev->ev_func; 18516141Seric arg = ev->ev_arg; 18616141Seric pid = ev->ev_pid; 1879346Seric free((char *) ev); 18816141Seric if (pid != getpid()) 1897931Seric continue; 1907862Seric if (EventQueue != NULL) 1917862Seric { 1927862Seric if (EventQueue->ev_time > now) 19312635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1947862Seric else 1957889Seric (void) alarm(3); 1967862Seric } 19716141Seric (*f)(arg); 1987862Seric (void) alarm(0); 1997889Seric now = curtime(); 2007684Seric } 2019373Seric (void) signal(SIGALRM, tick); 2027889Seric if (EventQueue != NULL) 20312635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 2047358Seric } 2057690Seric /* 2067690Seric ** SLEEP -- a version of sleep that works with this stuff 2077690Seric ** 2087690Seric ** Because sleep uses the alarm facility, I must reimplement 2097690Seric ** it here. 2107690Seric ** 2117690Seric ** Parameters: 2127690Seric ** intvl -- time to sleep. 2137690Seric ** 2147690Seric ** Returns: 2157690Seric ** none. 2167690Seric ** 2177690Seric ** Side Effects: 2187690Seric ** waits for intvl time. However, other events can 2197690Seric ** be run during that interval. 2207690Seric */ 2217690Seric 2227690Seric static bool SleepDone; 2237690Seric 2247690Seric sleep(intvl) 22525615Seric unsigned int intvl; 2267690Seric { 2277690Seric extern endsleep(); 2287690Seric 2297757Seric if (intvl == 0) 2307757Seric return; 2317690Seric SleepDone = FALSE; 23212635Seric (void) setevent((time_t) intvl, endsleep, 0); 2337690Seric while (!SleepDone) 2347690Seric pause(); 2357690Seric } 2367690Seric 2377690Seric static 2387690Seric endsleep() 2397690Seric { 2407690Seric SleepDone = TRUE; 2417690Seric } 242