File:  [Coherent Logic Development] / freem / src / grestore.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 19:14:25 2025 UTC (3 weeks, 2 days ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
First phase of REUSE compliance and header reformat

/*
 *   $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>