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>