mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 01:14:21 +00:00
426 lines
9.5 KiB
C
426 lines
9.5 KiB
C
/***
|
||
|
||
This file contains all the necessary routines to perform the
|
||
functioniality of CHSET. The two entry points are the functions
|
||
get_settings and set_fields. Both functions are called with a
|
||
byte pointer that points to a record. Both functions return an
|
||
error code from BDOS if you have set f_errmode (O.S. call 0x2d)
|
||
to 0xfe or 0xff.
|
||
|
||
Format of record:
|
||
|
||
---------------------------------------------------
|
||
| d | filename | typ | password | fields |
|
||
---------------------------------------------------
|
||
byte 0 1 8 9 11 12 19 20 22
|
||
|
||
d drive number
|
||
filename filename (can have attribute bits on)
|
||
typ type (can have attribute bits on)
|
||
password password
|
||
fields offset name
|
||
20 8087
|
||
21 SHARED
|
||
22 SUSPEND
|
||
|
||
GET_SETTINGS:
|
||
|
||
On exit, without an error, all fields will have a byte number in
|
||
them corresponding to the bit pattern that was match in com_tab. For
|
||
example the field SUSPEND has to possible settings ON and OFF, since
|
||
ON is before OFF in com_tab a zero will represent it while a one will
|
||
represent the setting of OFF.
|
||
|
||
SET_FIELDS:
|
||
|
||
On exit, without an error, all fields that where not EMPTY(i.e. -1)
|
||
will have caused the corresponding bit(s) in the given filespec to
|
||
be set or reset.
|
||
|
||
|
||
NOTES:
|
||
|
||
All offsets and counts are from zero unless specified otherwise.
|
||
|
||
BDOS opens write password protected files in R/O mode when the
|
||
wrong password is given; and then wrongly reports an R/O file
|
||
error when we try to write to the file. Therefore set_fields
|
||
prints out a proper error msg. If you set f_errmode to 0xff
|
||
you will need to compile with the -dno_errors option so this
|
||
special error message will not be printed.
|
||
|
||
|
||
***/
|
||
|
||
#include <portab.h>
|
||
#include "cpmfunc.h"
|
||
|
||
EXTERN WORD _EXTERR; /* holds AX after O.S. call */
|
||
|
||
#define NOT_FOUND -1
|
||
#define EXIT_PROGRAM -1
|
||
#define CONTINUE 1
|
||
|
||
#define LOW_TO_UP ('a' - 'A')
|
||
|
||
#define T1 9 /* T1 attribute */
|
||
#define F7 7 /* F7 attribute */
|
||
#define F6 6 /* F6 attribute */
|
||
#define ON 0x80 /* mask for attribute bit */
|
||
|
||
#define PASSWORD 0x07ff /* BDOS error for wrong password */
|
||
#define RO_ERROR 0x03ff /* BDOS error for R/O file */
|
||
|
||
#define DMA_LEN 128
|
||
#define FCB_LEN 36
|
||
|
||
/*** Record Constants ***/
|
||
|
||
/* offsets */
|
||
|
||
#define REC_PASSWORD 12
|
||
#define REC_FIELDS 20
|
||
|
||
/* values */
|
||
|
||
#define EMPTY -1 /* Can not be same as option number */
|
||
|
||
|
||
/***
|
||
|
||
ADDING NEW FIELDS:
|
||
|
||
Add the correct data to com_tab[], add one to MAX_FIELD for
|
||
each new field and modify first_opt[] to reflect where the new options
|
||
are in the com_tab[].
|
||
|
||
***/
|
||
|
||
struct comm_str
|
||
{
|
||
LONG rec_num; /* Record 0,1,....big */
|
||
WORD byte_num; /* Byte 0,1,...,127 */
|
||
BYTE bit_num; /* Bit 7,6,...,1,0 */
|
||
BYTE *pattern; /* Pattern 0 or 1 or X */
|
||
};
|
||
|
||
struct comm_str com_tab[] =
|
||
{
|
||
0L, 127, 6, "X1", /* 80 = on */
|
||
0L, 127, 6, "00", /* 80 = of */
|
||
0L, 127, 6, "10", /* 80 = op */
|
||
|
||
0L, 0, 3, "1", /* sh = on */
|
||
0L, 0, 3, "0", /* sh = of */
|
||
|
||
0L, 127, 3, "1", /* su = on */
|
||
0L, 127, 3, "0" /* su = of */
|
||
};
|
||
|
||
|
||
#define MAX_FIELD 3
|
||
|
||
|
||
BYTE first_opt[] =
|
||
{
|
||
0, /* 8087 */
|
||
3, /* shared */
|
||
5, /* suspend */
|
||
7 /* tells routines that suspend is 5,6 only */
|
||
};
|
||
|
||
BYTE *bdos_01_msg = "\n\rFile password protected in Write mode\n\r";
|
||
|
||
BYTE buffer[DMA_LEN];
|
||
|
||
BYTE fcb_01[FCB_LEN];
|
||
|
||
|
||
WORD get_settings(record)
|
||
|
||
|
||
BYTE *record;
|
||
|
||
{
|
||
|
||
BYTE *fcb; /* FCB pointer */
|
||
BYTE *dma; /* DMA pointer */
|
||
BYTE *field; /* pts to field's options */
|
||
LONG cur_rec; /* current record in DMA */
|
||
WORD error;
|
||
WORD i;
|
||
BYTE start,end;
|
||
|
||
fcb = &fcb_01[0]; /* set up FCB */
|
||
field = record + REC_FIELDS; /* pts to the first field's option */
|
||
copy(record,fcb,12); /* put dfilenametyp in FCB */
|
||
*(fcb+12) = 0; /* extent number */
|
||
f_dmaset(record+REC_PASSWORD); /* DMA points to the password */
|
||
*(fcb+F6) = *(fcb+F6) | ON; /* Set to Read/Only */
|
||
f_open(fcb);
|
||
if ( (error = _EXTERR) != 0)
|
||
{
|
||
return(error);
|
||
}
|
||
dma = &buffer[0];
|
||
f_dmaset(dma);
|
||
cur_rec = -1; /* i.e. no record in DMA */
|
||
for ( i=0; i < MAX_FIELD; i++)
|
||
{
|
||
if ( cur_rec != com_tab[i].rec_num )
|
||
{
|
||
if ( (error=get_rec(fcb,com_tab[i].rec_num,FALSE)) != 0)
|
||
{
|
||
f_close(fcb);
|
||
return(error);
|
||
}
|
||
}
|
||
start = first_opt[i];
|
||
end = first_opt[i+1] - 1;
|
||
end = cmp_patterns(start,end,dma);
|
||
*field++ = end;
|
||
}
|
||
f_close(fcb);
|
||
if (_EXTERR !=0)
|
||
{
|
||
return(_EXTERR);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
|
||
|
||
VOID set_ran_rec(fcb,rec_number)
|
||
|
||
BYTE *fcb;
|
||
LONG rec_number;
|
||
|
||
{
|
||
|
||
*(fcb+33) = (0xffL & rec_number);
|
||
*(fcb+34) = ((0xff00L & rec_number) >> 8);
|
||
*(fcb+35) = ((0xff0000L & rec_number) >> 16);
|
||
|
||
}
|
||
|
||
WORD cmp_patterns(start,end,dma)
|
||
|
||
BYTE start;
|
||
BYTE end;
|
||
BYTE *dma; /* ptr to DMA buffer */
|
||
|
||
{
|
||
BYTE index;
|
||
BYTE *byte_ptr;
|
||
|
||
for (index=start; index<=end; index++)
|
||
{
|
||
if ( ((bits_match(&com_tab[index],dma)) == TRUE) )
|
||
{
|
||
return(index-start);
|
||
}
|
||
}
|
||
return(-1);
|
||
}
|
||
|
||
|
||
WORD bits_match(com_rec,dma)
|
||
|
||
struct comm_str *com_rec;
|
||
BYTE *dma;
|
||
|
||
{
|
||
|
||
BYTE *byte_ptr; /* points to byte */
|
||
BYTE bit_number; /* 8 0's and 1's */
|
||
BYTE bit; /* contains a 0 or 1 */
|
||
BYTE *bit_pattern; /* pts to pattern */
|
||
BYTE is_on;
|
||
|
||
byte_ptr = dma + com_rec->byte_num;
|
||
bit_pattern = com_rec->pattern;
|
||
bit_number = com_rec->bit_num;
|
||
while ( (*bit_pattern != NULL) )
|
||
{ /* still in pattern */
|
||
is_on = ((*byte_ptr) >> (bit_number)) & 0x01;
|
||
/** is_on is 1 if bit coresponding to pattern is on **/
|
||
if ( ((is_on == 1) && (*bit_pattern == '0')) ||
|
||
((is_on == 0) && (*bit_pattern == '1')) )
|
||
{ /* not a match */
|
||
return(FALSE);
|
||
}
|
||
bit_pattern++; /* pts to next char that represents a bit */
|
||
bit_number--; /* dec bit postion to check pattern against */
|
||
}
|
||
return(TRUE);
|
||
}
|
||
|
||
VOID copy(source,dest,cnt)
|
||
|
||
BYTE *source;
|
||
BYTE *dest;
|
||
WORD cnt;
|
||
|
||
{
|
||
|
||
BYTE i;
|
||
|
||
for (i=0; i<cnt; i++)
|
||
{
|
||
*dest++ = *source++;
|
||
}
|
||
}
|
||
|
||
|
||
WORD get_rec(fcb,rec_num,write)
|
||
|
||
BYTE *fcb;
|
||
LONG rec_num;
|
||
WORD write; /* flag to dump DMA or not */
|
||
|
||
{
|
||
|
||
if ( write == TRUE )
|
||
{ /* Will write out DMA buffer */
|
||
f_writerand(fcb);
|
||
if (_EXTERR != 0)
|
||
{
|
||
return(_EXTERR);
|
||
}
|
||
}
|
||
set_ran_rec(fcb,rec_num);
|
||
f_readrand(fcb);
|
||
if (_EXTERR != 0)
|
||
{
|
||
return(_EXTERR);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
WORD set_fields(record)
|
||
|
||
|
||
BYTE *record;
|
||
|
||
{
|
||
|
||
BYTE *fcb; /* FCB pointer */
|
||
BYTE *dma; /* DMA pointer */
|
||
BYTE *field; /* pts to field's options */
|
||
LONG cur_rec; /* current record in DMA */
|
||
WORD error;
|
||
WORD i;
|
||
WORD ro_wr_pass = FALSE; /* RO because of wrong pass */
|
||
BYTE start;
|
||
WORD end;
|
||
WORD write; /* Flag to write DMA or not */
|
||
|
||
fcb = &fcb_01[0]; /* set up FCB */
|
||
field = record + REC_FIELDS; /* pts to the first field's option */
|
||
copy(record,fcb,12); /* put dfilenametyp in FCB */
|
||
*(fcb+12) = 0; /* extent number */
|
||
f_dmaset(record+REC_PASSWORD); /* DMA points to the password */
|
||
f_open(fcb);
|
||
if (_EXTERR != 0)
|
||
{
|
||
return(_EXTERR);
|
||
}
|
||
if ( (((*(fcb+T1)) & 0x80) != ON) && (((*(fcb+F7)) & 0x80) == ON) )
|
||
{ /* File is RW and write protected but wrong password */
|
||
ro_wr_pass = TRUE;
|
||
}
|
||
dma = &buffer[0];
|
||
f_dmaset(dma);
|
||
cur_rec = -1; /* i.e. no record in DMA */
|
||
write = FALSE;
|
||
for ( i=0; i < MAX_FIELD; i++)
|
||
{
|
||
if ( (*(field+i) != ((BYTE)EMPTY)) )
|
||
{ /* given field needs to be set */
|
||
if ( (cur_rec != com_tab[i].rec_num) )
|
||
{ /* In different record so fetch it */
|
||
if ((error=get_rec(fcb,com_tab[i].rec_num,write)) != 0)
|
||
{
|
||
f_close(fcb);
|
||
return(error);
|
||
}
|
||
else
|
||
{
|
||
cur_rec = com_tab[i].rec_num;
|
||
write = FALSE; /* default after a read */
|
||
}
|
||
}
|
||
start = first_opt[i] + *(field+i); /* opt loc in table */
|
||
end = cmp_patterns(start,start,dma);
|
||
if ( (end == -1) )
|
||
{ /* must set field */
|
||
if ( ro_wr_pass == TRUE )
|
||
{ /* Need password so bug user for it */
|
||
/***
|
||
Next line needed as BDOS will not print a error msg.
|
||
if you compile with -dno_errors then you will
|
||
not get this error msg.
|
||
***/
|
||
#ifndef no_errors
|
||
c_writestr(bdos_01_msg);
|
||
#endif
|
||
return(PASSWORD);
|
||
}
|
||
write = TRUE; /* will need to write DMA */
|
||
set_pattern(&com_tab[start],dma);
|
||
}
|
||
}
|
||
}
|
||
if ( write == TRUE)
|
||
{
|
||
f_writerand(fcb);
|
||
error = _EXTERR;
|
||
if ( (error != 0) )
|
||
{
|
||
f_close(fcb); /* will try to close */
|
||
return(error); /* returning write error */
|
||
}
|
||
}
|
||
f_close(fcb);
|
||
if (_EXTERR !=0)
|
||
{
|
||
return(_EXTERR);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
|
||
VOID set_pattern(com_rec,dma)
|
||
|
||
struct comm_str *com_rec;
|
||
BYTE *dma; /* pts to buffer */
|
||
|
||
{
|
||
|
||
BYTE *byte_ptr; /* points to byte */
|
||
BYTE bit_number; /* the bit number */
|
||
BYTE *bit_pattern; /* pts to pattern */
|
||
BYTE mask;
|
||
|
||
byte_ptr = dma + com_rec->byte_num;
|
||
bit_pattern = com_rec->pattern;
|
||
bit_number = com_rec->bit_num;
|
||
while ( (*bit_pattern != NULL) )
|
||
{ /* still have bits to do */
|
||
if ( (*bit_pattern != 'X') )
|
||
{ /* either a '1' or '0' so set */
|
||
mask = (0x01 << (bit_number));
|
||
if (*bit_pattern == '0')
|
||
{ /* AND bit to zero */
|
||
*byte_ptr = (*byte_ptr & ~(mask));
|
||
}
|
||
else
|
||
{ /* OR bit to a one */
|
||
*byte_ptr = (*byte_ptr | mask);
|
||
}
|
||
}
|
||
bit_pattern++; /* point to next bit in pattern */
|
||
bit_number--; /* point to next bit in DMA */
|
||
}
|
||
}
|
||
|