1: /*
2: * $Id: grestore.c,v 1.4 2025/04/02 03:02:42 snw Exp $
3: * repairs degraded freem globals
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: grestore.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: /* restores mumps globals.
39: * needs free disk storages approx. the size of the
40: * global to be restored. only data blocks are interpreted.
41: * it cannot recover from some errors in data blocks.
42: * anyway the global to be restored should be saved for
43: * a detailed analysis of the error.
44: */
45:
46: #include <stdlib.h>
47: #include <stddef.h>
48: #include "mpsdef0.h"
49: #include "errmsg.h"
50: #include <signal.h>
51: #include <setjmp.h>
52: #include <stdio.h>
53: #include <fcntl.h>
54: #include <unistd.h>
55: #include <sys/types.h>
56: #include <sys/stat.h>
57: #include <sys/wait.h>
58: #include <string.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:
84: #define PROTECT 30
85:
86:
87: #ifndef SYSFIVE
88: #define FreeM_timezone -3600
89: #else
90:
91: #ifdef __CYGWIN__
92: #define FreeM_timezone _timezone
93: #else
94: extern long FreeM_timezone;
95: #endif /* __CYGWIN__ */
96:
97: #endif /* SYSFIVE */
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: int main (argc, argv)
142: int argc; /* arguments count */
143: char *argv[]; /* arguments string */
144:
145: {
146: char filnam[40]; /* global to be restored */
147: static
148: char savnam[512] = "^/usr/tmp/", /* intermediate storage */
149: unlnam[40] = "/usr/tmp/^"; /* "unlink" filename */
150: short fildes; /* file descriptor to filnam */
151: char block[BLOCKLEN];
152: char key[512];
153: char data[512];
154: unsigned long blknbr;
155: long offset;
156: short type;
157: long length;
158: long koffs;
159:
160: register int i,
161: j,
162: k,
163: ch;
164:
165: umask (0); /* protection bits mask to full rights */
166: filnam[0] = '^';
167: filnam[1] = 0;
168:
169: if (argc > 1) {
170: j = 0;
171: while (--argc > 0) {
172: j++;
173: if (**(argv + j) == '-') {
174: printf ("usage is: %s [^]global\012\015", *argv);
175: exit (0);
176: }
177: strcpy (&filnam[1], *(argv + j));
178: }
179: } else {
180: printf ("\012\015%s global ^", *argv);
181: scanf ("%s", &filnam[1]);
182: }
183:
184: j = filnam[1];
185: if (j == '.' || j == '/' || j == '^') {
186: j = 0;
187: while ((filnam[j] = filnam[j + 1]))
188: j++;
189: }
190: if ((fildes = open (filnam, 0)) == -1) {
191: printf ("cannot open file %s\007\012\015", filnam);
192: exit (1);
193: }
194: strcpy (&savnam[10], &filnam[1]);
195: koffs = 10 + strlen (&filnam[1]);
196: strcpy (&unlnam[10], &filnam[1]);
197: unlink (unlnam); /* kill previous tmp_file */
198: blknbr = ROOT;
199:
200: again:;
201:
202: lseek (fildes, blknbr * BLOCKLEN, 0);
203: blknbr++;
204: if (read (fildes, block, BLOCKLEN) == 0) {
205: strcpy (block, "mv /usr/tmp/\\^");
206: strcat (block, &filnam[1]);
207: strcat (block, " .");
208: system (block);
209: exit (0);
210: }
211: type = block[BTYP];
212: if (type != DATA)
213: goto again;
214:
215: offset = UNSIGN (block[OFFS]) * 256 +
216: UNSIGN (block[OFFS + 1]);
217: if (offset > DATALIM) {
218: printf ("illegal offset %ld\012", offset);
219: offset = DATALIM;
220: }
221: i = 0;
222: while (i < offset) {
223: length = UNSIGN (block[i++]);
224: k = UNSIGN (block[i++]);
225: if ((i + length) > offset)
226: break;
227: for (j = 0; j < length; j++)
228: key[k++] = block[i++];
229: key[k] = g_EOL;
230: /*----------------------*/
231: {
232: long ch0,
233: i,
234: j,
235: k;
236:
237: j = 0;
238: i = 0;
239: data[j++] = DELIM;
240: k = 1;
241: while ((ch = UNSIGN (key[i++])) != g_EOL) {
242: if (k) {
243: k = 0;
244: }
245: ch0 = (ch >= SP ? (ch >> 1) : /* 'string' chars */
246: (ch < 20 ? (ch >> 1) + '0' : /* 0...9 */
247: (ch >> 1) + SP)); /* '.' or '-' */
248: if (ch0 == DEL) {
249: if (((ch = UNSIGN (key[i++])) >> 1) == DEL) {
250: ch0 += DEL;
251: ch = UNSIGN (key[i++]);
252: }
253: ch0 += (ch >> 1);
254: }
255: data[j++] = ch0;
256: if (ch & 01) {
257: data[j++] = DELIM;
258: k = 1;
259: }
260: }
261: data[j--] = EOL;
262: if (j == 0)
263: data[0] = EOL;
264: else if (data[j] == DELIM)
265: data[j] = EOL;
266: if ((koffs + j) > 255)
267: goto again; /* oversize subscript */
268: while (j >= 0) {
269: if ((UNSIGN (ch = data[--j]) < SP) && (ch != DELIM))
270: break;
271: }
272:
273: if (j < 0)
274: stcpy (&savnam[koffs], data);
275: else
276: goto again; /* illegal subscipt */
277: /*----------------------*/
278: }
279: length = UNSIGN (block[i++]);
280: k = 0;
281: if ((i + length) > offset)
282: break;
283: stcpy0 (data, &block[i], length);
284: i += length;
285: data[length] = EOL;
286: global (0, savnam, data); /* call original global */
287:
288: if (merr () == PROTECT) {
289: printf ("\012cannot open intermediate file in /usr/tmp\012");
290: exit (1);
291: }
292: }
293: if (i != offset)
294: printf ("\012wrong offset %ld vs. %d\012", offset, i);
295: goto again;
296: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>