File:  [Coherent Logic Development] / freem / src / gcompact.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 19:14:25 2025 UTC (6 months, 3 weeks ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
First phase of REUSE compliance and header reformat

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

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