File:  [Coherent Logic Development] / freem / src / global_dispatch.c
Revision 1.9: download - view: text, annotated - select for diffs
Thu Apr 10 01:24:38 2025 UTC (6 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Remove C++ style comments

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>