Annotation of freem/src/global_dispatch.c, revision 1.11
1.1 snw 1: /*
1.11 ! snw 2: * $Id: global_dispatch.c,v 1.10 2025/04/13 04:22:43 snw Exp $
1.1 snw 3: * global handler dispatch module
4: *
5: *
1.3 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.4 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 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: *
1.5 snw 26: * $Log: global_dispatch.c,v $
1.11 ! snw 27: * Revision 1.10 2025/04/13 04:22:43 snw
! 28: * Fix snprintf calls
! 29: *
1.10 snw 30: * Revision 1.9 2025/04/10 01:24:38 snw
31: * Remove C++ style comments
32: *
1.9 snw 33: * Revision 1.8 2025/04/09 19:52:02 snw
34: * Eliminate as many warnings as possible while building with -Wall
35: *
1.8 snw 36: * Revision 1.7 2025/04/09 15:16:50 snw
37: * Fix buffer overruns in mref_to_external and ssvn.c
38: *
1.7 snw 39: * Revision 1.6 2025/03/29 16:50:42 snw
40: * Back to cvs-current as version for development; temp fix for double-free issue in global_dispatch
41: *
1.6 snw 42: * Revision 1.5 2025/03/24 04:13:11 snw
43: * Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
44: *
1.5 snw 45: * Revision 1.4 2025/03/09 19:14:25 snw
46: * First phase of REUSE compliance and header reformat
47: *
1.4 snw 48: *
49: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
50: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 51: **/
52:
53: #include <stdlib.h>
54: #include <string.h>
55: #include <unistd.h>
56: #include <ctype.h>
57:
58: #include "mpsdef.h"
59: #include "mref.h"
60: #include "events.h"
61: #include "config.h"
62: #include "namespace.h"
63: #include "transact.h"
64: #include "mdebug.h"
65: #include "journal.h"
66: #include "iftab.h"
67: #include "shmmgr.h"
1.11 ! snw 68: #include "log.h"
1.1 snw 69:
70: void (*gbl_u)(short, char *, char *);
71: void (*gbl_s)(short, char *, char *);
72:
73: void global_set_engine(char ns, char *engine)
74: {
1.8 snw 75:
76: if (strcmp (engine, "BUILTIN") != 0) {
1.1 snw 77:
78: printf ("\r\nERROR: '%s' is not a valid global storage engine\r\n", engine);
79: merr_raise (M38);
80:
81: return;
82:
83: }
84:
85: switch (ns) {
86:
87: case 'u':
88: strcpy (gbl_u_engine, engine);
89:
90: if (strcmp (engine, "BUILTIN") == 0) {
91: gbl_u = &global_bltin;
92: }
93: else {
1.11 ! snw 94: logprintf (FM_LOG_WARNING, "global_set_engine: invalid global handler '%s' or FreeM built without '%s' global handler support", engine, engine);
! 95: logprintf (FM_LOG_WARNING, "global_set_engine: defaulting to 'BUILTIN' global handler for namespace '%s'", nsname);
1.1 snw 96: gbl_u = &global_bltin;
97: }
98:
99: break;
100:
101: case 's':
102: strcpy (gbl_s_engine, engine);
103:
104: if (strcmp (engine, "BUILTIN") == 0) {
105: gbl_s = &global_bltin;
106: }
107: else {
1.11 ! snw 108: logprintf (FM_LOG_WARNING, "global_set_engine: invalid global handler '%s' or FreeM built without '%s' global handler support", engine, engine);
! 109: logprintf (FM_LOG_WARNING, "global_set_engine: defaulting to 'BUILTIN' global handler for namespace 'SYSTEM'");
1.1 snw 110: gbl_s = &global_bltin;
111: }
112:
113: break;
114:
115: }
116:
117: merr_raise (OK);
118: return;
119:
120: }
121:
122: void global (short action, char *key, char *data)
123: {
124:
125: int ierr_sav = OK;
126:
127: char *ptr;
128: char name[256];
129: char old_gloplib[PATHLEN];
130: register int i = 0;
131: register int j = 0;
132: register char ch;
133:
134: char *old_ns;
135: char *old_value;
136: char *new_value;
137: char *tk_buf;
138: char *mapk_buf;
139: char *mapd_buf;
140: freem_ref_t *r;
141: short extref_flg;
142: short mapped_flg;
143:
144: /* variables for transaction-in-flight symbol table */
145: iftab *ift;
146: char tmpd[256];
147:
148: old_ns = (char *) malloc (STRLEN * sizeof (char));
149: NULLPTRCHK(old_ns,"global");
150:
151: old_value = (char *) malloc (STRLEN * sizeof (char));
152: NULLPTRCHK(old_value,"global");
153:
154: new_value = (char *) malloc (STRLEN * sizeof (char));
155: NULLPTRCHK(new_value,"global");
156:
157: tk_buf = (char *) malloc (STRLEN * sizeof (char));
158: NULLPTRCHK(tk_buf,"global");
159:
160: mapk_buf = (char *) malloc (STRLEN * sizeof (char));
161: NULLPTRCHK(mapk_buf,"global");
162:
163: mapd_buf = (char *) malloc (STRLEN * sizeof (char));
164: NULLPTRCHK(mapd_buf,"global");
165:
166: r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
167: NULLPTRCHK(r,"global");
168:
169: extref_flg = FALSE;
170: mapped_flg = FALSE;
171:
172: ptr = key;
173: if (key[1] != '$') {
174: while ((shm_config->hdr->tp_owner != pid) && (shm_config->hdr->tp_owner != 0)) {
175: sleep (1);
176: }
177: }
178:
179: stcpy (tk_buf, key);
180:
181: if (key[1] != '$') frm_process_alias (key);
182:
183: if (key[1] != '$') {
184: /* process mappings */
185: ierr_sav = OK;
186:
187: while ((ch = *(ptr++)) != DELIM && ch != EOL && i < 256) {
188: name[i++] = ch;
189: }
190:
191: name[i] = '\0';
192:
193: snprintf (mapk_buf, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202%s\201", name);
1.7 snw 194: symtab_shm (get_sym, mapk_buf, mapd_buf);
1.1 snw 195:
196: stcnv_m2c (mapd_buf);
197:
198: if (merr () == OK) {
199: mapped_flg = TRUE;
200: strncpy (old_ns, nsname, STRLEN - 1);
201: set_namespace (mapd_buf, 0);
202: strncpy (old_gloplib, gloplib, PATHLEN - 1);
203: strncpy (gloplib, glopath, PATHLEN - 1);
204: }
205: else {
206: merr_raise (OK);
207: }
208: }
209:
210: if (dbg_enable_watch && (action == set_sym)) dbg_fire_watch (key);
211:
212: if ((jnl_enabled == TRUE) && (key[1] != '$') && (tp_committing == FALSE)) {
213: switch (action) {
214:
215: case set_sym:
216: jnl_ent_write (JNLA_SET, key, data);
217: break;
218:
219: case kill_sym:
220: case killone:
221: jnl_ent_write (JNLA_KILL, key, data);
222: break;
223:
224: }
225: }
226:
227: /* If we are writing to a global in a transaction but not committing it,
228: queue up the operation at the current transaction level.*/
229: if ((tp_level > 0) && (action == set_sym ||
230: action == kill_sym ||
231: action == killone ||
232: action == merge_sym) && (tp_committing == FALSE)) {
233:
234: if (key[1] != '$') {
235: tp_add_op (FALSE, action, key, data);
236:
237: merr_raise (OK);
238: return;
239: }
240:
241: }
242:
243: /* in a transaction and retrieving */
244: if ((tp_level > 0) && (action == get_sym)) {
245:
246: /* check transactions-in-flight symbol table */
247: ift = iftab_retrieve (key, tmpd);
248:
249: if (ift != NULL) {
250:
251: if (ift->killed == TRUE) {
252: merr_raise (M7);
253: }
254: else {
255: stcpy (data, ift->data);
256: merr_raise (OK);
257: }
258:
259: return;
260: }
261:
262: /* if we got here, the node referenced by "key" has not been
263: modified in the current transaction, so we can proceed to
264: the normal disk block retrieval. */
265: }
266:
267:
268: mref_init (r, MREF_RT_GLOBAL, "^DUMMY");
269: internal_to_mref (r, key);
270:
271: if (rtn_dialect () == D_M77) {
272:
273: for (i = 0; i < r->subscript_count; i++) {
274: for (j = 0; j < strlen (r->subscripts[i]); j++) {
275:
276: ch = r->subscripts[i][j];
277:
278: if (!isdigit (ch)) {
279: merr_raise (NOSTAND);
280: return;
281: }
282:
283: }
284: }
285:
286: }
287:
288:
1.2 snw 289: if (r->name[1] == '|') {
1.1 snw 290:
291: /* this is an mdc-style extended reference */
292:
293: char old_code[512];
294: char *old_codptr;
295: char newns[256];
296: register int i = 0;
297: char *nsstart;
298: char *nssave;
299: char ch;
300: char *subprt;
301: extref_flg = TRUE;
302:
303: /* save off current interpreter state (code and codptr)
304: so we can call expr() without losing the plot */
305: stcpy (old_code, code);
306: old_codptr = codptr;
307:
308: /* save off the current namespace */
309: strncpy (old_ns, nsname, STRLEN - 1);
310:
311: nsstart = r->name + 2;
312: nssave = nsstart;
313:
314: /* grab everything between the vertical bars */
315: while ((ch = *(nsstart++)) != '|') {
316: newns[i++] = ch;
317: }
318:
319: newns[i] = '\0';
320:
321: /* load up the namespace expression into the code buffer */
322: strcpy (code, newns);
323: strcat (code, " ");
324: stcnv_c2m (code);
325:
326: /* point the code pointer at the beginning of code */
327: codptr = code;
328:
329: /* parse a string expression */
330: expr (STRING);
331:
332: /* expr (STRING) stores its result in argptr */
333: stcpy (newns, argptr);
334: stcnv_m2c (newns);
335:
336: /* restore interpreter state */
337: stcpy (code, old_code);
338: codptr = old_codptr;
339:
340: /* grab the rest of the gvn */
341: subprt = nssave + i + 1;
1.10 snw 342: sprintf (r->name, "^%s", subprt);
1.1 snw 343:
344: /* get a fully-formed key */
345: key = mref_to_internal (r);
346:
347: /* switch to the namespace specified in the extended reference */
348: set_namespace (newns, 0);
349: if (merr () > OK) {
350:
351: if (merr () == M26) {
352: /* if namespace doesn't exist, go back to the
353: original one and raise M26 */
354: set_namespace (old_ns, 0);
355: merr_raise (M26);
356: }
357:
358: return;
359: }
360: }
361:
362: switch (r->name[1]) {
363:
364: case '%':
365: case '$':
366:
367: if ((action % 2) == 0) {
368: (*gbl_s)(get_sym, tk_buf, old_value);
369: stcpy (new_value, data);
370: merr_raise (OK);
371: }
372:
373: (*gbl_s)(action, key, data);
374: ierr_sav = ierr;
375: break;
376:
377: default:
378:
379: if ((action % 2) == 0) {
380: (*gbl_u)(get_sym, tk_buf, old_value);
381: stcpy (new_value, data);
382: merr_raise (OK);
383: }
384:
385: (*gbl_u)(action, key, data);
386: ierr_sav = ierr;
387: break;
388:
389: }
390:
391: if ((extref_flg == TRUE) || (mapped_flg == TRUE)) {
392:
393: if (mapped_flg == TRUE) {
394: strncpy (gloplib, old_gloplib, PATHLEN - 1);
395: }
396:
397: set_namespace (old_ns, 0);
398:
399: }
400:
401: if (evt_async_enabled && r->reftype == MREF_RT_GLOBAL) {
402: char an[20];
403: char ev_id[512];
404:
405: char *k_buf = (char *) malloc (STRLEN * sizeof (char));
406: char *d_buf = (char *) malloc (STRLEN * sizeof (char));
407: NULLPTRCHK(k_buf,"global");
408: NULLPTRCHK(d_buf,"global");
409:
410: mref_to_external (r, d_buf);
411: stcnv_c2m (d_buf);
412:
413: switch (action) {
414: case set_sym:
415: sprintf (an, "SET");
416: break;
417: case kill_sym:
418: case kill_all:
419: case killexcl:
420: case killone:
421: sprintf (an, "KILL");
422: break;
423: case get_sym:
424: sprintf (an, "GET");
425: break;
1.5 snw 426: case fra_dat:
1.1 snw 427: sprintf (an, "DATA");
428: break;
429: case fra_order:
430: sprintf (an, "ORDER");
431: break;
432: case fra_query:
433: case bigquery:
434: sprintf (an, "QUERY");
435: break;
436: case getinc:
437: sprintf (an, "INCREMENT");
438: break;
439: case getnext:
440: sprintf (an, "NEXT");
441: break;
442: case zdata:
443: sprintf (an, "ZDATA");
444: break;
445: }
446:
447: /* NEW ^$EVENT */
448: symtab (new_sym, "^$EVENT\201", "\201");
449:
450: /* populate ^$EVENT("GLVN") with the key */
451: snprintf (k_buf, STRLEN - 1, "^$EVENT\202GLOBAL\201");
452: symtab (set_sym, k_buf, d_buf);
453:
454: if ((action % 2) == 0) {
455:
456: snprintf (k_buf, STRLEN - 1, "^$EVENT\202OLD_VALUE\201");
457: symtab (set_sym, k_buf, old_value);
458:
459: snprintf (k_buf, STRLEN - 1, "^$EVENT\202NEW_VALUE\201");
460: symtab (set_sym, k_buf, new_value);
461:
462: }
463:
464: sprintf (ev_id, "%s:%s", an, r->name);
465: evt_enqueue (ev_id, EVT_CLS_TRIGGER, 0);
466:
467: free (k_buf);
1.6 snw 468: /* free (d_buf); */
1.1 snw 469: }
470:
471: free (old_value);
472: free (new_value);
473: free (r);
474: free (tk_buf);
475: free (old_ns);
476: free (mapk_buf);
477: free (mapd_buf);
478:
479: merr_raise (ierr_sav);
480:
481: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>