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>