/*
* $Id: grestore.c,v 1.3 2025/03/09 19:14:25 snw Exp $
* repairs degraded freem globals
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
* $Log: grestore.c,v $
* Revision 1.3 2025/03/09 19:14:25 snw
* First phase of REUSE compliance and header reformat
*
*
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
/* restores mumps globals.
* needs free disk storages approx. the size of the
* global to be restored. only data blocks are interpreted.
* it cannot recover from some errors in data blocks.
* anyway the global to be restored should be saved for
* a detailed analysis of the error.
*/
#include <stdlib.h>
#include <stddef.h>
#include "mpsdef0.h"
#include "errmsg.h"
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
/* needed if byte data are to be interpreted as unsigned integer */
#define UNSIGN(A) ((A)&0377)
#define g_EOL 30
#define POINT 28
#define MINUS 26
#define ROOT 0L
/* length of blocks. status bytes defined as offset to blocklength */
#define DATALIM (BLOCKLEN-11)
#define LLPTR (BLOCKLEN-10)
#define NRBLK LLPTR
#define RLPTR (BLOCKLEN- 6)
#define FREE RLPTR
#define BTYP (BLOCKLEN- 3)
#define OFFS (BLOCKLEN- 2)
#define EMPTY 0
#define FBLK 1
#define POINTER 2
#define BOTTOM 6
#define DATA 8
#define PROTECT 30
#ifndef SYSFIVE
#define FreeM_timezone -3600
#else
#ifdef __CYGWIN__
#define FreeM_timezone _timezone
#else
extern long FreeM_timezone;
#endif /* __CYGWIN__ */
#endif /* SYSFIVE */
/* mumps commands */
#define BREAK 'b'
#define CLOSE 'c'
#define DO 'd'
#define DO_BLOCK 2
#define ELSE 'e'
#define FOR 'f'
#define GOTO 'g'
#define HA 'h'
#define HALT '0'
#define HANG '1'
#define IF 'i'
#define JOB 'j'
#define KILL 'k'
#define LOCK 'l'
#define NEW 'n'
#define OPEN 'o'
#define QUIT 'q'
#define READ 'r'
#define SET 's'
#define USE 'u'
#define VIEW 'v'
#define WRITE 'w'
#define XECUTE 'x'
#define ZALLOCATE 'A'
#define ZBREAK 'B'
#define ZDEALLOCATE 'D'
#define ZGO 'G'
#define ZHALT 'H'
#define ZINSERT 'I'
#define ZJOB 'J'
#define ZLOAD 'L'
#define ZNEW 'N'
#define ZPRINT 'P'
#define ZQUIT 'Q'
#define ZREMOVE 'R'
#define ZSAVE 'S'
#define ZTRAP 'T'
#define ZWRITE 'W'
#define PRIVATE SP
extern short ierr;
int main (argc, argv)
int argc; /* arguments count */
char *argv[]; /* arguments string */
{
char filnam[40]; /* global to be restored */
static
char savnam[512] = "^/usr/tmp/", /* intermediate storage */
unlnam[40] = "/usr/tmp/^"; /* "unlink" filename */
short fildes; /* file descriptor to filnam */
char block[BLOCKLEN];
char key[512];
char data[512];
unsigned long blknbr;
long offset;
short type;
long length;
long koffs;
register int i,
j,
k,
ch;
umask (0); /* protection bits mask to full rights */
filnam[0] = '^';
filnam[1] = 0;
if (argc > 1) {
j = 0;
while (--argc > 0) {
j++;
if (**(argv + j) == '-') {
printf ("usage is: %s [^]global\012\015", *argv);
exit (0);
}
strcpy (&filnam[1], *(argv + j));
}
} else {
printf ("\012\015%s global ^", *argv);
scanf ("%s", &filnam[1]);
}
j = filnam[1];
if (j == '.' || j == '/' || j == '^') {
j = 0;
while ((filnam[j] = filnam[j + 1]))
j++;
}
if ((fildes = open (filnam, 0)) == -1) {
printf ("cannot open file %s\007\012\015", filnam);
exit (1);
}
strcpy (&savnam[10], &filnam[1]);
koffs = 10 + strlen (&filnam[1]);
strcpy (&unlnam[10], &filnam[1]);
unlink (unlnam); /* kill previous tmp_file */
blknbr = ROOT;
again:;
lseek (fildes, blknbr * BLOCKLEN, 0);
blknbr++;
if (read (fildes, block, BLOCKLEN) == 0) {
strcpy (block, "mv /usr/tmp/\\^");
strcat (block, &filnam[1]);
strcat (block, " .");
system (block);
exit (0);
}
type = block[BTYP];
if (type != DATA)
goto again;
offset = UNSIGN (block[OFFS]) * 256 +
UNSIGN (block[OFFS + 1]);
if (offset > DATALIM) {
printf ("illegal offset %ld\012", offset);
offset = DATALIM;
}
i = 0;
while (i < offset) {
length = UNSIGN (block[i++]);
k = UNSIGN (block[i++]);
if ((i + length) > offset)
break;
for (j = 0; j < length; j++)
key[k++] = block[i++];
key[k] = g_EOL;
/*----------------------*/
{
long ch0,
i,
j,
k;
j = 0;
i = 0;
data[j++] = DELIM;
k = 1;
while ((ch = UNSIGN (key[i++])) != g_EOL) {
if (k) {
k = 0;
}
ch0 = (ch >= SP ? (ch >> 1) : /* 'string' chars */
(ch < 20 ? (ch >> 1) + '0' : /* 0...9 */
(ch >> 1) + SP)); /* '.' or '-' */
if (ch0 == DEL) {
if (((ch = UNSIGN (key[i++])) >> 1) == DEL) {
ch0 += DEL;
ch = UNSIGN (key[i++]);
}
ch0 += (ch >> 1);
}
data[j++] = ch0;
if (ch & 01) {
data[j++] = DELIM;
k = 1;
}
}
data[j--] = EOL;
if (j == 0)
data[0] = EOL;
else if (data[j] == DELIM)
data[j] = EOL;
if ((koffs + j) > 255)
goto again; /* oversize subscript */
while (j >= 0) {
if ((UNSIGN (ch = data[--j]) < SP) && (ch != DELIM))
break;
}
if (j < 0)
stcpy (&savnam[koffs], data);
else
goto again; /* illegal subscipt */
/*----------------------*/
}
length = UNSIGN (block[i++]);
k = 0;
if ((i + length) > offset)
break;
stcpy0 (data, &block[i], length);
i += length;
data[length] = EOL;
global (0, savnam, data); /* call original global */
if (merr () == PROTECT) {
printf ("\012cannot open intermediate file in /usr/tmp\012");
exit (1);
}
}
if (i != offset)
printf ("\012wrong offset %ld vs. %d\012", offset, i);
goto again;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>