OSDN Git Service

added a null pointer check in alarm
[opengatem/opengatem.git] / mngsrc / alarms.c
1 /*************************************************
2 OpengateM - MAC address authentication system 
3   module for multi-alarms 
4
5 Copyright (C) 2006 Opengate Project Team
6 Written by Yoshiaki Watanabe
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
22 Email: watanaby@is.saga-u.ac.jp
23 **************************************************/
24
25 /*** alarms example ****
26 This case, the alarms are ringed after 5 and 8 seconds
27
28 int main(void)
29 {
30   AddAlarm("alarm1", 8, FALSE, func1);
31   AddAlarm("alarm2", 5, FALSE, func2);
32   EnableAlarm();
33  }
34 void func1(int signo){
35   printf("func1 is called at %d\n",time(NULL));
36 }
37 void func2(int signo){
38   printf("func2 is called at %d\n",time(NULL));
39 }
40 **********/
41
42 #include        "opengatemmng.h"
43
44 typedef struct alarm{ /* an item in the alarm list */
45   char name[WORDMAXLN]; /* the alarm name */
46   int timeout;          /* the duration(sec) to timeout */
47   int unixtime;         /* the unix time to timeout */
48   int preceding;         /* if true, precede to other alarms */
49   Sigfunc *func;       /* function to call at timeout */
50   struct alarm *next;  /* the next item in list */
51 } Alarm;
52
53 int addAlarm(char *name, int timeout, int preceding, Sigfunc *func);
54 int removeAlarm(char *name);
55 int delAlarmListItem(Alarm *pDel);
56 int enableAlarm(void);
57 int disableAlarm(void);
58 void alarmSigFunc(int signo);
59
60 static Sigfunc *defaultSigfunc;
61 static Alarm *pRunningAlarm=NULL;
62 static Alarm *pAlarmTop=NULL;
63
64
65 /***************************************************
66 Add a new alarm named <name>, which calls 
67 function <func> after <timeout> seconds
68 If <preceding> is TRUE, the alarm precedes to other alarms
69 (the alarm has first priority. other alarms are delayed after the alarm)
70 Multiple alarms can be registered in the alarm list
71 At timeout, the alarm is removed from the alarm list
72 after the calling addAlarm, alarms are disabled
73 ***************************************************/
74 int addAlarm(char *name, int timeout, int preceding, Sigfunc *func)
75 {
76   Alarm *pNew;
77   Alarm *p;
78   Alarm *pPrev;
79
80   /* disable Alarm */
81   disableAlarm();
82
83   /* memory allocate for the alarm list item */
84   if((pNew = (Alarm *) malloc(sizeof(Alarm))) == NULL){
85     //   err_msg("ERR at %s#%d: malloc error",__FILE__,__LINE__);
86     return -1;
87   }
88
89   /* set the item info */
90   strlcpy(pNew->name, name, WORDMAXLN);
91   pNew->timeout = timeout;
92   pNew->unixtime = time(NULL) + timeout;
93   pNew->preceding = preceding;
94   pNew->func = func;
95   
96   /* if list is null, add as first item */
97   if(pAlarmTop ==NULL){
98     pAlarmTop = pNew;
99     pNew->next =NULL;
100   }
101
102   /* if preceding alarm, insert it at the top */
103   else if(preceding==TRUE){
104     pNew->next =pAlarmTop;
105     pAlarmTop = pNew;
106   }
107
108   /* if list is not null, search the item later than the new alarm 
109      and not a preceding alarm */
110   else{
111     p = pPrev = pAlarmTop;
112     while(p!=NULL){
113       if(p->unixtime >= pNew->unixtime && (p->preceding)==FALSE) break;
114       pPrev = p;
115       p = p->next;
116     }
117     
118     /* insert new item before the item */
119     if(p==pAlarmTop) pAlarmTop = pNew;
120     else pPrev->next = pNew;
121     pNew->next = p;
122   }
123
124   return 0;
125 }
126
127 /***************************************************
128 Remove alarm named <name> from the alarm list 
129 after the calling removeAlarm, alarms are disabled
130 ***************************************************/
131 int removeAlarm(char *name)
132 {
133   Alarm *p, *pPrev, *pDel;
134
135
136   /* disable alarm */
137   disableAlarm();
138
139   p=pAlarmTop;
140
141   if(name==NULL){
142     /* if name is NULL, all items are removed */
143     while(p!=NULL){
144       pDel = p;
145       p = p->next;
146       free(pDel);
147     }
148     pAlarmTop=NULL;
149   }
150
151   else{
152     /* scan alarm list to search name and delete it */
153     while(p!=NULL){
154       
155       /* if name is matched */
156       if(strncmp(name, p->name, WORDMAXLN)==0){
157         
158         /* delete the item */
159         delAlarmListItem(p);
160
161         /* exit (only the first match item is deleted)  */
162         break;
163       }
164       
165       /* if not matched, move to next item */
166       else{
167         pPrev = p;
168         p = p->next;
169       }
170     }
171   }
172
173   return 0;
174 }
175
176
177 /***************************************************
178 Enable alarm interupt
179 Delayed alarms by preceding alarm or by disable-mode 
180 are executed in this timing
181 ***************************************************/
182 int enableAlarm(void)
183 {
184   Alarm *p, *pDel;
185   int alarmemain=0;
186   int alarmSet=FALSE;
187
188   p=pAlarmTop;
189
190   /* scan all list */
191   while(p!=NULL){
192     
193     /* time remain to the timeout */
194     alarmemain = p->unixtime - time(NULL);
195     
196     /* if the time is the past */
197     if(alarmemain<=0){
198       
199       /* execute the function and save item for deletion */
200       p->func(0);
201       pDel = p;
202       
203       /* move to next item */
204       p = p->next;
205       
206       /* delete the list item */
207       delAlarmListItem(pDel);
208     }
209     
210     /* if the time is the future */
211     else{
212       /* save the alarm info */
213       pRunningAlarm = p;
214       
215       /* set signal alarm */
216       if(defaultSigfunc==NULL)defaultSigfunc=signalx(SIGALRM, alarmSigFunc);
217       else signalx(SIGALRM, alarmSigFunc);
218       alarm(alarmemain);
219       alarmSet=TRUE;
220
221       /* exit */
222       break;
223     }
224   }
225   return 0;
226 }
227
228
229 /***************************************************
230 Disable alarm interupt
231 Time count is not stoped in disable mode
232 ***************************************************/
233 int disableAlarm(void)
234 {
235   /* reset alarm */
236   signalx(SIGALRM, defaultSigfunc);
237   alarm(0);
238
239   return 0;
240 }
241
242 /***************************************************
243 Signal function for alarm signal
244 ***************************************************/
245 void alarmSigFunc(int signo)
246 {
247   /* some alarm must run at this point, but check it */
248   if(pRunningAlarm != NULL){
249
250     /* execute the function */
251     (pRunningAlarm->func)(signo);
252
253     /* remove the alarm */
254     delAlarmListItem(pRunningAlarm);
255   }
256
257   /* restart alarm */
258   enableAlarm();
259 }
260
261 /***************************************************
262 delete an item pointed by <p> in linked list
263 ***************************************************/
264 int delAlarmListItem(Alarm *pDel){
265   Alarm *p;
266   Alarm *pPrev;
267
268   /* if item or list is none, no proc */
269   if(pDel==NULL || pAlarmTop==NULL){
270     /* no proc */
271   }
272
273   /* if the item is top, change top to the next */
274   else if(pDel==pAlarmTop){
275     pAlarmTop = pDel->next;
276     free(pDel);
277   }
278
279   /* if the item is not top, search previous and link it to next */
280   else{
281     pPrev=pAlarmTop;
282     p=pAlarmTop->next;
283
284     while(p!=NULL){
285       if(p == pDel){
286         pPrev->next = p->next;
287         free(p);
288         break;
289       }
290       pPrev=p;
291       p=p->next;
292     }
293   }
294   return 0;
295 }
296
297 /***************************************************
298 list up registered alarms
299 upper alarm in the list has higher priority 
300 this is prepared for debug use
301 ***************************************************/
302 void listAlarm(void)
303 {
304   Alarm *p;
305
306   printf("TimeNow=%d\n",(int)time(NULL));
307
308   p=pAlarmTop;
309
310   while(p!=NULL){
311     printf("name=%s timeout=%d unixtime=%d preceding=%d\n", 
312            p->name, p->timeout, p->unixtime, p->preceding);
313     p=p->next;
314   }
315 }
316 /*****************************************************/
317 /*****************************************************/
318 int AddAlarm(char *name, int timeout, int preceding, Sigfunc *func){
319   int ret;
320
321   if(debug>1) err_msg("DEBUG:=>addAlarm(%s,%d, %d, %x)", 
322                     name, timeout, preceding, func);
323   ret=addAlarm(name, timeout, preceding, func);
324   if(debug>1) err_msg("DEBUG:(%d)<=addAlarm( )",ret);
325
326   return ret;
327 }
328
329 int RemoveAlarm(char *name){
330   int ret;
331
332   if(debug>1){
333     if(name==NULL) err_msg("DEBUG:=>removeAlarm(NULL)");
334     else           err_msg("DEBUG:=>removeAlarm(%s)", name);
335   }
336   ret=removeAlarm(name);
337   if(debug>1) err_msg("DEBUG:(%d)<=removeAlarm( )",ret);
338
339   return ret;
340 }
341
342 int EnableAlarm(void){
343   int ret;
344
345   if(debug>1) err_msg("DEBUG:=>enableAlarm()");
346   ret=enableAlarm();
347   if(debug>1) err_msg("DEBUG:(%d)<=enableAlarm( )",ret);
348
349   return ret;
350 }
351
352 int DisableAlarm(void){
353   int ret;
354
355   //  if(debug>1) err_msg("DEBUG:=>disableAlarm()");
356   ret=disableAlarm();
357   //  if(debug>1) err_msg("DEBUG:(%d)<=disableAlarm( )",ret);
358
359   return ret;
360 }