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