File:  [Coherent Logic Development] / freem / src / gfix.c
Revision 1.4: download - view: text, annotated - select for diffs
Wed Apr 2 03:02:42 2025 UTC (4 months ago) by snw
Branches: MAIN
CVS tags: v0-63-1-rc1, v0-63-0-rc1, v0-63-0, HEAD
Stop requiring users to pass -e to fmadm when -u or -g are passed

    1: /*
    2:  *   $Id: gfix.c,v 1.4 2025/04/02 03:02:42 snw Exp $
    3:  *    display freem database blocks on-screen
    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: gfix.c,v $
   27:  *   Revision 1.4  2025/04/02 03:02:42  snw
   28:  *   Stop requiring users to pass -e to fmadm when -u or -g are passed
   29:  *
   30:  *   Revision 1.3  2025/03/09 19:14:25  snw
   31:  *   First phase of REUSE compliance and header reformat
   32:  *
   33:  *
   34:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
   35:  * SPDX-License-Identifier: AGPL-3.0-or-later
   36:  **/
   37: 
   38: #include <stdlib.h>
   39: #include <setjmp.h>
   40: #include <signal.h>
   41: #include <stdio.h>
   42: #include "mpsdef0.h"
   43: #include "errmsg.h"
   44: #include <fcntl.h>
   45: #include <unistd.h>
   46: #include <string.h>
   47: #include <sys/types.h>
   48: #include <sys/wait.h>
   49: 
   50: /* needed if byte data are to be interpreted as unsigned integer */
   51: #define UNSIGN(A) ((A)&0377)
   52: 
   53: #define g_EOL 30
   54: #define POINT 28
   55: #define MINUS 26
   56: 
   57: #define ROOT 0L
   58: 	/* length of blocks. status bytes defined as offset to blocklength */
   59: #define BLOCKLEN 1024
   60: #define DATALIM (BLOCKLEN-11)
   61: #define LLPTR   (BLOCKLEN-10)
   62: #define NRBLK    LLPTR
   63: #define RLPTR   (BLOCKLEN- 6)
   64: #define FREE     RLPTR
   65: #define BTYP    (BLOCKLEN- 3)
   66: #define OFFS    (BLOCKLEN- 2)
   67: 
   68: #define PLEN     3
   69: 
   70: #define EMPTY    0
   71: #define FBLK     1
   72: #define POINTER  2
   73: #define BOTTOM   6
   74: #define DATA     8
   75: 
   76: #define LF      10
   77: #define CR      13
   78: #define SPC     ' '
   79: #define NUL      0
   80: #define DEL    127
   81: 
   82: #ifndef SYSFIVE
   83:     #define FreeM_timezone -3600
   84: #else
   85: 
   86:     #ifdef __CYGWIN__
   87:         #define FreeM_timezone _timezone
   88:     #else
   89:         extern long FreeM_timezone;
   90:     #endif /* __CYGWIN__ */
   91: 
   92: #endif /* SYSFIVE */
   93: 
   94: /* mumps commands */
   95: #define BREAK       'b'
   96: #define CLOSE       'c'
   97: #define DO          'd'
   98: #define DO_BLOCK     2
   99: #define ELSE        'e'
  100: #define FOR         'f'
  101: #define GOTO        'g'
  102: #define HA          'h'
  103: #define HALT        '0'
  104: #define HANG        '1'
  105: #define IF          'i'
  106: #define JOB         'j'
  107: #define KILL        'k'
  108: #define LOCK        'l'
  109: #define NEW         'n'
  110: #define OPEN        'o'
  111: #define QUIT        'q'
  112: #define READ        'r'
  113: #define SET         's'
  114: #define USE         'u'
  115: #define VIEW        'v'
  116: #define WRITE       'w'
  117: #define XECUTE      'x'
  118: 
  119: #define ZBREAK      'B'
  120: #define ZGO         'G'
  121: #define ZHALT       'H'
  122: #define ZINSERT     'I'
  123: #define ZJOB        'J'
  124: #define ZLOAD       'L'
  125: #define ZNEW        'N'
  126: #define ZPRINT      'P'
  127: #define ZQUIT       'Q'
  128: #define ZREMOVE     'R'
  129: #define ZSAVE       'S'
  130: #define ZTRAP       'T'
  131: #define ZWRITE      'W'
  132: #define PRIVATE     SP
  133: 
  134: 
  135: 
  136: int
  137: main (argc, argv)
  138: 	int     argc;			/* arguments count */
  139: 	char   *argv[];			/* arguments string */
  140: 
  141: {
  142:     static char ASCII[] = "NULSOHSTXETXEOTENQACKBELBS TABLF VT FF CR SO SI DLEDC1DC2DC3DC4NAKSYNETBCANEM SUBESCFS GS RS US ";
  143:     char    filnam[40];
  144:     short   filedes;
  145:     char    block[BLOCKLEN];
  146:     char    key[512];
  147:     char    data[1024];
  148:     long    blknbr;
  149:     short   offset;
  150:     short   type;
  151:     unsigned long pointer;
  152:     short   length;
  153:     short   koffs;
  154: 
  155:     register int i,
  156:             j,
  157:             k,
  158:             ch;
  159: 
  160:     filnam[0] = '^';
  161:     filnam[1] = 0;
  162: 
  163:     if (argc > 1) {
  164: 	j = 0;
  165: 	while (--argc > 0) {
  166: 	    j++;			/* accept it with or without '^' sign */
  167: 	    if (**(argv + j) == '-') {
  168: 		fprintf (stderr, "usage is: %s [^]global\012\015", *argv);
  169: 		exit (0);
  170: 	    }
  171: 	    if (**(argv + j) == '^')
  172: 		strcpy (filnam, *(argv + j));
  173: 	    else
  174: 		strcpy (&filnam[1], *(argv + j));
  175: 	}
  176:     } else {
  177: 	printf ("\012\015display global ^");
  178: 	scanf ("%s", &filnam[1]);
  179:     }
  180:     if ((filedes = open (filnam, 0)) == -1) {
  181: 	printf ("cannot open file %s\007\012\015", filnam);
  182: 	exit (0);
  183:     }
  184:   again:;
  185: 
  186:     printf ("\012\015display block #");
  187:     scanf ("%ld", &blknbr);
  188:     if (blknbr < 0) {
  189: 	printf ("\012\015*** done ***\012\015\033[r\033[24H");
  190: 	exit (0);
  191:     }
  192:     lseek (filedes, blknbr * 1024L, 0);
  193:     if (read (filedes, block, BLOCKLEN) == 0) {
  194: 	printf ("block #%ld does not exist\007\012\015-1 will terminate", blknbr);
  195: 	goto again;
  196:     }
  197:     printf ("\033[r\033[2Jglobal\033[;20H%s\033[;40Hblock\033[;60H%ld",
  198: 	    filnam,
  199: 	    blknbr);
  200:     printf ("\033[2Hblock type\033[2;20H");
  201:     type = block[BTYP];
  202:     switch (type) {
  203:     case DATA:
  204: 	printf ("DATA");
  205: 	break;
  206:     case POINTER:
  207: 	printf ("POINTER");
  208: 	break;
  209:     case BOTTOM:
  210: 	printf ("BOTTOM POINTER");
  211: 	break;
  212:     case EMPTY:
  213: 	printf ("EMPTY");
  214: 	break;
  215:     case FBLK:
  216: 	printf ("FBLK");
  217: 	break;
  218:     default:
  219: 	printf ("ILLEGAL TYPE");
  220: 	type = DATA;
  221:     }
  222:     if (blknbr == ROOT)
  223: 	printf (", ROOT");
  224: 
  225:     offset = UNSIGN (block[OFFS]) * 256 +
  226: 	    UNSIGN (block[OFFS + 1]);
  227:     printf ("\033[2;40Hoffset\033[2;60H%d", offset);
  228:     if (offset > DATALIM || (type == FBLK && offset % PLEN)) {
  229: 	printf (" ???");
  230: 	offset = DATALIM;
  231:     }
  232:     pointer = UNSIGN (block[LLPTR]) * 65536 +
  233: 	    UNSIGN (block[LLPTR + 1]) * 256 +
  234: 	    UNSIGN (block[LLPTR + 2]);
  235:     printf ("\033[3H%s\033[3;20H%ld",
  236: 	    blknbr != ROOT ? "LEFT LINK POINTER" : "NR_OF_BLKS",
  237: 	    pointer);
  238: 
  239:     pointer = UNSIGN (block[RLPTR]) * 65536 +
  240: 	    UNSIGN (block[RLPTR + 1]) * 256 +
  241: 	    UNSIGN (block[RLPTR + 2]);
  242:     printf ("\033[3;40H%s\033[3;60H%ld",
  243: 	    blknbr != ROOT ? "RIGHT LINK POINTER" : "FREE",
  244: 	    pointer);
  245: 
  246:     printf ("\033[4;24r\033[4H");	/* define scrolling area */
  247: 
  248:     if (type == FBLK) {
  249: 	i = 0;
  250: 	while (i < offset) {
  251: 	    k = UNSIGN (block[i]) * 65536 +
  252: 		    UNSIGN (block[i + 1]) * 256 +
  253: 		    UNSIGN (block[i + 2]);
  254: 	    i += PLEN;
  255: 	    printf ("%8d", k);
  256: 	}
  257: 	goto again;
  258:     }
  259:     i = 0;
  260:     while (i < offset) {
  261: 	printf ("\012\015%3d", i);
  262: 	length = UNSIGN (block[i++]);
  263: 	k = koffs = UNSIGN (block[i++]);
  264: 	if ((i + length) > offset)
  265: 	    break;
  266: 	for (j = 0; j < length; j++)
  267: 	    key[k++] = block[i++];
  268: 	key[k] = g_EOL;
  269: /*----------------------*/
  270: 	{
  271: 	    short   ch0,
  272: 	            i,
  273: 	            j,
  274: 	            k,
  275: 	            typ;
  276: 
  277: 	    j = 0;
  278: 	    i = 0;
  279: 	    data[j++] = '(';
  280: 	    k = 1;
  281: 	    while ((ch = UNSIGN (key[i++])) != g_EOL) {
  282: 		if (k) {
  283: 		    k = 0;
  284: 		    if ((typ = (ch > SPC)))
  285: 			data[j++] = '"';
  286: 		}
  287: 		ch0 = (ch >= SPC ? (ch >> 1) :	/* 'string' chars */
  288: 		       (ch < 20 ? (ch >> 1) + '0' :	/* 0...9          */
  289: 			(ch >> 1) + SPC));	/* '.' or '-'     */
  290: 		if (ch0 == DEL) {
  291: 		    if (((ch = UNSIGN (key[i++])) >> 1) == DEL) {
  292: 			ch0 += DEL;
  293: 			ch = UNSIGN (key[i++]);
  294: 		    }
  295: 		    ch0 += (ch >> 1);
  296: 		    data[j] = '<';
  297: 		    data[++j] = '0' + ch0 / 100;
  298: 		    data[++j] = '0' + (ch0 % 100) / 10;
  299: 		    data[++j] = '0' + ch0 % 10;
  300: 		    data[++j] = '>';
  301: 		} else
  302: 		    data[j] = ch0;
  303: 		if (data[j++] == '"')
  304: 		    data[j++] = '"';
  305: 		if (ch & 01) {
  306: 		    if (typ)
  307: 			data[j++] = '"';
  308: 		    data[j++] = ',';
  309: 		    k = 1;
  310: 		}
  311: 	    }
  312: 	    data[j--] = 0;
  313: 	    data[j] = ')';
  314: 	    if (j == 0)
  315: 		data[0] = 0;
  316: 	    while (j >= 0) {
  317: 		if ((ch = data[--j]) < SPC || ch >= DEL)
  318: 		    break;
  319: 	    }
  320: 	    if (j < 0)
  321: 		printf ("[%d][%d] %s ", length, koffs, data);
  322: 	    else
  323: 		printf ("[%d][%d] <illegal subscipt>", length, koffs);
  324: /*----------------------*/
  325: 	}
  326: 	if (type == DATA) {
  327: 	    length = UNSIGN (block[i++]);
  328: 	    k = 0;
  329: 	    if ((i + length) > offset)
  330: 		break;
  331: 	    while (length-- > 0) {
  332: 		ch = UNSIGN (block[i++]);
  333: 		if ((ch >= SPC) && (ch < DEL))
  334: 		    data[k++] = ch;
  335: 		else {
  336: 		    data[k++] = '<';
  337: 		    if ((ch >= NUL) && (ch < SPC)) {
  338: 			ch = ch * 3;
  339: 			data[k++] = ASCII[ch++];
  340: 			data[k++] = ASCII[ch++];
  341: 			if ((data[k++] = ASCII[ch++]) == SPC)
  342: 			    k--;
  343: 		    } else if (ch == DEL) {
  344: 			data[k++] = 'D';
  345: 			data[k++] = 'E';
  346: 			data[k++] = 'L';
  347: 		    } else {
  348: 			if (ch > 99) {
  349: 			    data[k++] = '0' + (ch / 100);
  350: 			    ch = ch % 100;
  351: 			}
  352: 			if (ch > 9) {
  353: 			    data[k++] = '0' + (ch / 10);
  354: 			    ch = ch % 10;
  355: 			}
  356: 			data[k++] = '0' + ch;
  357: 		    }
  358: 		    data[k++] = '>';
  359: 		}
  360: 	    }
  361: 	    data[k] = 0;
  362: 	    printf ("= %s", data);
  363: 	} else {
  364: 	    pointer = UNSIGN (block[i]) * 65536 +
  365: 		    UNSIGN (block[i + 1]) * 256 +
  366: 		    UNSIGN (block[i + 2]);
  367: 	    i += PLEN;
  368: 	    printf ("-> %ld", pointer);
  369: 	}
  370:     }
  371:     if (i != offset)
  372: 	printf ("\012\015wrong offset %d vs. %d\012\015", offset, i);
  373:     goto again;
  374: }

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