snmp_alarm.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:6k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /* snmp_alarm.c: generic library based alarm timers for various parts
  2.    of an application */
  3. #include <config.h>
  4. #if HAVE_UNISTD_H
  5. #include <unistd.h>
  6. #endif
  7. #include <signal.h>
  8. #if HAVE_STDLIB_H
  9. #include <stdlib.h>
  10. #endif
  11. #if HAVE_NETINET_IN_H
  12. #include <netinet/in.h>
  13. #endif
  14. #if TIME_WITH_SYS_TIME
  15. # ifdef WIN32
  16. #  include <sys/timeb.h>
  17. # else
  18. #  include <time.h>
  19. # endif
  20. # include <time.h>
  21. #else
  22. # if HAVE_SYS_TIME_H
  23. #  include <sys/time.h>
  24. # else
  25. #  include <time.h>
  26. # endif
  27. #endif
  28. #if HAVE_WINSOCK_H
  29. #include <ip/socket.h>
  30. #endif
  31. #if HAVE_DMALLOC_H
  32. #include <dmalloc.h>
  33. #endif
  34. #include "asn1.h"
  35. #include "snmp_api.h"
  36. #include "snmp_debug.h"
  37. #include "tools.h"
  38. #include "default_store.h"
  39. #include "callback.h"
  40. #include "snmp_alarm.h"
  41. static struct snmp_alarm *thealarms;
  42. static int start_alarms = 0;
  43. static unsigned int regnum = 1;
  44. extern time_t time(time_t *);
  45. #undef SIGALRM
  46. int
  47. init_alarm_post_config(int majorid, int minorid, void *serverarg,
  48.                      void *clientarg) {
  49.   start_alarms = 1;
  50.   set_an_alarm();
  51.   return SNMPERR_SUCCESS;
  52. }
  53. void
  54. init_snmp_alarm(void) {
  55.   start_alarms = 0;
  56.   snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
  57.                          init_alarm_post_config, NULL);
  58. }
  59. void
  60. sa_update_entry(struct snmp_alarm *alrm) {
  61.   time_t t_temp;
  62.   if (alrm->seconds == 0) {
  63.     DEBUGMSGTL(("snmp_alarm_update_entry","illegal 0 length alarm timer specifiedn"));
  64.     return; /* illegal */
  65.   }
  66.   if (alrm->lastcall == 0) {
  67.     /* never been called yet, call seconds from now. */
  68.     alrm->lastcall = time(&t_temp);
  69.     alrm->nextcall = alrm->lastcall + alrm->seconds;
  70.   } else if (alrm->nextcall == 0) {
  71.     /* We've been called but not reset for the next? call */
  72.     if ((alrm->flags & SA_REPEAT) == SA_REPEAT) {
  73.       alrm->nextcall = alrm->lastcall + alrm->seconds;
  74.     } else {
  75.       /* single time call, remove it */
  76.       snmp_alarm_unregister(alrm->clientreg);
  77.     }
  78.   }
  79. }
  80. void
  81. snmp_alarm_unregister(unsigned int clientreg) {
  82.   struct snmp_alarm *sa_ptr, *alrm=NULL;
  83.   if (thealarms == NULL)
  84.     return;
  85.   if (clientreg == thealarms->clientreg) {
  86.     alrm = thealarms;
  87.     thealarms = alrm->next;
  88.   }
  89.   else {
  90.     for(sa_ptr = thealarms;
  91.         sa_ptr != NULL && sa_ptr->next->clientreg != clientreg;
  92.         sa_ptr = sa_ptr->next);
  93.     if (sa_ptr) {
  94.       if (sa_ptr->next) {
  95.         alrm = sa_ptr->next;
  96.         sa_ptr->next = sa_ptr->next->next;
  97.       }
  98.     }
  99.   }
  100.   /* Note:  do not free the clientarg, its the clients responsibility */
  101.   if (alrm)
  102.     free(alrm);
  103. }
  104.   
  105. struct snmp_alarm *
  106. sa_find_next(void) {
  107.   struct snmp_alarm *sa_ptr, *sa_ret = NULL;
  108.   for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_ptr->next) {
  109.     if (sa_ret == NULL || sa_ptr->nextcall < sa_ret->nextcall)
  110.       sa_ret = sa_ptr;
  111.   }
  112.   return sa_ret;
  113. }
  114. void
  115. run_alarms(void) {
  116.   int done=0;
  117.   struct snmp_alarm *sa_ptr;
  118.   time_t t_temp;
  119.   /* loop through everything we have repeatedly looking for the next
  120.      thing to call until all events are finally in the future again */
  121.   DEBUGMSGTL(("snmp_alarm_run_alarms","looking for alarms to run...n"));
  122.   while(done == 0) {
  123.     sa_ptr = sa_find_next();
  124.     if (sa_ptr == NULL)
  125.       return;
  126.     if (sa_ptr->nextcall <= time(&t_temp)) {
  127.       DEBUGMSGTL(("snmp_alarm_run_alarms","  running alarm %dn",
  128.                   sa_ptr->clientreg));
  129.       (*(sa_ptr->thecallback))(sa_ptr->clientreg, sa_ptr->clientarg);
  130.       DEBUGMSGTL(("snmp_alarm_run_alarms","     ... donen"));
  131.       sa_ptr->lastcall = time(&t_temp);
  132.       sa_ptr->nextcall = 0;
  133.       sa_update_entry(sa_ptr);
  134.     } else {
  135.       done = 1;
  136.     }
  137.   }
  138.   DEBUGMSGTL(("snmp_alarm_run_alarms","Done.n"));
  139. }
  140. RETSIGTYPE
  141. alarm_handler(int a) {
  142.   run_alarms();
  143.   set_an_alarm();
  144. }
  145. int
  146. get_next_alarm_delay_time(void) {
  147.   struct snmp_alarm *sa_ptr;
  148.   int nexttime = 0;
  149.   time_t t_temp;
  150.   sa_ptr = sa_find_next();
  151.   if (sa_ptr) {
  152.     nexttime = sa_ptr->nextcall - time(&t_temp);
  153.     if (nexttime <= 0)
  154.       nexttime = 1; /* occurred already, return 1 second */
  155.   }
  156.   return nexttime;
  157. }
  158. void
  159. set_an_alarm(void) {
  160.   int nexttime = get_next_alarm_delay_time();
  161.   
  162.   /* we don't use signals if they asked us nicely not to.  It's
  163.      expected they'll check the next alarm time and do their own
  164.      calling of run_alarms(). */
  165.   if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG) && nexttime) {
  166. #ifndef WIN32
  167. #ifdef SIGALRM
  168.     alarm(nexttime);
  169.     DEBUGMSGTL(("snmp_alarm_set_an_alarm","setting an alarm for %d seconds from nown",nexttime));
  170.     signal(SIGALRM, alarm_handler);
  171. #endif /* SIGALRM */
  172. #endif
  173.   } else {
  174.     DEBUGMSGTL(("snmp_alarm_set_an_alarm","no alarms found to handlen"));
  175.   }
  176. }
  177. unsigned int
  178. snmp_alarm_register(unsigned int when, unsigned int flags,
  179.                     SNMPAlarmCallback *thecallback, void *clientarg) {
  180.   struct snmp_alarm **sa_pptr;
  181.   if (thealarms != NULL) {
  182.     for(sa_pptr = &thealarms; (*sa_pptr) != NULL;
  183.         sa_pptr = &((*sa_pptr)->next));
  184.   } else {
  185.     sa_pptr = &thealarms;
  186.   }
  187.   *sa_pptr = SNMP_MALLOC_STRUCT(snmp_alarm);
  188.   if (*sa_pptr == NULL)
  189.     return 0;
  190.   (*sa_pptr)->seconds = when;
  191.   (*sa_pptr)->flags = flags;
  192.   (*sa_pptr)->clientarg = clientarg;
  193.   (*sa_pptr)->thecallback = thecallback;
  194.   (*sa_pptr)->clientreg = regnum++;
  195.   sa_update_entry(*sa_pptr);
  196.   DEBUGMSGTL(("snmp_alarm_register","registered alarm %d, secends=%d, flags=%dn",
  197.               (*sa_pptr)->clientreg, (*sa_pptr)->seconds, (*sa_pptr)->flags));
  198.   if (start_alarms)
  199.     set_an_alarm();
  200.   return (*sa_pptr)->clientreg;