File:  [Coherent Logic Development] / freem / src / merr.c
Revision 1.10: download - view: text, annotated - select for diffs
Wed May 14 12:22:04 2025 UTC (2 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Further work on shared memory

    1: /*
    2:  *   $Id: merr.c,v 1.10 2025/05/14 12:22:04 snw Exp $
    3:  *    stuff for handling program bogosity
    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: merr.c,v $
   27:  *   Revision 1.10  2025/05/14 12:22:04  snw
   28:  *   Further work on shared memory
   29:  *
   30:  *   Revision 1.9  2025/05/03 04:21:01  snw
   31:  *   Another fix for user-defined errors
   32:  *
   33:  *   Revision 1.8  2025/05/03 04:12:34  snw
   34:  *   Fix user-defined error codes
   35:  *
   36:  *   Revision 1.7  2025/05/01 03:56:29  snw
   37:  *   -m
   38:  *
   39:  *   Revision 1.6  2025/04/30 17:19:16  snw
   40:  *   Improve backtraces in debugger
   41:  *
   42:  *   Revision 1.5  2025/04/13 04:22:43  snw
   43:  *   Fix snprintf calls
   44:  *
   45:  *   Revision 1.4  2025/04/09 19:52:02  snw
   46:  *   Eliminate as many warnings as possible while building with -Wall
   47:  *
   48:  *   Revision 1.3  2025/03/09 19:50:47  snw
   49:  *   Second phase of REUSE compliance and header reformat
   50:  *
   51:  *
   52:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
   53:  * SPDX-License-Identifier: AGPL-3.0-or-later
   54:  **/
   55: 
   56: #include <string.h>
   57: #include <stdlib.h>
   58: 
   59: #include "mpsdef.h"
   60: #include "merr.h"
   61: #include "jobtab.h"
   62: 
   63: merr_stackent merr_stack[NESTLEVLS + 1];
   64: char etrap[256];
   65: char ecode[256];
   66: char user_ecode[256];
   67: int estack;
   68: int etrap_lvl = 0;
   69: int merr_topstk = 0;
   70: 
   71: typedef struct err_lut {
   72:     int ecode;
   73:     const char *canonical_name;
   74: } err_lut;
   75: 
   76: err_lut errtab[] = {
   77:     {0, "ZOK"},
   78:     {1, "ZINRPT"},
   79:     {2, "ZBKERR"},
   80:     {3, "ZNOSTAND"},
   81:     {4, "ZUNDEF"},
   82:     {5, "ZLBLUNDEF"},
   83:     {6, "ZMISSOPD"},
   84:     {7, "ZMISSOP"},
   85:     {8, "ZILLOP"},
   86:     {9, "ZQUOTER"},
   87:     {10, "ZCOMMAER"},
   88:     {11, "ZASSIGNER"},
   89:     {12, "ZARGER"},
   90:     {13, "ZSPACER"},
   91:     {14, "ZBRAER"},
   92:     {15, "ZLVLERR"},
   93:     {16, "ZDIVER"},
   94:     {17, "ZILLFUN"},
   95:     {18, "ZFUNARG"},
   96:     {19, "ZZTERR"},
   97:     {20, "ZNEXTER"},
   98:     {21, "ZSELER"},
   99:     {22, "ZCMMND"},
  100:     {23, "ZARGLIST"},
  101:     {24, "ZINVEXPR"},
  102:     {25, "ZINVREF"},
  103:     {26, "ZMXSTR"},
  104:     {27, "ZTOOPARA"},
  105:     {28, "ZNOPEN"},
  106:     {29, "ZNODEVICE"},
  107:     {30, "ZPROTECT"},
  108:     {31, "ZGLOBER"},
  109:     {32, "ZFILERR"},
  110:     {33, "ZPGMOV"},
  111:     {34, "ZSTKOV"},
  112:     {35, "ZSTORE"},
  113:     {36, "ZNOREAD"},
  114:     {37, "ZNOWRITE"},
  115:     {38, "ZNOPGM"},
  116:     {39, "ZNAKED"},
  117:     {40, "ZSBSCR"},
  118:     {41, "ZISYNTX"},
  119:     {42, "ZDBDGD"},
  120:     {43, "ZKILLER"},
  121:     {44, "ZHUPER"},
  122:     {45, "ZMXNUM"},
  123:     {46, "ZNOVAL"},
  124:     {47, "ZTYPEMISMATCH"},
  125:     {48, "ZMEMOV"},
  126:     {49, "ZNAMERES"},
  127:     {50, "ZSCKCREAT"},
  128:     {51, "ZSCKIFAM"},
  129:     {52, "ZSCKITYP"},
  130:     {53, "ZSCKIPRT"},
  131:     {54, "ZSCKCERR"},
  132:     {55, "ZSCKAERR"},
  133:     {56, "ZSCKACON"},
  134:     {57, "ZSCKNCON"},
  135:     {58, "ZSCKEOPT"},
  136:     {59, "ZSCKERCV"},
  137:     {60, "ZSCKESND"},
  138:     {61, "ZNORPI"},
  139:     {62, "ZCREDEF"},
  140:     {63, "ZCMODIFY"},
  141:     {64, "ZFILEXWR"},
  142:     {65, "ZINEWMUL"},
  143:     {66, "ZINVHORO"},
  144:     {67, "ZTYPMISMATCH"},
  145:     {68, "ZINVTYPE"},
  146:     {69, "ZINVLIBOPT"},
  147:     {80, "ZECODEINV"},
  148:     {81, "ZASSERT"},
  149:     {82, "ZUSERERR"},
  150:     {83, "ZOBJFLDACCV"},
  151:     {84, "ZOBJCONFLICT"},
  152:     {85, "ZOBJPRIVOVFL"},
  153:     {86, "ZOBJACINVALID"},
  154:     {128, "ZSYNTERR"},
  155:     {140, "M1"},
  156:     {141, "M2"},
  157:     {142, "M3"},
  158:     {143, "M4"},
  159:     {144, "M5"},
  160:     {145, "M6"},
  161:     {146, "M7"},
  162:     {147, "M8"},
  163:     {148, "M9"},
  164:     {149, "M10"},
  165:     {150, "M11"},
  166:     {151, "M12"},
  167:     {152, "M13"},
  168:     {153, "M14"},
  169:     {154, "M15"},
  170:     {155, "M16"},
  171:     {156, "M17"},
  172:     {157, "M18"},
  173:     {158, "M19"},
  174:     {159, "M20"},
  175:     {160, "M21"},
  176:     {161, "M22"},
  177:     {162, "M23"},
  178:     {163, "M24"},
  179:     {164, "M25"},
  180:     {165, "M26"},
  181:     {166, "M27"},
  182:     {167, "M28"},
  183:     {168, "M29"},
  184:     {169, "M30"},
  185:     {170, "M31"},
  186:     {171, "M32"},
  187:     {172, "M33"},
  188:     {173, "M34"},
  189:     {174, "M35"},
  190:     {175, "M36"},
  191:     {176, "M37"},
  192:     {177, "M38"},
  193:     {178, "M39"},
  194:     {179, "M40"},
  195:     {180, "M41"},
  196:     {181, "M42"},
  197:     {182, "M43"},
  198:     {183, "M44"},
  199:     {184, "M45"},
  200:     {185, "M46"},
  201:     {186, "M47"},
  202:     {187, "M48"},
  203:     {188, "M49"},
  204:     {189, "M50"},
  205:     {190, "M51"},
  206:     {191, "M52"},
  207:     {192, "M53"},
  208:     {193, "M54"},
  209:     {194, "M55"},
  210:     {195, "M56"},
  211:     {196, "M57"},
  212:     {197, "M58"},
  213:     {198, "M59"},
  214:     {199, "M60"},
  215:     {214, "M75"},
  216:     {240, "M101"},
  217:     {241, "M102"},
  218:     {242, "M103"},
  219:     {243, "M104"},
  220:     {254, "ZASYNC"},
  221:     {255, "ZCTRLB"},
  222:     {-1, NULL}
  223: };
  224: 
  225: inline int merr_raise(int num)
  226: {
  227:     char placebuf[256];
  228:     char lref[256];
  229:     
  230:     if (num != OK) {
  231:         lasterr[nstx] = ierr;
  232:     }
  233:     
  234:     if (merr_in_break ()) {
  235:         ierr = num - CTRLB;
  236:     }
  237:     else {
  238:         ierr = num;
  239:     }
  240: 
  241:     if (num != OK) {
  242:         merr_set_ecode_ierr ();
  243:         
  244:         stcpy (merr_stack[nstx].ECODE, ecode);
  245:         
  246:         if (direct_mode == 1 && nstx == 0) {
  247:             stcpy (merr_stack[nstx].PLACE, "@\201\0");
  248:             stcpy (merr_stack[nstx].MCODE, " \201\0");
  249:         }
  250:         else {            
  251:             getraddress (placebuf, nstx);
  252:             stcpy (merr_stack[nstx].PLACE, &(placebuf[3]));
  253:             stcpy (lref, merr_stack[nstx].PLACE);
  254:             stcnv_m2c (lref);
  255:             if (routine_get_line (lref, merr_stack[nstx].MCODE) == NULL) {
  256:                 sprintf (merr_stack[nstx].MCODE, "???\201");
  257:             }
  258:             else {
  259:                 stcnv_c2m (merr_stack[nstx].MCODE);
  260:             }
  261:         }
  262:         
  263:         if (nstx > merr_topstk) merr_topstk = nstx;
  264:     }   
  265:     
  266:     return ierr;    
  267: }
  268: 
  269: inline int merr(void)
  270: {
  271:     return ierr < OK ? ierr + CTRLB : ierr;
  272: }
  273: 
  274: short merr_in_break(void)
  275: {
  276:     if (ierr < OK) {
  277:         return TRUE;
  278:     }
  279:     else {
  280:         return FALSE;
  281:     }
  282: }
  283: 
  284: void merr_set_break(void)
  285: {
  286:     if (!merr_in_break ()) {
  287:         ierr = ierr - CTRLB;
  288:     }
  289: }
  290: 
  291: void merr_clear_break(void)
  292: {
  293:     if (merr_in_break ()) {
  294:         ierr = ierr + CTRLB;
  295:     }
  296: }
  297: 
  298: int merr_num_to_code (int num, char *code)
  299: {
  300: 
  301:     err_lut *p;
  302: 
  303:     for (p = errtab; p->canonical_name != NULL; ++p) {
  304: 
  305:         if (p->ecode == num) {
  306:             strcpy (code, p->canonical_name);            
  307:             return 1;
  308:         }
  309: 
  310:     }
  311: 
  312:     return -1;
  313: 
  314: }
  315: 
  316: int merr_code_to_num (char *code)
  317: {
  318: 
  319:     err_lut *p;
  320: 
  321:     for (p = errtab; p->canonical_name != NULL; ++p) {
  322: 
  323:         if (strcmp (p->canonical_name, code) == 0) {            
  324:             return p->ecode;
  325:         }
  326: 
  327:     }
  328:     
  329:     return -1;
  330: 
  331: }
  332: 
  333: void merr_set_ecode_ierr (void)
  334: {
  335:     char *cod;
  336:     char *t;
  337:     
  338:     cod = (char *) malloc (MERR_COD_LENGTH * sizeof (char));
  339:     NULLPTRCHK(cod,"merr_set_ecode_ierr");
  340:     
  341:     t = (char *) malloc (MERR_COD_LENGTH * sizeof (char));
  342:     NULLPTRCHK(t,"merr_set_ecode_ierr");
  343:     
  344:     if ((merr_num_to_code (merr (), cod)) == -1) goto done;
  345: 
  346:     snprintf (t, MERR_COD_LENGTH - 1, ",%s,\201", cod);
  347:     merr_set_ecode (t);
  348:     
  349:     /* job_set_ecode (pid, cod); */
  350:     
  351: done:
  352: 
  353:     free (cod);
  354:     free (t);
  355:     return;
  356: 
  357: }
  358: 
  359: int merr_set_ecode (char *t_code)
  360: {
  361:     int ec;
  362:     char *tmp;
  363:     
  364:     if (t_code[0] == '\201') {
  365:         stcpy (ecode, "\201");
  366:         return 0;
  367:     }
  368: 
  369:     if (t_code[1] != 'M' && t_code[1] != 'Z' && t_code[1] != 'U') { 
  370:         return M101;
  371:     }
  372: 
  373:     stcpy (ecode, t_code);
  374: 
  375:     if (stcmp (t_code, "") == 0) {
  376:         merr_clear ();
  377:         stcpy (t_code, ",ZOK,");  
  378:         stcpy (user_ecode, t_code);      
  379:     }
  380: 
  381:     tmp = strtok (t_code, ",");    
  382: 
  383:     /* caller may set ierr with return value */
  384:     if (ecode[1] == 'U') {
  385:         stcpy (user_ecode, ecode);
  386:         return USERERR;
  387:     }
  388:     else {        
  389:         ec = merr_code_to_num (tmp);
  390:         return (ec);
  391:     }
  392: }
  393: 
  394: void merr_dump (int num, char *rtn, char *nsn, char *tcod, int tpos)
  395: {
  396:     char *tbuf;
  397:     char *dbuf;
  398:     char *nem;
  399:     char *nrt;
  400:     char *real_ecode;
  401:     err_lut *p;
  402:     
  403:     tbuf = (char *) malloc (STRLEN * sizeof (char));
  404:     NULLPTRCHK(tbuf,"merr_dump");
  405: 
  406:     dbuf = (char *) malloc (STRLEN * sizeof (char));
  407:     NULLPTRCHK(dbuf,"merr_dump");
  408:     
  409:     nem = (char *) malloc (STRLEN * sizeof (char));
  410:     NULLPTRCHK(nem,"merr_dump");
  411:     
  412:     nrt = (char *) malloc (STRLEN * sizeof (char));
  413:     NULLPTRCHK(nrt,"merr_dump");
  414:     
  415:     real_ecode = (char *) malloc (STRLEN * sizeof (char));
  416:     NULLPTRCHK(real_ecode,"merr_dump");
  417: 
  418:     stcpy (nrt, rtn);
  419:     stcnv_m2c (nrt);
  420: 
  421:     stcpy (nem, errmes[num]);
  422:     stcnv_m2c (nem);
  423: 
  424:     for (p = errtab; p->canonical_name != NULL; ++p) {
  425: 
  426:         if (p->ecode == num) {
  427: 
  428:             if (strcmp (p->canonical_name, "ZUSERERR") == 0) {
  429:                 stcpy (real_ecode, &user_ecode[1]);
  430:                 stcnv_m2c (real_ecode);
  431:                 real_ecode [strlen (real_ecode) - 1] = NUL;
  432: 
  433:                 snprintf (tbuf, STRLEN - 1, "^$JOB\202%d\202USER_ERRORS\202%s\201", pid, &user_ecode[1]);
  434:                 tbuf [stlen (tbuf) - 1] = '\201';
  435: 
  436:                 ssvn (get_sym, tbuf, dbuf);
  437:                 
  438:                 if (merr () == OK) {
  439:                     stcpy (nem, dbuf);
  440:                     stcnv_m2c (nem);
  441:                 }
  442:                 else {
  443:                     sprintf (nem, "user-defined error");                    
  444:                     merr_clear ();
  445:                 }
  446: 
  447:                 if (strlen (nem) == 0) {
  448:                     sprintf (nem, "user-defined error");
  449:                 }
  450:                 
  451:             }
  452:             else {
  453:                 strcpy (real_ecode, p->canonical_name);
  454:             }
  455: 
  456: 
  457:             
  458:             if (!stlen (err_suppl)) {
  459:                 snprintf (tbuf, STRLEN - 1, "\r\n>> Error %s:  %s in %s.%s::%s  [$STACK = %d]\r\n\201", real_ecode, nem, shm_env, nsn, nrt, nstx);
  460:             }
  461:             else {
  462:                 stcnv_m2c (err_suppl);
  463:                 snprintf (tbuf, STRLEN - 1, "\r\n>> Error %s:  %s (%s) in %s::%s  [$STACK = %d]\r\n\201", real_ecode, nem, err_suppl, nsn, nrt, nstx);
  464:                 err_suppl[0] = EOL;
  465:             }
  466:             write_m (tbuf);
  467:             write_m (">> \201");
  468:             write_m (tcod);
  469:             write_m ("\r\n\201");
  470:             write_t (tpos);
  471:             write_m ("^\201");            
  472: 
  473:             goto done;
  474:         }
  475: 
  476:     }
  477: 
  478: 
  479: done:
  480: 
  481:     free (tbuf);
  482:     free (dbuf);
  483:     free (nem);
  484:     free (nrt);
  485:     free (real_ecode);
  486: 
  487:     return;
  488: }
  489: 
  490: 
  491: void merr_set_iochan_err(int channel, short frm_err, char *err_text)
  492: {
  493:     if (channel > MAXDEV || channel < 0) {
  494:         merr_raise (ARGLIST);
  495:         return;
  496:     }
  497: 
  498:     devstat[channel].mdc_err = 1;
  499:     devstat[channel].frm_err = frm_err;
  500: 
  501:     strncpy (devstat[channel].err_txt, err_text, 79);
  502: 
  503:     return;
  504: }
  505: 
  506: void merr_clear_iochan_err(int channel)
  507: {
  508:     if (channel > MAXDEV || channel < 0) {
  509:         merr_raise (ARGLIST);
  510:         return;
  511:     }
  512: 
  513:     devstat[channel].mdc_err = 1;
  514:     devstat[channel].frm_err = OK;
  515:     devstat[channel].err_txt[0] = '\0';
  516: 
  517:     return;
  518: 
  519: }

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