File: | d/tclsched.c |
Warning: | line 295, column 13 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * The contents of this file are subject to the Mozilla Public License |
3 | * Version 1.1 (the "License"); you may not use this file except in |
4 | * compliance with the License. You may obtain a copy of the License at |
5 | * http://mozilla.org/. |
6 | * |
7 | * Software distributed under the License is distributed on an "AS IS" |
8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
9 | * the License for the specific language governing rights and limitations |
10 | * under the License. |
11 | * |
12 | * The Original Code is AOLserver Code and related documentation |
13 | * distributed by AOL. |
14 | * |
15 | * The Initial Developer of the Original Code is America Online, |
16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, |
17 | * Inc. All Rights Reserved. |
18 | * |
19 | * Alternatively, the contents of this file may be used under the terms |
20 | * of the GNU General Public License (the "GPL"), in which case the |
21 | * provisions of GPL are applicable instead of those above. If you wish |
22 | * to allow use of your version of this file only under the terms of the |
23 | * GPL and not to allow others to use your version of this file under the |
24 | * License, indicate your decision by deleting the provisions above and |
25 | * replace them with the notice and other provisions required by the GPL. |
26 | * If you do not delete the provisions above, a recipient may use your |
27 | * version of this file under either the License or the GPL. |
28 | */ |
29 | |
30 | |
31 | /* |
32 | * tclsched.c -- |
33 | * |
34 | * Implement scheduled procs in Tcl. |
35 | */ |
36 | |
37 | #include "nsd.h" |
38 | |
39 | /* |
40 | * Static variables defined in this file. |
41 | */ |
42 | |
43 | static Ns_ObjvValueRange dayRange = {0, 6}; |
44 | static Ns_ObjvValueRange hourRange = {0, 23}; |
45 | static Ns_ObjvValueRange minuteRange = {0, 59}; |
46 | static const Ns_ObjvTimeRange posTimeRange = {{0, 1}, {LONG_MAX9223372036854775807L, 0}}; |
47 | static const Ns_ObjvTimeRange nonnegTimeRange = {{0, 0}, {LONG_MAX9223372036854775807L, 0}}; |
48 | |
49 | /* |
50 | * Local functions defined in this file. |
51 | */ |
52 | |
53 | static Ns_SchedProc FreeSchedCallback; |
54 | static int SchedObjCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const* objv, char cmd); |
55 | static int ReturnValidId(Tcl_Interp *interp, int id, Ns_TclCallback *cbPtr) |
56 | NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1))) NS_GNUC_NONNULL(3)__attribute__((__nonnull__(3))); |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | /* |
63 | *---------------------------------------------------------------------- |
64 | * |
65 | * NsTclAfterObjCmd -- |
66 | * |
67 | * Implements "ns_after". |
68 | * |
69 | * Results: |
70 | * Tcl result. |
71 | * |
72 | * Side effects: |
73 | * See docs. |
74 | * |
75 | *---------------------------------------------------------------------- |
76 | */ |
77 | |
78 | int |
79 | NsTclAfterObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
80 | { |
81 | Tcl_Obj *scriptObj; |
82 | Ns_Time *interval; |
83 | int remain = 0, result = TCL_OK0; |
84 | Ns_ObjvSpec args[] = { |
85 | {"interval", Ns_ObjvTime, &interval, (void*)&nonnegTimeRange}, |
86 | {"script", Ns_ObjvObj, &scriptObj, NULL((void*)0)}, |
87 | {"?args", Ns_ObjvArgs, &remain, NULL((void*)0)}, |
88 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
89 | }; |
90 | |
91 | if (Ns_ParseObjv(NULL((void*)0), args, interp, 1, objc, objv) != NS_OK) { |
92 | result = TCL_ERROR1; |
93 | |
94 | } else { |
95 | int id; |
96 | Ns_TclCallback *cbPtr = Ns_TclNewCallback(interp, (ns_funcptr_t)NsTclSchedProc, |
97 | scriptObj, objc - 3, objv + 3); |
98 | id = Ns_After(interval, NsTclSchedProc, cbPtr, (ns_funcptr_t)Ns_TclFreeCallback); |
99 | result = ReturnValidId(interp, id, cbPtr); |
100 | } |
101 | |
102 | return result; |
103 | } |
104 | |
105 | |
106 | /* |
107 | *---------------------------------------------------------------------- |
108 | * |
109 | * SchedObjCmd -- |
110 | * |
111 | * Implements "ns_unschedule_proc", "ns_cancel", "ns_pause", and |
112 | * "ns_resume". |
113 | * |
114 | * Results: |
115 | * Tcl result. |
116 | * |
117 | * Side effects: |
118 | * See docs. |
119 | * |
120 | *---------------------------------------------------------------------- |
121 | */ |
122 | |
123 | static int |
124 | SchedObjCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const* objv, char cmd) |
125 | { |
126 | int id, result = TCL_OK0; |
127 | |
128 | if (objc != 2) { |
129 | Tcl_WrongNumArgs(interp, 1, objv, "id"); |
130 | result = TCL_ERROR1; |
131 | |
132 | } else if (Tcl_GetIntFromObj(interp, objv[1], &id) != TCL_OK0) { |
133 | result = TCL_ERROR1; |
134 | |
135 | } else { |
136 | bool_Bool ok; |
137 | |
138 | switch (cmd) { |
139 | case 'c': |
140 | Ns_LogDeprecated(objv, 1, "ns_unschedule_proc ...", NULL((void*)0)); |
141 | ok = Ns_Cancel(id); |
142 | break; |
143 | case 'u': |
144 | ok = Ns_Cancel(id); |
145 | break; |
146 | case 'p': |
147 | ok = Ns_Pause(id); |
148 | break; |
149 | case 'r': |
150 | ok = Ns_Resume(id); |
151 | break; |
152 | default: |
153 | result = TCL_ERROR1; |
154 | ok = NS_FALSE0; |
155 | Ns_Log(Error, "unexpected code '%c' passed to SchedObjCmd", cmd); |
156 | break; |
157 | } |
158 | |
159 | if (result == TCL_OK0) { |
160 | Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ok)Tcl_NewIntObj((ok)!=0)); |
161 | } |
162 | } |
163 | return result; |
164 | } |
165 | |
166 | int |
167 | NsTclCancelObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
168 | { |
169 | return SchedObjCmd(interp, objc, objv, 'c'); |
170 | } |
171 | |
172 | int |
173 | NsTclPauseObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
174 | { |
175 | return SchedObjCmd(interp, objc, objv, 'p'); |
176 | } |
177 | |
178 | int |
179 | NsTclResumeObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
180 | { |
181 | return SchedObjCmd(interp, objc, objv, 'r'); |
182 | } |
183 | |
184 | int |
185 | NsTclUnscheduleObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
186 | { |
187 | return SchedObjCmd(interp, objc, objv, 'u'); |
188 | } |
189 | |
190 | |
191 | /* |
192 | *---------------------------------------------------------------------- |
193 | * |
194 | * NsTclSchedDailyObjCmd -- |
195 | * |
196 | * Implements "ns_schedule_daily". |
197 | * |
198 | * Results: |
199 | * Tcl result. |
200 | * |
201 | * Side effects: |
202 | * See docs. |
203 | * |
204 | *---------------------------------------------------------------------- |
205 | */ |
206 | |
207 | int |
208 | NsTclSchedDailyObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
209 | { |
210 | Tcl_Obj *scriptObj; |
211 | int hour = 0, minute = 0, remain = 0, once = 0, thread = 0, result; |
212 | Ns_ObjvSpec opts[] = { |
213 | {"-once", Ns_ObjvBool, &once, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
214 | {"-thread", Ns_ObjvBool, &thread, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
215 | {"--", Ns_ObjvBreak, NULL((void*)0), NULL((void*)0)}, |
216 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
217 | }; |
218 | Ns_ObjvSpec args[] = { |
219 | {"hour", Ns_ObjvInt, &hour, &hourRange}, |
220 | {"minute", Ns_ObjvInt, &minute, &minuteRange}, |
221 | {"script", Ns_ObjvObj, &scriptObj, NULL((void*)0)}, |
222 | {"?args", Ns_ObjvArgs, &remain, NULL((void*)0)}, |
223 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
224 | }; |
225 | |
226 | if (Ns_ParseObjv(opts, args, interp, 1, objc, objv) != NS_OK) { |
227 | result = TCL_ERROR1; |
228 | |
229 | } else { |
230 | unsigned int flags = 0u; |
231 | int id; |
232 | Ns_TclCallback *cbPtr; |
233 | |
234 | if (once != 0) { |
235 | flags |= NS_SCHED_ONCE0x02u; |
236 | } |
237 | if (thread != 0) { |
238 | flags |= NS_SCHED_THREAD0x01u; |
239 | } |
240 | cbPtr = Ns_TclNewCallback(interp, (ns_funcptr_t)NsTclSchedProc, |
241 | scriptObj, remain, objv + (objc - remain)); |
242 | id = Ns_ScheduleDaily(NsTclSchedProc, cbPtr, flags, hour, minute, |
243 | FreeSchedCallback); |
244 | |
245 | result = ReturnValidId(interp, id, cbPtr); |
246 | } |
247 | return result; |
248 | } |
249 | |
250 | |
251 | /* |
252 | *---------------------------------------------------------------------- |
253 | * |
254 | * NsTclSchedWeeklyObjCmd -- |
255 | * |
256 | * Implements "ns_sched_weekly". |
257 | * |
258 | * Results: |
259 | * Tcl result. |
260 | * |
261 | * Side effects: |
262 | * See docs. |
263 | * |
264 | *---------------------------------------------------------------------- |
265 | */ |
266 | |
267 | int |
268 | NsTclSchedWeeklyObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
269 | { |
270 | Tcl_Obj *scriptObj; |
271 | int day = 0, hour = 0, minute = 0, remain = 0, once = 0, thread = 0, result; |
272 | Ns_ObjvSpec opts[] = { |
273 | {"-once", Ns_ObjvBool, &once, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
274 | {"-thread", Ns_ObjvBool, &thread, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
275 | {"--", Ns_ObjvBreak, NULL((void*)0), NULL((void*)0)}, |
276 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
277 | }; |
278 | Ns_ObjvSpec args[] = { |
279 | {"day", Ns_ObjvInt, &day, &dayRange}, |
280 | {"hour", Ns_ObjvInt, &hour, &hourRange}, |
281 | {"minute", Ns_ObjvInt, &minute, &minuteRange}, |
282 | {"script", Ns_ObjvObj, &scriptObj, NULL((void*)0)}, |
283 | {"?args", Ns_ObjvArgs, &remain, NULL((void*)0)}, |
284 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
285 | }; |
286 | if (Ns_ParseObjv(opts, args, interp, 1, objc, objv) != NS_OK) { |
287 | result = TCL_ERROR1; |
288 | |
289 | } else { |
290 | unsigned int flags = 0u; |
291 | Ns_TclCallback *cbPtr; |
292 | int id; |
293 | |
294 | if (once != 0) { |
295 | flags |= NS_SCHED_ONCE0x02u; |
This statement is never executed | |
296 | } |
297 | if (thread != 0) { |
298 | flags |= NS_SCHED_THREAD0x01u; |
299 | } |
300 | |
301 | cbPtr = Ns_TclNewCallback(interp, (ns_funcptr_t)NsTclSchedProc, |
302 | scriptObj, remain, objv + (objc - remain)); |
303 | id = Ns_ScheduleWeekly(NsTclSchedProc, cbPtr, flags, day, hour, minute, |
304 | FreeSchedCallback); |
305 | |
306 | result = ReturnValidId(interp, id, cbPtr); |
307 | } |
308 | |
309 | return result; |
310 | } |
311 | |
312 | |
313 | /* |
314 | *---------------------------------------------------------------------- |
315 | * |
316 | * NsTclSchedObjCmd -- |
317 | * |
318 | * Implements "ns_schedule_proc". |
319 | * |
320 | * Results: |
321 | * Tcl result. |
322 | * |
323 | * Side effects: |
324 | * See docs. |
325 | * |
326 | *---------------------------------------------------------------------- |
327 | */ |
328 | |
329 | int |
330 | NsTclSchedObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv) |
331 | { |
332 | Tcl_Obj *scriptObj; |
333 | Ns_Time *intervalPtr; |
334 | int remain = 0, once = 0, thread = 0, result = TCL_OK0; |
335 | Ns_ObjvSpec opts[] = { |
336 | {"-once", Ns_ObjvBool, &once, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
337 | {"-thread", Ns_ObjvBool, &thread, INT2PTR(NS_TRUE)((void *)(intptr_t)(1))}, |
338 | {"--", Ns_ObjvBreak, NULL((void*)0), NULL((void*)0)}, |
339 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
340 | }; |
341 | Ns_ObjvSpec args[] = { |
342 | {"interval", Ns_ObjvTime, &intervalPtr, (void*)&nonnegTimeRange}, |
343 | {"script", Ns_ObjvObj, &scriptObj, NULL((void*)0)}, |
344 | {"?args", Ns_ObjvArgs, &remain, NULL((void*)0)}, |
345 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} |
346 | }; |
347 | if (Ns_ParseObjv(opts, args, interp, 1, objc, objv) != NS_OK) { |
348 | result = TCL_ERROR1; |
349 | |
350 | } else { |
351 | unsigned int flags = 0u; |
352 | |
353 | if (thread != 0) { |
354 | flags |= NS_SCHED_THREAD0x01u; |
355 | } |
356 | if (once != 0) { |
357 | flags |= NS_SCHED_ONCE0x02u; |
358 | } else { |
359 | result = Ns_CheckTimeRange(interp, "interval", &posTimeRange, intervalPtr); |
360 | } |
361 | |
362 | if (result == TCL_OK0) { |
363 | Ns_TclCallback *cbPtr; |
364 | int id; |
365 | |
366 | cbPtr = Ns_TclNewCallback(interp, (ns_funcptr_t)NsTclSchedProc, |
367 | scriptObj, remain, objv + (objc - remain)); |
368 | id = Ns_ScheduleProcEx(NsTclSchedProc, cbPtr, flags, intervalPtr, FreeSchedCallback); |
369 | |
370 | result = ReturnValidId(interp, id, cbPtr); |
371 | } |
372 | } |
373 | return result; |
374 | } |
375 | |
376 | |
377 | /* |
378 | *---------------------------------------------------------------------- |
379 | * |
380 | * NsTclSchedProc -- |
381 | * |
382 | * Callback for a Tcl scheduled proc. |
383 | * |
384 | * Results: |
385 | * None. |
386 | * |
387 | * Side effects: |
388 | * None. |
389 | * |
390 | *---------------------------------------------------------------------- |
391 | */ |
392 | |
393 | void |
394 | NsTclSchedProc(void *arg, int UNUSED(id)UNUSED_id __attribute__((__unused__))) |
395 | { |
396 | const Ns_TclCallback *cbPtr = arg; |
397 | |
398 | (void) Ns_TclEvalCallback(NULL((void*)0), cbPtr, NULL((void*)0), (char *)0L); |
399 | } |
400 | |
401 | |
402 | /* |
403 | *---------------------------------------------------------------------- |
404 | * |
405 | * ReturnValidId -- |
406 | * |
407 | * Update the interp result with the given schedule id if valid. |
408 | * Otherwise, free the callback and leave an error in the interp. |
409 | * |
410 | * Results: |
411 | * TCL_OK or TCL_ERROR. |
412 | * |
413 | * Side effects: |
414 | * None. |
415 | * |
416 | *---------------------------------------------------------------------- |
417 | */ |
418 | |
419 | static int |
420 | ReturnValidId(Tcl_Interp *interp, int id, Ns_TclCallback *cbPtr) |
421 | { |
422 | int result = TCL_OK0; |
423 | |
424 | NS_NONNULL_ASSERT(interp != NULL)((void) (0)); |
425 | NS_NONNULL_ASSERT(cbPtr != NULL)((void) (0)); |
426 | |
427 | if (id == (int)NS_ERROR) { |
428 | Ns_TclPrintfResult(interp, "could not schedule procedure"); |
429 | Ns_TclFreeCallback(cbPtr); |
430 | result = TCL_ERROR1; |
431 | |
432 | } else { |
433 | Tcl_SetObjResult(interp, Tcl_NewIntObj(id)); |
434 | } |
435 | |
436 | return result; |
437 | } |
438 | |
439 | |
440 | /* |
441 | *---------------------------------------------------------------------- |
442 | * |
443 | * FreeSchedCallback -- |
444 | * |
445 | * Free a callback used for scheduled commands. |
446 | * |
447 | * Results: |
448 | * None. |
449 | * |
450 | * Side effects: |
451 | * None. |
452 | * |
453 | *---------------------------------------------------------------------- |
454 | */ |
455 | |
456 | static void |
457 | FreeSchedCallback(void *arg, int UNUSED(id)UNUSED_id __attribute__((__unused__))) |
458 | { |
459 | Ns_TclFreeCallback(arg); |
460 | } |
461 | |
462 | /* |
463 | * Local Variables: |
464 | * mode: c |
465 | * c-basic-offset: 4 |
466 | * fill-column: 78 |
467 | * indent-tabs-mode: nil |
468 | * End: |
469 | */ |