1: /*
2: * $Id: events.c,v 1.5 2025/04/13 04:22:43 snw Exp $
3: * event framework
4: *
5: *
6: * Author: Serena Willis <snw@coherent-logic.com>
7: * Copyright (C) 1998 MUG Deutschland
8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
26: * $Log: events.c,v $
27: * Revision 1.5 2025/04/13 04:22:43 snw
28: * Fix snprintf calls
29: *
30: * Revision 1.4 2025/03/22 18:43:54 snw
31: * Make STRLEN 255 chars and add BIGSTR macro for larger buffers
32: *
33: * Revision 1.3 2025/03/09 19:14:24 snw
34: * First phase of REUSE compliance and header reformat
35: *
36: *
37: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
38: * SPDX-License-Identifier: AGPL-3.0-or-later
39: **/
40:
41: #include <stdlib.h>
42: #include <string.h>
43:
44: #include "mpsdef.h"
45: #include "events.h"
46: #include "freem.h"
47: #include "mref.h"
48:
49:
50: short evt_async_enabled = FALSE;
51: short evt_async_restore = FALSE;
52: short evt_async_initial = FALSE;
53:
54: short evt_queue_rear = -1;
55: short evt_queue_front = -1;
56:
57: evt_entry *evt_queue[EVT_QLENGTH];
58: short evt_status[EVT_MAX];
59: int evt_blocks[EVT_MAX];
60: int evt_depth;
61:
62: void evt_init (void)
63: {
64: register int i;
65:
66: for(i = 0; i < EVT_MAX; i++) {
67: evt_status[i] = EVT_S_DISABLED;
68: evt_blocks[i] = 0;
69: }
70:
71: evt_async_enabled = FALSE;
72: evt_depth = 0;
73: }
74:
75: int evt_ablock (short evt_class)
76: {
77: register int i;
78: int unblocked_evt_count = 0;
79:
80: evt_blocks[evt_class]++;
81:
82: for (i = 0; i < EVT_MAX; i++) {
83: if (evt_blocks[i] == 0) unblocked_evt_count++;
84: }
85:
86: if (unblocked_evt_count == 0) evt_async_enabled = FALSE;
87:
88: return evt_blocks[evt_class];
89: }
90:
91: int evt_aunblock (short evt_class)
92: {
93: register int i;
94: int unblocked_evt_count = 0;
95:
96: if (evt_blocks[evt_class]) evt_blocks[evt_class]--;
97:
98: for (i = 0; i < EVT_MAX; i++) {
99: if (evt_blocks[i] == 0) unblocked_evt_count++;
100: }
101:
102: if (unblocked_evt_count) evt_async_enabled = TRUE;
103:
104: return evt_blocks[i - 1];
105: }
106:
107: int evt_enqueue (char *event_id, short evt_class, short interrupt)
108: {
109: evt_entry *e = malloc (sizeof (evt_entry));
110: NULLPTRCHK(e,"evt_enqueue");
111:
112: if (!evt_registered (event_id, evt_class)) {
113: free (e);
114: return -1;
115: }
116:
117: strncpy (e->event_id, event_id, 256);
118: e->evt_class = evt_class;
119:
120: if (evt_queue_rear == EVT_QLENGTH - 1) {
121: /* queue overflow */
122: free (e);
123: return -1;
124: }
125:
126: if (evt_queue_front == -1) evt_queue_front = 0;
127:
128: evt_queue[++evt_queue_rear] = e;
129:
130: if (interrupt && (evt_blocks[evt_class] == 0)) {
131: merr_raise (ASYNC);
132: }
133:
134: return evt_queue_rear;
135: }
136:
137: evt_entry *evt_dequeue (void)
138: {
139: evt_entry *e;
140:
141: if (evt_queue_front == -1 || evt_queue_front > evt_queue_rear) {
142: /* queue underflow */
143: return NULL;
144: }
145:
146: e = evt_queue[evt_queue_front++];
147:
148: return e;
149: }
150:
151:
152: char *evt_class_name (evt_entry *e) {
153:
154: char *evt_name = malloc (15 * sizeof (char));
155: NULLPTRCHK(evt_name,"evt_class_name");
156:
157: switch (e->evt_class) {
158:
159: case EVT_CLS_COMM:
160: strcpy (evt_name, "COMM");
161: break;
162:
163: case EVT_CLS_HALT:
164: strcpy (evt_name, "HALT");
165: break;
166:
167: case EVT_CLS_IPC:
168: strcpy (evt_name, "IPC");
169: break;
170:
171: case EVT_CLS_INTERRUPT:
172: strcpy (evt_name, "INTERRUPT");
173: break;
174:
175: case EVT_CLS_POWER:
176: strcpy (evt_name, "POWER");
177: break;
178:
179: case EVT_CLS_TIMER:
180: strcpy (evt_name, "TIMER");
181: break;
182:
183: case EVT_CLS_USER:
184: strcpy (evt_name, "USER");
185: break;
186:
187: case EVT_CLS_WAPI:
188: strcpy (evt_name, "WAPI");
189: break;
190:
191: case EVT_CLS_TRIGGER:
192: strcpy (evt_name, "TRIGGER");
193: break;
194:
195: }
196:
197: return evt_name;
198:
199: }
200:
201: char *evt_class_name_c (int c) {
202:
203: char *evt_name = malloc (15 * sizeof (char));
204: NULLPTRCHK(evt_name,"evt_class_name_c");
205:
206: switch (c) {
207:
208: case EVT_CLS_COMM:
209: strcpy (evt_name, "COMM");
210: break;
211:
212: case EVT_CLS_HALT:
213: strcpy (evt_name, "HALT");
214: break;
215:
216: case EVT_CLS_IPC:
217: strcpy (evt_name, "IPC");
218: break;
219:
220: case EVT_CLS_INTERRUPT:
221: strcpy (evt_name, "INTERRUPT");
222: break;
223:
224: case EVT_CLS_POWER:
225: strcpy (evt_name, "POWER");
226: break;
227:
228: case EVT_CLS_TIMER:
229: strcpy (evt_name, "TIMER");
230: break;
231:
232: case EVT_CLS_USER:
233: strcpy (evt_name, "USER");
234: break;
235:
236: case EVT_CLS_WAPI:
237: strcpy (evt_name, "WAPI");
238: break;
239:
240: case EVT_CLS_TRIGGER:
241: strcpy (evt_name, "TRIGGER");
242: break;
243:
244: }
245:
246: return evt_name;
247:
248: }
249:
250: int evt_get_handlers (char *buf) {
251:
252: char *t_key;
253: char *class_name;
254: char *t_buf;
255: freem_ref_t *r;
256: freem_ref_t *rs;
257: char pid_s[10];
258: int ct;
259: evt_entry *e;
260:
261: class_name = malloc (STRLEN * sizeof (char));
262: NULLPTRCHK(class_name,"evt_get_handlers");
263:
264: t_buf = malloc (STRLEN * sizeof (char));
265: NULLPTRCHK(t_buf,"evt_get_handlers");
266:
267: r = malloc (sizeof (freem_ref_t));
268: NULLPTRCHK(r,"evt_get_handlers");
269:
270: rs = malloc (sizeof (freem_ref_t));
271: NULLPTRCHK(rs,"evt_get_handlers");
272:
273: ct = 0;
274: t_buf[0] = '\201';
275:
276: mref_init (r, MREF_RT_SSVN, "^$JOB");
277: mref_init (rs, MREF_RT_SSVN, "^$SYSTEM");
278:
279: snprintf (pid_s, sizeof (pid_s) - 1, "%d", pid);
280:
281:
282: while ((e = evt_dequeue ()) != NULL) {
283:
284: if (evt_status[e->evt_class] > EVT_S_DISABLED) {
285: class_name = evt_class_name (e);
286:
287: mref_set_subscript (r, 0, pid_s);
288: mref_set_subscript (r, 1, "EVENT");
289: mref_set_subscript (r, 2, class_name);
290: mref_set_subscript (r, 3, e->event_id);
291:
292: t_key = mref_to_internal (r);
293: ssvn (get_sym, t_key, t_buf);
294: free (t_key);
295: stcnv_m2c (t_buf);
296:
297: if (strlen (t_buf) > 0) {
298:
299: ct++;
300:
301: strcat (buf, t_buf);
302: strcat (buf, ",");
303: }
304:
305: mref_set_subscript (rs, 0, "EVENT");
306: mref_set_subscript (rs, 1, class_name);
307: mref_set_subscript (rs, 2, e->event_id);
308:
309: t_key = mref_to_internal (rs);
310: ssvn (get_sym, t_key, t_buf);
311: free (t_key);
312: stcnv_m2c (t_buf);
313:
314: if (strlen (t_buf) > 0) {
315:
316: ct++;
317:
318: strcat (buf, t_buf);
319: strcat (buf, ",");
320: }
321:
322: }
323:
324: free (e);
325:
326: }
327:
328: if (ct) {
329: buf[strlen (buf) - 1] = NUL;
330: }
331: else {
332: buf[0] = NUL;
333: }
334:
335: free (r);
336: free (rs);
337: free (class_name);
338: free (t_buf);
339:
340: return ct;
341: }
342:
343: short evt_registered (char *event_id, short evt_class)
344: {
345: char *t_key;
346: char *class_name;
347: char *t_buf;
348: freem_ref_t *r;
349: freem_ref_t *rs;
350: char pid_s[10];
351: int ct;
352:
353: t_key = malloc (STRLEN * sizeof (char));
354: NULLPTRCHK(t_key,"evt_registered");
355:
356: class_name = malloc (STRLEN * sizeof (char));
357: NULLPTRCHK(class_name,"evt_registered");
358:
359: t_buf = malloc (STRLEN * sizeof (char));
360: NULLPTRCHK(t_buf,"evt_registered");
361:
362:
363: r = malloc (sizeof (freem_ref_t));
364: NULLPTRCHK(r,"evt_registered");
365:
366: rs = malloc (sizeof (freem_ref_t));
367: NULLPTRCHK(rs,"evt_registered");
368:
369: ct = 0;
370: t_buf[0] = '\201';
371:
372: mref_init (r, MREF_RT_SSVN, "^$JOB");
373:
374: snprintf (pid_s, sizeof (pid_s) - 1, "%d", pid);
375:
376: class_name = evt_class_name_c (evt_class);
377:
378: mref_set_subscript (r, 0, pid_s);
379: mref_set_subscript (r, 1, "EVENT");
380: mref_set_subscript (r, 2, class_name);
381: mref_set_subscript (r, 3, event_id);
382:
383: t_key = mref_to_internal (r);
384:
385: ssvn (get_sym, t_key, t_buf);
386: stcnv_m2c (t_buf);
387:
388: if (strlen (t_buf) > 0) ct++;
389:
390: mref_init (rs, MREF_RT_SSVN, "^$SYSTEM");
391:
392: mref_set_subscript (rs, 0, "EVENT");
393: mref_set_subscript (rs, 1, class_name);
394: mref_set_subscript (rs, 2, event_id);
395:
396: t_key = mref_to_internal (rs);
397:
398: ssvn (get_sym, t_key, t_buf);
399: stcnv_m2c (t_buf);
400:
401: if (strlen (t_buf) > 0) ct++;
402:
403: free (r);
404: free (rs);
405: free (t_key);
406: free (class_name);
407: free (t_buf);
408:
409: return (ct > 0) ? TRUE : FALSE;
410: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>