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