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

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