#ifndef PART1
#ifndef PART2
#define PART1 1
#define PART2 1
#endif
#endif
#ifdef PART1
#define INIT = {0}
#else
#define INIT
#endif
#ifdef hpux
#define SYSTEM5 1
#endif
#ifdef SYSTEM5
#define TTYSTRUCT termio
#else
#define TTYSTRUCT sgttyb
#endif
#define BYTE unsigned char
#define WORD unsigned short
#define LONG long
#define FAST register
#define VOID int
#define BOOL int
#define YES 1
#define NO 0
#define VERSION "6.00"
#define INIT_TYPE 0
#define START_TYPE 3
#define ASTRT_TYPE 4
#define DATA_TYPE 5
#define EOD_TYPE 6
#define ABORT_TYPE 7
#define AEOD_TYPE 8
#define EXIT_TYPE 9
#define START_LEN 55
#define ASTRT_LEN 90
#define EOD_LEN 2
#define ABORT_LEN 84
#define AEOD_LEN 84
#define EXIT_LEN 2
#define RESIZE_BLK 0
#define DATA_BLK 1
#define DUMMY_BLK 3
#define START_ONLY 1
#define DATA_OR_EOD 2
#define CONTROL_ONLY 3
#define QUIT_NORMAL 0
#define QUIT_SHUTDOWN 1
#define QUIT_READ_TTY 2
#define QUIT_WRITE_TTY 3
#define QUIT_ABORT_TTY 4
#define QUIT_TIMEOUT 5
#define ASCII 'A'
#define FROM_SLAVE 0x00
#define BU_FILENM ".*.*.* /WRQ BACKUP\\ *.*.*."
#define RE_FILENM ".*.*.* /WRQ RESTORE\\ *.*.*."
#define TEMPFILE "r2wrqres.tmp"
#define MAX_SPACES 125
#define REC_SEPARATOR 0xff
#define START 0
#define STABLE 1
#define ESCAPE 2
#define DUPLICATE 3
#define COUNT 4
#define COMPRESS '~'
#define MIN_DUPS 4
#define DATABUFSZ 524
#define UPLDBFSZ 512
#define TT_BUF_OUT 1600
#define IOBUFSZ 512
#define TT_BUF_IN 256
#define TTBUF_MAX 1472
#define VERSZ 8
#define FNAMESZ 42
#define ERRTXSZ 80
#define PATHSIZE 80
#define DEF_BURECSZ 256
#define DEF_BUHASH 128
#define TIME_MIN 10
#define TIME_MAX 20*60
#define NO_TIMEOUT -1
#define TIME_DEFAULT 60
#define DEF_RETRY 5
#define TIMEOUT_EIGHT 20
#ifndef NULL
#define NULL 0
#endif
#ifdef DG
#include <paru.h>
#define SOH 14
int dgcode = 0;
#else
#define SOH 1
#endif
#define STX 2
#define CTRL_C 3
#define CR 13
#define DC1 17
#define XON 17
#define XOFF 19
#define CTRL_Y 25
#define ACK 'S'
#define ACK_T 'T'
#define NAK 'F'
#define NOERROR 0
#define EXISTS 100
#define FILE_NF 52
#define TYPE_CNT 5
#define UPLOAD 0
#define DNLOAD 1
#define BACKUP 2
#define RESTORE 3
#define SAVE 4
#define BU_FNSZ 72
#define BU_MAXRSZ 256
#define BU_VERSZ 4
#define BU_MAXBUCK 1024
#define BU_DEFBUCK 256
#define DUMMY_TIMEOUT 5
#define BU_DIRSZ 97
#define BU_HDRSZ 154
#define CKPT_OKAY 0
#define CKPT_INITIATE 1
#define CKPT_DELETE 2
#define CKPT_INSTALL 3
#define SD_CHAR '\\'
#define AUTOSIZE 300
#define SUBDIR '\001'
#define FCHAR 'C'
#define FDOT 'D'
#define FANY 'A'
#define FSUBDIR 'S'
#define FSUCCEED 'Y'
#define FFAIL 'F'
#include <stdio.h>
#ifdef SYSTEM5
#include <termio.h>
#include <fcntl.h>
#else
#include <sgtty.h>
#endif
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
typedef struct
{
WORD reclen;
LONG filesize;
BYTE method;
BYTE direction;
BYTE filename[42];
BYTE bits_allowed;
BYTE compression;
BYTE option_byte;
} STRTMSG;
typedef struct
{
WORD datalen;
BYTE databuf[DATABUFSZ];
} DATAMSG;
typedef struct {
LONG syn_next;
LONG dfirst;
LONG dlast;
WORD fdate;
WORD ftime;
LONG fsize;
WORD ddate;
WORD dtime;
BYTE dattr;
BYTE fname[BU_FNSZ];
} DIR;
typedef struct {
BYTE version[BU_VERSZ];
WORD recsize;
WORD buckets;
BYTE hrec_count;
WORD hblocking;
LONG free_first;
LONG free_last;
LONG file_last;
WORD bu_date;
WORD bu_time;
BYTE c_status;
BYTE c_dupname;
LONG c_prior;
LONG c_current;
LONG c_bucket;
LONG c_nfirst;
LONG c_newdir;
LONG c_odfirst;
LONG c_odlast;
DIR c_dir;
} HDR;
int tty_timeout();
int send_dummy();
LONG file_size();
BYTE get_raw();
BYTE get_byte();
long get_long();
char *get_string();
BYTE getd_char();
WORD getd_word();
LONG getd_long();
BYTE Bread();
BYTE bgchar();
WORD bgword();
LONG bglink();
LONG bglong();
VOID getd_byte_1();
VOID getd_byte_2();
VOID putd_byte_1();
VOID putd_byte_2();
VOID (*putd_byte)() = putd_byte_1;
VOID (*getd_byte)() = getd_byte_1;
LONG htab[BU_MAXBUCK] INIT;
BYTE bu_rec[BU_MAXRSZ] INIT;
BYTE bu_rec2[BU_MAXRSZ] INIT;
BYTE *bu_ptr INIT;
LONG bu_link INIT;
LONG file_lrec INIT;
LONG backup_eof INIT;
BYTE autotab[AUTOSIZE+1] = {0};
BYTE *autoix = NULL;
DIR dir INIT;
HDR hdr INIT;
BYTE dupname INIT;
LONG prior INIT;
LONG current INIT;
LONG bucket INIT;
LONG nfirst INIT;
LONG newdir INIT;
LONG odfirst INIT;
LONG odlast INIT;
WORD ferrno INIT;
char *ferrtx INIT;
#ifdef PART1
int file_created_yet = NO;
int backup_closed = YES;
int is_lat = NO;
int is_rt = NO;
int _8_bit = NO;
int _7_bit_explicit = NO;
int resized = NO;
int resizing = NO;
int tt_buf_out = TT_BUF_OUT;
char *type[TYPE_CNT] = {"upload", "download", "backup","restore",
"save parameters"};
LONG transfer_type;
int send_dummy_blk = NO;
int buffer_overflow = NO;
unsigned int state = 0;
unsigned char new_putd_chr;
WORD get_crc = 0;
int retry_limit = DEF_RETRY;
int cur_blksz = 116;
WORD data_count = 0;
BYTE pbuf[TT_BUF_OUT] = {NULL};
BYTE *pbufp = (BYTE *) NULL;
WORD pblkno = 1;
WORD put_crc = 0;
BOOL aborting = NO;
BOOL eight_bit = NO;
BOOL soh = SOH;
LONG default_bufsz = TT_BUF_IN;
LONG active_bufsz = TT_BUF_IN;
LONG message_byte_cnt;
BOOL escape_mode = NO;
BOOL b_comp = NO;
LONG sub_block_len = 0;
STRTMSG s_msg = {0};
DATAMSG d_msg = {0};
WORD msg_type = 0;
LONG host_rec_len = 0;
BOOL pc2622 = 0;
BOOL do_readsync = 0;
short image_transfer = NO;
short image_header = YES;
short word_perfect = NO;
BYTE dbuf[DATABUFSZ+4] = {0};
int dbufcnt = 0;
int space_cnt = 0;
BYTE iobuf[IOBUFSZ] = {0};
BYTE op_buf[UPLDBFSZ+1] = {0};
int op_len = 0;
int gbuf_used = 0;
int gbuf_count = 0;
int data_ix = 0;
BOOL eof_data = NO;
int blankct = 0;
BYTE blk_type = 0;
WORD info_len = 0;
WORD in_blkno = 0;
WORD last_blkno = 0;
WORD info_seen = 0;
WORD resize_request = 0;
int errno;
int u_fd = -1;
int u_eof = NO;
int tb_max = 0;
int RF_fd = 0;
int RF_rsize = 0;
int RF_eof = 0;
FILE *RF_ptr;
int timeout = NO_TIMEOUT;
WORD crctab[256] = {
0,4129,8258,12387,16516,20645,24774,28903,
33032,37161,41290,45419,49548,53677,57806,61935,
4657,528,12915,8786,21173,17044,29431,25302,
37689,33560,45947,41818,54205,50076,62463,58334,
9314,13379,1056,5121,25830,29895,17572,21637,
42346,46411,34088,38153,58862,62927,50604,54669,
13907,9842,5649,1584,30423,26358,22165,18100,
46939,42874,38681,34616,63455,59390,55197,51132,
18628,22757,26758,30887,2112,6241,10242,14371,
51660,55789,59790,63919,35144,39273,43274,47403,
23285,19156,31415,27286,6769,2640,14899,10770,
56317,52188,64447,60318,39801,35672,47931,43802,
27814,31879,19684,23749,11298,15363,3168,7233,
60846,64911,52716,56781,44330,48395,36200,40265,
32407,28342,24277,20212,15891,11826,7761,3696,
65439,61374,57309,53244,48923,44858,40793,36728,
37256,33193,45514,41451,53516,49453,61774,57711,
4224,161,12482,8419,20484,16421,28742,24679,
33721,37784,41979,46042,49981,54044,58239,62302,
689,4752,8947,13010,16949,21012,25207,29270,
46570,42443,38312,34185,62830,58703,54572,50445,
13538,9411,5280,1153,29798,25671,21540,17413,
42971,47098,34713,38840,59231,63358,50973,55100,
9939,14066,1681,5808,26199,30326,17941,22068,
55628,51565,63758,59695,39368,35305,47498,43435,
22596,18533,30726,26663,6336,2273,14466,10403,
52093,56156,60223,64286,35833,39896,43963,48026,
19061,23124,27191,31254,2801,6864,10931,14994,
64814,60687,56684,52557,48554,44427,40424,36297,
31782,27655,23652,19525,15522,11395,7392,3265,
61215,65342,53085,57212,44955,49082,36825,40952,
28183,32310,20053,24180,11923,16050,3793,7920
};
BYTE gbuf[TTBUF_MAX] = {0};
struct TTYSTRUCT curtty;
struct TTYSTRUCT oldtty;
#define swap(X,Y) {(X)=(X)^(Y); (Y)=(X)^(Y); (X)=(X)^(Y);}
#define docrc(old, c) (old = (old<<8) ^ crctab[((old>>8)^c) & 0xff])
#define LSB(x) ((x) & 0xff)
#define MSB(x) (((x) >> 8) & 0xff)
#define MAX(A,B) ((B>A) ? (B) : (A))
#define WRQRAW (++message_byte_cnt && buffer_overflow ? soh :\
(gbuf_used>=gbuf_count? get_raw(): gbuf[gbuf_used++]))
#define GETC ((data_ix >= d_msg.datalen)? getd_data():\
d_msg.databuf[data_ix++])
#define PUTC(x) {if (dbufcnt>=cur_blksz) putd_flush();\
dbuf[dbufcnt++]=(x);}
#define PUTB(ch) (*pbufp++ = (ch))
#define TREAD(a,b) read(0, a, b)
#define TWRITE(a,b) write(1, a, b)
VOID main(ac, av)
int ac;
char **av;
{
char *ap;
while (ap = *++av)
switch (*ap)
{
case '/':
case '-':
switch (*++ap)
{
case 't':
if (!(*++ap) && !(ap = *++av))
usage();
for (timeout = 0; *ap; ++ap)
if (*ap < '0' || *ap > '9')
usage();
else
timeout = timeout*10 + (*ap - '0');
if (!timeout)
timeout = TIME_MAX;
break;
case 'o':
pc2622 = 1;
break;
#ifdef DG
case 'p':
dgcode = 1;
break;
#endif
default:
usage();
}
break;
default:
usage();
}
tty_open();
if (!_8_bit) {
send_init();
recv_message(START_ONLY);
}
for (;;)
{
if (!strcmp(s_msg.filename, BU_FILENM))
{
transfer_type = BACKUP;
backup();
}
else if (!strcmp(s_msg.filename, RE_FILENM))
{
if (s_msg.direction == FROM_SLAVE)
{
transfer_type = RESTORE;
restore();
}
else
{
transfer_type = SAVE;
save_parms();
}
}
else
{
if (s_msg.direction == FROM_SLAVE)
{
transfer_type = DNLOAD;
dnload();
}
else
{
transfer_type = UPLOAD;
upload();
}
}
recv_message(START_ONLY);
}
}
VOID usage()
{
#ifdef DG
write(2, "usage: dglink [-t timeout_seconds, -o]\n", 40);
#else
write(2, "usage: unixlink [-t timeout_seconds, -o]\n", 40);
#endif
exit(1);
}
VOID dnload()
{
char *addr;
LONG size;
int i, j, k;
if ((size = file_size(s_msg.filename)) == -1) {
send_astrt(FILE_NF, "Requested file not present.", 0L);
}
else if (size == -2)
send_astrt(ferrno, ferrtx, 0L);
else
{
send_astrt(NOERROR, "", size);
{
file_open(s_msg.filename);
data_count = 0;
for (i=file_read(iobuf,IOBUFSZ); i; i=file_read(iobuf,IOBUFSZ))
for (j = 0; j < i; ++j)
{ (*putd_byte)(iobuf[j]);
++data_count;
}
if (b_comp) binary_c_flush();
putd_flush();
file_close();
send_eod();
}
}
}
VOID upload()
{
char *addr;
LONG size;
size = file_size(s_msg.filename);
if (size == -2)  {
send_astrt(ferrno, ferrtx, 0L);
return;
}
if (size == -1)
send_astrt(NOERROR, "", 0L);
else
send_astrt(EXISTS, "File already exists.", size);
getd_init();
op_len = 0;
if (image_transfer == NO) upload_binary_ascii();
else if (image_header == YES) upload_image_head();
else if (word_perfect == YES) upload_image_wp();
else upload_image_nohead();
if (file_close() == -1) send_aeod(ferrno, ferrtx);
else send_aeod(0, "");
}
VOID upload_binary_ascii()
{
LONG i,j;
for (i = (*getd_byte)(); i != EOF; i = (*getd_byte)() ) {
if (op_len >= UPLDBFSZ) {
file_write(op_buf, op_len);
op_len = 0;
}
op_buf[op_len++] = i;
}
if (op_len) file_write(op_buf, op_len);
}
VOID upload_image_nohead()
{
}
VOID upload_image_wp()
{
}
VOID upload_image_head()
{
}
VOID backup()
{
BYTE bu_file[FNAMESZ+1];
WORD new_date, new_time;
int b;
BYTE pname[PATHSIZE+1];
LONG fsize;
WORD fdate, ftime;
BYTE fattr;
LONG i;
LONG backup_desc;
send_astrt(NOERROR, "", 1);
getd_init();
getd_str(bu_file, FNAMESZ);
new_date = getd_word();
new_time = getd_word();
Binit(bu_file, YES, DEF_BURECSZ, DEF_BUHASH);
for (b = (*getd_byte)(); b != EOF; b = (*getd_byte)() )
{
pname[0] = b;
getd_str(&pname[1], PATHSIZE-1);
fsize = getd_long();
fdate = getd_word();
ftime = getd_word();
fattr = getd_char();
Bcreate();
for (i = 0; i < fsize; ++i)
Bwrite(getd_char());
Binstall(new_date, new_time, pname, fsize, fdate, ftime, fattr);
}
if (Bterm() == -1)
send_aeod(ferrno, ferrtx);
else
send_aeod(0, "");
}
VOID save_parms()
{
BYTE s_len;
BYTE bu_file[FNAMESZ+1];
BYTE pname[PATHSIZE+1];
BYTE subdirs[2];
getd_init();
file_create(TEMPFILE);
send_astrt(NOERROR, "", 1);
getd_str(bu_file, FNAMESZ);
getd_str(pname, PATHSIZE);
getd_str(subdirs, 2);
s_len = strlen(bu_file) + 32;
file_write(&s_len, 1);
file_write(bu_file, s_len-32);
s_len = strlen(pname) + 32;
file_write(&s_len, 1);
file_write(pname, s_len-32);
if (subdirs[0] == 'S')
file_write("S\n", 2);
else
file_write("N\n", 2);
for (;;) {
getd_pname(pname,PATHSIZE);
s_len = strlen(pname);
if (!(s_len))
break;
s_len += 32;
file_write(&s_len,1);
file_write(pname, s_len-32);
file_write("\n", 1);
}
if (file_close() == -1)
send_aeod(ferrno, ferrtx);
else
send_aeod(0, "");
}
VOID restore()
{
LONG i;
BYTE bu_file[FNAMESZ+1];
BYTE pname[PATHSIZE+1];
BYTE subdir;
BOOL subs_ok;
BOOL more;
BYTE s_len;
int temp_fd, rest_fd;
file_open(TEMPFILE);
temp_fd = u_fd;
if (file_read(&s_len, 1) != 1)
shutdown(-16, "Invalid temp file - restore");
if (s_len -= 32)
if (file_read(bu_file, s_len) != s_len)
shutdown(-17, "Invalid temp file - restore");
bu_file[s_len] = NULL;
if (file_read(&s_len, 1) != 1)
shutdown(-18, "Invalid temp file - restore");
if (s_len -= 32)
if (file_read(pname, s_len) != s_len)
shutdown(-19, "Invalid temp file - restore");
pname[s_len] = NULL;
if (file_read(&subdir, 1) != 1)
shutdown(-20, "Invalid temp file - restore");
if (subdir == 'S')
subs_ok = YES;
else
subs_ok = NO;
if (!Binit(bu_file, NO)) {
send_astrt(FILE_NF, "Requested backup file not present.");
}
else if (!pname[0]) {
send_astrt(-21, "Invalid pathname to be restored.");
}
else {
send_astrt(NOERROR, "", 1);
for (;;) {
for (more = Bopenf(pname, subs_ok); more; more = Bopenn()) {
putd_str(dir.fname);
putd_long(dir.fsize);
putd_word(dir.ddate);
putd_word(dir.dtime);
(*putd_byte)(dir.dattr);
for (i = 0; i < dir.fsize; ++i)
(*putd_byte)(Bread());
}
for (i=0; i <= AUTOSIZE; i++)
autotab[AUTOSIZE+1] = 0;
autoix = NULL;
rest_fd = u_fd;
u_fd = temp_fd;
file_read(&s_len,1);
if ((file_read(&s_len, 1) == 1) &&
(file_read(pname, s_len-32) == s_len-32)) {
pname[s_len] = NULL;
u_fd = rest_fd;
}
else {
file_close();
file_delete(TEMPFILE);
u_fd = rest_fd;
break;
}
}
if (b_comp) binary_c_flush();
putd_flush();
Bterm();
send_eod();
}
}
VOID shutdown(errcode, errtext)
WORD errcode;
BYTE *errtext;
{
static BOOL allover = NO;
if (!allover)
{
allover = YES;
send_abort(errcode, errtext);
recv_message(CONTROL_ONLY);
}
quit(QUIT_SHUTDOWN);
}
VOID quit(i)
{
tty_close();
exit(i);
}
BYTE get_raw()
{
while (gbuf_used >= gbuf_count) {
gbuf_count = tty_read(gbuf);
gbuf_used = 0;
}
return(gbuf[gbuf_used++]);
}
remove_pad(n)
int n;
{
}
BYTE get_byte()
{
BYTE c;
if (!(_8_bit)) {
if ((c = WRQRAW) == '&') {
if (((c = WRQRAW) == '#') && (c = WRQRAW) != '#' && c != '&') c ^= 0x40;
c ^= 0xC0;
}
else if (c == '#' && (c = WRQRAW) != '#' && c != '&') c ^= 0x40;
}
else c = WRQRAW;
docrc(get_crc, c);
return(c);
}
WORD get_word()
{
BYTE c;
c = get_byte();
return((c << 8) + get_byte());
}
LONG get_long()
{
WORD w;
w = get_word();
return((((LONG) w) << 16) + get_word());
}
int get_buffer(buf, cnt)
BYTE *buf;
int cnt;
{
for (;!buffer_overflow && cnt; ++buf, --cnt) *buf = get_byte();
}
VOID getd_init()
{
data_ix = 0;
d_msg.datalen = 0;
eof_data = NO;
blankct = 0;
}
int getd_byte_1()
{
BYTE c;
int i;
get_loop:
if (blankct)
{
--blankct;
return (' ');
}
if (data_ix >= d_msg.datalen)
{
data_ix = 0;
recv_message(DATA_OR_EOD);
if (msg_type == EOD_TYPE)
{
d_msg.datalen = 0;
eof_data = YES;
}
}
if (eof_data)
return (EOF);
c = d_msg.databuf[data_ix++];
if (s_msg.method == ASCII)
{
if (c == REC_SEPARATOR)
{
return('\n');
}
else
{
if (escape_mode)
{
escape_mode = NO;
c = c | 0x80;
goto take_char;
}
if (c == 254)
if (eight_bit)
{
escape_mode = YES;
goto get_loop;
}
if (c & 0x80)
{
blankct = c & 0x7F;
return ((*getd_byte)());
}
}
}
take_char:
i = c;
return(i & 0x00FF);
}
int getd_byte_2()
{
static unsigned char dup,
count;
static unsigned int state = STABLE;
int c;
for (;;) {
switch (state) {
case STABLE: if ((c = GETC) != COMPRESS)
return(c);
state = DUPLICATE;
count = GETC - 32;
dup = GETC;
return(dup);
case DUPLICATE: if (--count)
return(dup);
state = STABLE;
}
}
}
int getd_data()
{
data_ix = 0;
recv_message(DATA_OR_EOD);
if (msg_type == EOD_TYPE)
return(EOF);
else return(d_msg.databuf[data_ix++]);
}
BYTE getd_char()
{
int c;
if ((c = (*getd_byte)()) == EOF)
shutdown(-37, "File hasn't changed since last backup");
return(c & 0xFF);
}
WORD getd_word()
{
BYTE c;
c = getd_char();
return( (c<<8) + ((*getd_byte)() & 0xFF) );
}
LONG getd_long()
{
WORD w;
w = getd_word();
return( (((LONG) w) << 16) + (getd_word() & 0xFFFF) );
}
VOID getd_str(buf, maxsz)
BYTE *buf;
int maxsz;
{
while(*buf++ = getd_char())
if (!(maxsz--))
shutdown(-23, "Internal error - string too long.");
}
VOID getd_pname(buf, maxsz)
BYTE *buf;
int maxsz;
{
int c;
for (;;) {
c = (*getd_byte)();
if (c == EOF || c == 0) {
*buf++ = (BYTE) 0;
return;
}
*buf++ = (BYTE) c;
if (!(maxsz--))
shutdown(-23, "Internal error - string too long.");
}
}
VOID put_byte(c)
BYTE c;
{
c &= 0xff;
docrc(put_crc, c);
if (!(_8_bit)) {
if ((c == '#') || (c == '&')) PUTB('#');
else if ((c == 0x7F) || (c < 0x20)) {
PUTB('#');
c ^= 0x40;
}
else if (c > 0x7F) {
PUTB('&');
c ^= 0xC0;
if ((c == '#') || (c == '&')) PUTB('#');
else if ((c == 0x7F) || (c < 0x20)) {
PUTB('#');
c ^= 0x40;
}
}
}
PUTB(c);
if (pbufp >= pbuf + tt_buf_out)
shutdown(-9, "Internal buffer overflow.");
}
VOID put_word(w)
WORD w;
{
put_byte(MSB(w));
put_byte(LSB(w));
}
VOID put_long(lo)
LONG lo;
{
put_word((lo>>16) & 0xFFFF);
put_word(lo & 0xFFFF);
}
VOID put_string(p, maxlen)
BYTE *p;
int maxlen;
{
for (; (maxlen > 1) && *p; --maxlen)
put_byte(*p++);
while (maxlen-- > 1)
put_byte(NULL);
put_byte(NULL);
}
VOID put_begin(msgtype, infolen)
WORD msgtype;
int infolen;
{
pbuf[0] = soh;
pbufp = pbuf + 1;
put_crc = 0;
put_byte(DATA_BLK);
put_word(infolen);
put_word(pblkno);
put_word(msgtype);
aborting = (msgtype == ABORT_TYPE) ? YES : NO;
}
put_end()
{
int i;
static char c[TTBUF_MAX];
put_word(put_crc);
if (!(++pblkno & 0xffff)) pblkno = 1;
for(;;) {
tty_write(pbuf,pbufp - pbuf);
i = tty_read(c);
if (c[--i]==ACK)
return(YES);
else if (c[i] == ACK_T) {
if (!aborting) {
recv_message(CONTROL_ONLY);
}
return(YES);
}
}
}
VOID putd_byte_1(c)
BYTE c;
{
if (space_cnt)
if (c == ' ')
{
if (++space_cnt > MAX_SPACES)
dbuf[dbufcnt-1] = MAX_SPACES | 0x80;
else
return;
}
else
{
if (space_cnt > 1)
dbuf[dbufcnt-1] = space_cnt | 0x80;
space_cnt = 0;
}
if (dbufcnt >= cur_blksz)
putd_flush();
if (s_msg.method == ASCII)
{
if (c & 0x80)
{
if (eight_bit)
{
dbuf[dbufcnt++] = 0xFE;
if (dbufcnt >= cur_blksz)
putd_flush();
c = (c & 0x7F);
dbuf[dbufcnt++] = c;
return;
}
c = (c & 0x7F);
}
if (c == ' ')
space_cnt = 1;
else if (c == '\n')
{
c = REC_SEPARATOR;
}
}
dbuf[dbufcnt++] = c;
}
VOID putd_byte_2(c)
unsigned char c;
{
static unsigned char old,
rep,
count;
do {
switch (state)
{
case START: old = c;
state = STABLE;
break;
case STABLE: new_putd_chr = c;
if (new_putd_chr == old) {
state = DUPLICATE;
count = 1;
break;
}
swap(old,new_putd_chr);
if (new_putd_chr == COMPRESS) {
count = 1;
rep = new_putd_chr;
state = COUNT;
}
PUTC(new_putd_chr);
break;
case ESCAPE: rep = new_putd_chr;
new_putd_chr = COMPRESS;
state = COUNT;
PUTC(new_putd_chr);
break;
case DUPLICATE: new_putd_chr = c;
++count;
if (count && old == new_putd_chr)
break;
swap(old,new_putd_chr);
if (count >= MIN_DUPS || !count ||
new_putd_chr == COMPRESS) {
state = ESCAPE;
break;
}
--count;
while (count < MIN_DUPS) {
PUTC(new_putd_chr);
--count;
}
state = STABLE;
break;
case COUNT: PUTC(count+32);
state = STABLE;
PUTC(rep);
break;
}
}
while (state == ESCAPE || state == COUNT);
}
VOID binary_c_flush()
{
putd_byte_2(~new_putd_chr);
state = START;
}
VOID putd_word(w)
WORD w;
{
(*putd_byte)((BYTE) (MSB(w)));
(*putd_byte)((BYTE) (LSB(w)));
}
VOID putd_long(lo)
LONG lo;
{
putd_word( (WORD) ((lo>>16) & 0xFFFF) );
putd_word( (WORD) (lo & 0xFFFF) );
}
VOID putd_str(s)
BYTE *s;
{
while (*s)
(*putd_byte)(*s++);
(*putd_byte)(NULL);
}
VOID putd_flush()
{
if (space_cnt)
{
dbuf[dbufcnt-1] = space_cnt | 0x80;
space_cnt = 0;
}
send_data(dbuf, dbufcnt);
dbufcnt = 0;
}
VOID recv_message(expected)
{
for (;;)
{
recv_block();
if (blk_type == DATA_BLK && msg_type == EXIT_TYPE)
quit(QUIT_NORMAL);
if (in_blkno && (in_blkno == last_blkno))
continue;
if (!in_blkno)
last_blkno = 0;
else if (!(++last_blkno & 0xffff))
last_blkno = 1;
if (last_blkno != in_blkno)
shutdown(-5, "Block number sequence error.");
if (blk_type != RESIZE_BLK && blk_type != DATA_BLK
&& blk_type != DUMMY_BLK)
shutdown(-1, "Bad block type.");
if (expected == CONTROL_ONLY)
{
if (blk_type != DUMMY_BLK && blk_type != RESIZE_BLK)
shutdown(-2, "Unexpected message type.");
return;
}
if (blk_type == DATA_BLK)
{
if (expected == START_ONLY && msg_type != START_TYPE)
shutdown(-3, "Unexpected message type.");
if (expected == DATA_OR_EOD
&& (msg_type != DATA_TYPE && msg_type != EOD_TYPE))
shutdown(-4, "Unexpected message type.");
return;
}
}
}
VOID recv_block()
{
for (;;) {
while (WRQRAW != soh)
;
message_byte_cnt = 1;
get_crc = 0;
blk_type = get_byte();
if ((info_len = get_word()) & 1) ++info_len;
in_blkno = get_word();
if (info_len <= DATABUFSZ) {
info_seen = 0;
if (recv_fields()) {
for (; info_seen < info_len; ++info_seen) get_byte();
get_word();
if (!get_crc) {
ack_it(YES);
if (blk_type == RESIZE_BLK)
cur_blksz = resize_request - 12;
return;
}
}
}
nak_it();
}
}
BOOL recv_fields()
{
if (blk_type == RESIZE_BLK)
{
if ((resize_request = get_word()) > DATABUFSZ)
resize_request = 128;
info_seen = 2;
}
else if (blk_type == DATA_BLK)
{
if (info_len < 2)
return(NO);
msg_type = get_word();
info_seen = 2;
if (msg_type == START_TYPE)
{
if (info_len < 52)
return(NO);
s_msg.reclen = get_word();
s_msg.filesize = get_long();
s_msg.method = get_byte();
s_msg.direction = get_byte();
get_buffer(s_msg.filename, 42);
if (info_len > 52)
{
s_msg.bits_allowed = get_byte();
if (s_msg.bits_allowed = '8')
eight_bit = YES;
s_msg.compression = get_byte();
if (s_msg.compression = 'c' && s_msg.method != ASCII) {
b_comp = YES;
putd_byte = putd_byte_2;
getd_byte = getd_byte_2;
}
info_seen = 54;
}
else info_seen = 52;
}
else if (msg_type == DATA_TYPE)
{
if (info_len < 4)
return(NO);
if ((d_msg.datalen = get_word()) > DATABUFSZ)
return(NO);
if (gbuf_count>sub_block_len)
sub_block_len = gbuf_count;
get_buffer(d_msg.databuf, d_msg.datalen);
info_seen = d_msg.datalen + 4;
}
}
return(YES);
}
VOID ack_it(do_dc1)
int do_dc1;
{
tty_write("S", 1);
}
VOID ackt_it(do_dc1)
int do_dc1;
{
tty_write("T", 1);
}
VOID nak_it()
{
tty_write("F", 1);
}
VOID send_init()
{
int j,k;
j = 0;
do {
put_begin(INIT_TYPE, 14);
put_string("1.20", 5);
put_byte('6');
put_byte('.');
put_byte('0');
put_byte('0');
put_byte('8');
put_byte('c');
put_byte(0x00);
} while (!(k=put_end()) && ++j<retry_limit && --pblkno);
}
VOID send_astrt(errcode, errtext, filesz)
WORD errcode;
BYTE *errtext;
LONG filesz;
{
int j,k;
j = 0;
do {
put_begin(ASTRT_TYPE, ASTRT_LEN);
put_word(errcode);
put_string(errtext, ERRTXSZ);
put_word(1);
put_long(filesz);
} while (!(k=put_end()) && ++j<retry_limit && --pblkno);
}
VOID send_data(data, datalen)
BYTE *data;
WORD datalen;
{
BYTE *g;
WORD h;
int i,j,k;
i = datalen & 1;
j = 0;
do {
h = datalen;
g = data;
put_begin(DATA_TYPE, h + 4);
put_word(data_count);
while (h--) put_byte(*g++);
if (i) put_byte(NULL);
} while (!(k=put_end()) && ++j < retry_limit && --pblkno);
data_count = 0;
}
VOID send_eod()
{
int j,k;
j = 0;
do {
put_begin(EOD_TYPE, EOD_LEN);
} while (!(k=put_end()) && ++j<retry_limit && --pblkno);
}
VOID send_abort(errcode, errtext)
WORD errcode;
BYTE *errtext;
{
int j,k;
do {
put_begin(ABORT_TYPE, ABORT_LEN);
put_word(errcode);
put_string(errtext, ERRTXSZ);
} while (!(k=put_end()) && ++j<retry_limit && --pblkno);
}
VOID send_aeod(errcode, errtext)
WORD errcode;
BYTE *errtext;
{
int j,k;
j = 0;
do {
put_begin(AEOD_TYPE, AEOD_LEN);
put_word(errcode);
put_string(errtext, ERRTXSZ);
} while (!(k=put_end()) && ++j<retry_limit && --pblkno);
}
VOID send_resize(size)
int size;
{
}
VOID tty_open()
{
VOID tty_abort(), tty_timeout();
#ifdef SYSTEM5
ioctl(0, TCGETA, &oldtty);
curtty = oldtty;
curtty.c_lflag &= ~ECHO;
curtty.c_cc[2] = 8;
curtty.c_cc[3] = 21;
ioctl(0, TCSETA, &curtty);
#else
gtty(0, &oldtty);
curtty = oldtty;
curtty.sg_flags &= ~ECHO;
stty(0, &curtty);
#endif
signal(SIGHUP, tty_abort);
signal(SIGINT, tty_abort);
signal(SIGQUIT, tty_abort);
if (timeout != NO_TIMEOUT)
{
alarm(0);
signal(SIGALRM, tty_timeout);
}
tty_flush();
}
VOID tty_close()
{
#ifdef SYSTEM5
ioctl(0, TCSETA, &oldtty);
#else
stty(0, &oldtty);
#endif
}
int tty_read(buf)
char *buf;
{
tb_max = 0;
while (!tb_max)
{
if (timeout != NO_TIMEOUT)
alarm(timeout);
if ((tb_max = TREAD(buf, default_bufsz)) < 1)
quit(QUIT_READ_TTY);
while (tb_max && (buf[tb_max-1] == '\n' || buf[tb_max-1] == '\r'))
--tb_max;
}
return(tb_max);
}
VOID tty_write(buf, blen)
char *buf;
int blen;
{
char xbuf[2];
#ifdef DG
fflush(stdout);
#endif
if (blen > 1 && TWRITE(buf, blen-1) < 1)
quit(QUIT_WRITE_TTY);
if (blen)
{
xbuf[0] = buf[blen-1];
if (!pc2622)
{
xbuf[1] = '\r';
if (TWRITE(xbuf, 2) < 1)
quit(QUIT_WRITE_TTY);
}
}
else
{
if (!pc2622)
{
if (TWRITE("\r", 1) < 1)
quit(QUIT_WRITE_TTY);
}
}
}
VOID tty_flush()
{
#ifdef SYSTEM5
ioctl(0, TCSETA, &curtty);
#else
stty(0, &curtty);
#endif
}
VOID tty_timeout()
{
quit(QUIT_TIMEOUT);
}
VOID tty_abort()
{
quit(QUIT_ABORT_TTY);
}
VOID file_open(fn)
char *fn;
{
u_eof = NO;
u_fd = fl_open(fn, 0);
}
VOID file_create(fn)
char *fn;
{
u_fd = fl_create(fn);
}
int file_read(buf, blen)
char *buf;
int blen;
{
int i;
if (u_eof)
return(0);
if ((i = fl_read(u_fd, buf, blen)) != blen)
u_eof = YES;
return(i);
}
VOID file_write(buf, blen)
char *buf;
int blen;
{
if (file_created_yet == NO && transfer_type == UPLOAD) {
file_create(s_msg.filename);
file_created_yet = YES;
}
fl_write(u_fd, buf, blen);
}
int file_close()
{
return(fl_close(u_fd));
}
long file_size(fn)
char *fn;
{
struct stat sbuf;
if (stat(fn, &sbuf) == -1)
{
ferrno = errno;
ferrtx = "stat() failed";
#ifdef ENOTDIR
if (errno == ENOTDIR)
ferrtx = "a component of the path prefix is not a directory.";
#endif
#ifdef ENOENT
if (errno == ENOENT)
return(-1L);
#endif
#ifdef EACCES
if (errno == EACCES)
ferrtx = "read permission is denied for the specified file.";
#endif
return(-2L);
}
return(sbuf.st_size);
}
VOID file_delete(nm)
char *nm;
{
if (unlink(nm))
shutdown(errno, "error on file delete.");
}
VOID RF_create(nm, rsize)
char *nm;
int rsize;
{
if (fl_close(fl_create(nm)) == -1)
shutdown(ferrno, "close after RF_create failed.");
RF_open(nm, rsize);
}
VOID RF_open(nm, rsize)
char *nm;
int rsize;
{
RF_rsize = rsize;
RF_fd = fl_open(nm, 2);
}
VOID RF_read(buf, rnum)
char *buf;
LONG rnum;
{
RF_position(rnum);
if (fl_read(RF_fd, buf, RF_rsize) != RF_rsize)
shutdown(-45, "Invalid backup file record.");
}
VOID RF_write(buf, rnum)
char *buf;
LONG rnum;
{
RF_position(rnum);
fl_write(RF_fd, buf, RF_rsize);
}
int RF_close()
{
return(fl_close(RF_fd));
}
VOID RF_position(rnum)
LONG rnum;
{
long rval;
long lseek();
if ((rval = lseek(RF_fd, rnum * RF_rsize, 0)) == -1L)
{
ferrno = errno;
ferrtx = "lseek failed.";
#ifdef EBADF
if (errno == EBADF)
ferrtx = "lseek: invalid file handle.";
#endif
#ifdef EINVAL
if (errno == EINVAL)
ferrtx = "lseek: invalid origin or offset.";
#endif
shutdown(ferrno, ferrtx);
}
}
int fl_open(fn, open_flag)
char *fn;
int open_flag;
{
int r_value;
#ifdef SYSTEM5
if (open_flag = 0)
open_flag = O_RDONLY;
else
open_flag = O_RDWR;
#endif
if ((r_value = open(fn, open_flag)) == -1)
{
ferrno = errno;
ferrtx = "open failed; file not found or inaccessible.";
#ifdef ENOTDIR
if (errno == ENOTDIR)
ferrtx = "a component of the path prefix is not a directory.";
#endif
#ifdef ENOENT
if (errno == ENOENT)
ferrtx = "the specified file does not exist.";
#endif
#ifdef EACCES
if (errno == EACCES)
ferrtx = "read permission is denied for the specified file.";
#endif
shutdown(ferrno, ferrtx);
}
return(r_value);
}
int fl_create(fn)
char *fn;
{
int r_value;
#ifdef DG
if (dgcode)
r_value = dg_creat(fn, 0666, $FPRV);
else
r_value = dg_creat(fn, 0666, $FTXT);
if (r_value == -1)
#else
if ((r_value = creat(fn, 0666)) == -1)
#endif
{
ferrno = errno;
ferrtx = "open failed; file not creatable.";
#ifdef ENOTDIR
if (errno == ENOTDIR)
ferrtx = "a component of the path prefix is not a directory.";
#endif
#ifdef ENOENT
if (errno == ENOENT)
ferrtx = "a component of the path prefix does not exist.";
#endif
#ifdef EACCES
if (errno == EACCES)
ferrtx = "search/write permission denied for the specified file.";
#endif
#ifdef EISDIR
if (errno == EISDIR)
ferrtx = "specified file is a directory.";
#endif
#ifdef EROFS
if (errno == EROFS)
ferrtx = "file would reside on a read-only file system.";
#endif
shutdown(ferrno, ferrtx);
}
return(r_value);
}
int fl_close(fd)
int fd;
{
if (close(fd) == -1)
{
ferrno = errno;
ferrtx = "close failed.";
#ifdef EBADF
if (errno == EBADF)
ferrtx = "close: bad file handle.";
#endif
return(-1);
}
else
return(0);
}
int fl_read(fd, buf, blen)
int fd;
char *buf;
int blen;
{
int i, progress;
progress = 0;
for (i = 1; (i >= 1) && blen; buf += i, blen -= i, progress += i)
i = read(fd, buf, blen);
if (i == -1)
shutdown(errno, "read failed.");
return(progress);
}
VOID fl_write(fd, buf, blen)
int fd;
char *buf;
int blen;
{
int i;
if ((i = write(fd, buf, blen)) == -1)
{
ferrno = errno;
ferrtx = "write failed.";
#ifdef EFBIG
if (errno == EFBIG)
ferrtx = "file size exceeds maximum allowed.";
#endif
shutdown(ferrno, ferrtx);
}
if (i != blen)
shutdown(EINVAL, "write: out of room.");
}
#endif
#ifdef PART2
BOOL Binit(fname, create_it, rec_size, ibuckets)
char *fname;
BOOL create_it;
int rec_size, ibuckets;
{
int i;
if (file_size(fname) < BU_HDRSZ)
{
if (!create_it)
return(NO);
else
{
if (ibuckets == 0)
ibuckets = BU_DEFBUCK;
if (ibuckets > BU_MAXBUCK)
ibuckets = BU_MAXBUCK;
if (rec_size > BU_MAXRSZ)
rec_size = BU_MAXRSZ;
if (rec_size < BU_HDRSZ)
rec_size = BU_HDRSZ;
if (rec_size < BU_DIRSZ)
rec_size = BU_DIRSZ;
RF_create(fname, rec_size);
hdr.version[0] = '1';
hdr.version[1] = '.';
hdr.version[2] = '0';
hdr.version[3] = '0';
hdr.recsize = rec_size;
hdr.buckets = ibuckets;
hdr.hblocking = hdr.recsize >> 2;
hdr.hrec_count = hdr.buckets / hdr.hblocking;
if (hdr.buckets % hdr.hblocking)
++hdr.hrec_count;
hdr.free_first = 0L;
hdr.free_last = 0L;
hdr.file_last = hdr.hrec_count;
hdr.bu_date = 0;
hdr.bu_time = 0;
checkpoint(CKPT_INITIATE);
crit_initiate();
return(YES);
}
}
file_open(fname);
file_read(bu_rec, BU_HDRSZ);
hdr_read();
if (file_close() == -1)
shutdown(ferrno, ferrtx);
RF_open(fname, hdr.recsize);
if (hdr.c_status != CKPT_INITIATE)
for (i = 1; i <= hdr.hrec_count; ++i)
hash_read((LONG) i);
if (hdr.c_status != CKPT_OKAY)
{
info_restore();
switch (hdr.c_status)
{
case CKPT_INITIATE:
crit_initiate();
break;
case CKPT_DELETE:
crit_delete();
break;
case CKPT_INSTALL:
crit_install();
break;
default:
shutdown(-99, "Invalid ckeckpoint status");
}
}
return(YES);
}
VOID crit_initiate()
{
int i;
for (i = 0; i < hdr.buckets; ++i)
htab[i] = 0;
for (i = 1; i <= hdr.hrec_count; ++i)
hash_write((LONG) i);
checkpoint(CKPT_OKAY);
}
int Bterm()
{
hdr_write();
return(RF_close());
}
VOID Bcreate()
{
nfirst = 0L;
file_lrec = hdr.file_last;
bu_link = hdr.free_first;
bplink(0L);
}
VOID Bdelete(pathname)
BYTE *pathname;
{
if (!Blookup(pathname))
return;
checkpoint(CKPT_DELETE);
crit_delete();
}
VOID crit_delete()
{
Add_to_free(dir.dfirst, dir.dlast);
Set_prior(dir.syn_next);
Add_to_free(current, current);
checkpoint(CKPT_OKAY);
}
VOID Binstall(new_date, new_time, pathname, size, date, time, attr)
WORD new_date, new_time;
BYTE *pathname;
LONG size;
WORD date, time;
BYTE attr;
{
FAST BYTE *p, *q;
int i;
LONG first_drec = 0L, last_drec = 0L;
if (size > 0)
{
last_drec = bu_link;
data_write(YES);
if (hdr.free_first > 0L)
first_drec = hdr.free_first;
else
first_drec = hdr.file_last + 1;
if (nfirst > 0L)
last_drec = file_lrec;
}
hdr.free_first = bu_link;
dupname = Blookup(pathname);
odfirst = dir.dfirst;
odlast = dir.dlast;
dir.dfirst = first_drec;
dir.dlast = last_drec;
dir.fdate = new_date;
dir.ftime = new_time;
dir.fsize = size;
dir.dtime = time;
dir.ddate = date;
dir.dattr = attr;
p = dir.fname;
q = pathname;
for (i = 0; i < BU_FNSZ && *q; ++i)
*p++ = *q++;
for (; i < BU_FNSZ; ++i)
*p++ = NULL;
hdr.bu_date = new_date;
hdr.bu_time = new_time;
hdr.file_last = file_lrec;
if (!dupname)
{
if (hdr.free_first == 0L)
newdir = ++hdr.file_last;
else
{
newdir = hdr.free_first;
RF_read(bu_rec, hdr.free_first);
hdr.free_first = bglink();
}
}
checkpoint(CKPT_INSTALL);
crit_install();
}
VOID crit_install()
{
if (nfirst == 0L && dir.fsize > 0L
&& hdr.free_last != dir.dlast)
{
RF_read(bu_rec, dir.dlast);
bplink(0L);
RF_write(bu_rec, dir.dlast);
}
if (nfirst > 0L && hdr.free_last > 0L)
{
RF_read(bu_rec, hdr.free_last);
bplink(nfirst);
RF_write(bu_rec, hdr.free_last);
}
if (hdr.free_first == 0L)
hdr.free_last = 0L;
if (dupname)
Add_to_free(odfirst, odlast);
else
{
Set_prior(newdir);
dir.syn_next = current;
current = newdir;
}
dir_write(current);
checkpoint(CKPT_OKAY);
}
BOOL Bopenf(path, subdirs_ok)
char *path;
BOOL subdirs_ok;
{
if (Bcompile(path, subdirs_ok))
{
if (!Bposition((WORD) 0, YES))
return(NO);
while (!Bmatch(dir.fname)) {
if (!Badvance(YES))
return(NO);
}
return(YES);
}
else
return(Blookup(path));
}
BOOL Bopenn()
{
while (Badvance(YES))
{
if (Bmatch(dir.fname))
return(YES);
}
return(NO);
}
BYTE Bread()
{
return(bgchar());
}
VOID Bwrite(c)
{
bpchar(c);
}
BOOL Badvance(keep_going)
BOOL keep_going;
{
prior = current;
current = dir.syn_next;
if (current > 0L)
{
dir_read(current);
return(YES);
}
if (!keep_going)
return(NO);
return(Bposition((WORD) bucket+1, YES));
}
WORD Bhash(name)
char *name;
{
WORD hash_value;
int i;
hash_value = 0;
while (*name)
hash_value += *name++;
return(hash_value % hdr.buckets);
}
BOOL Blookup(name)
char *name;
{
int rval;
if (!Bposition(Bhash(name), NO))
return(NO);
while ((rval = strncmp(name, dir.fname, BU_FNSZ)) > 0)
{
if (!Badvance(NO))
return(NO);
}
return(rval == 0);
}
BOOL Bposition(hash_value, keep_going)
WORD hash_value;
BOOL keep_going;
{
prior = 0;
current = 0;
for (bucket = hash_value; bucket < hdr.buckets; ++bucket)
{
current = htab[bucket];
if (current > 0L)
{
dir_read(current);
return(YES);
}
if (!keep_going)
return(NO);
}
return(NO);
}
VOID Add_to_free(first, last)
LONG first, last;
{
if (first == 0L)
return;
if (hdr.free_first == 0L && first != last)
{
hdr.free_first = first;
hdr.free_last = last;
}
else
{
bplink(hdr.free_first);
RF_write(bu_rec, last);
hdr.free_first = first;
if (hdr.free_last == 0L)
hdr.free_last = last;
}
}
VOID data_write(eof_flag)
BOOL eof_flag;
{
int i;
bpfill();
if (bu_link == 0L)
{
++file_lrec;
if (eof_flag)
bplink(0L);
else
bplink(file_lrec + 1L);
RF_write(bu_rec, file_lrec);
if (nfirst == 0L)
nfirst = file_lrec;
}
else
{
RF_read(bu_rec2, bu_link);
for (i = 0; i < 4; ++i)
bu_rec[i] = bu_rec2[i];
RF_write(bu_rec, bu_link);
bu_link = bglink();
}
bplink(0L);
}
VOID Set_prior(link_value)
LONG link_value;
{
if (prior == 0L)
{
htab[bucket] = link_value;
hash_write( (LONG) ((bucket / hdr.hblocking) + 1));
}
else
{
RF_read(bu_rec, prior);
bplink(link_value);
RF_write(bu_rec, prior);
}
}
static add_chr(c)
BYTE c;
{
if (autoix >= autotab + AUTOSIZE)
shutdown(-35, "Internal error.");
*autoix++ = c;
}
BOOL Bcompile(pname, subs_ok)
FAST BYTE *pname;
BOOL subs_ok;
{
FAST BYTE *p, *q, *r;
int i;
BOOL wild = NO;
BYTE buf[PATHSIZE+2];
if ((i = strlen(pname)) > PATHSIZE || i < 1)
shutdown(-46, "Internal error.");
if (subs_ok)
{
for (p = q = pname; *p; ++p)
if (*p == SD_CHAR)
q = p + 1;
for (p = buf; pname < q;)
*p++ = *pname++;
*p++ = SUBDIR;
while (*p++ = *pname++)
;
pname = buf;
}
for (autoix = autotab; *pname; ++pname)
switch (*pname)
{
case '*':
for (i = 0; i < 8; ++i)
add_chr(FANY);
while (*pname != '.' && *pname != SD_CHAR && *pname)
++pname;
--pname;
wild = YES;
break;
case '?':
add_chr(FANY);
wild = YES;
break;
case SUBDIR:
add_chr(FSUBDIR);
wild = YES;
break;
case '.':
add_chr(FDOT);
break;
default:
add_chr(FCHAR);
add_chr(*pname);
}
if (wild)
{
add_chr(FCHAR);
add_chr(NULL);
add_chr(FSUCCEED);
return(YES);
}
else
{
autoix = autotab;
add_chr(FFAIL);
return(NO);
}
}
BOOL Bmatch(s)
FAST BYTE *s;
{
FAST BYTE *p, *q;
for (p = autotab; ;)
switch (*p++)
{
case FCHAR:
if (*p++ != *s++)
return(NO);
break;
case FDOT:
if (*s == '.')
++s;
else if (*s)
return(NO);
break;
case FSUBDIR:
for (q = s; *q; ++q)
if (*q == SD_CHAR)
s = q + 1;
break;
case FANY:
if (*s == SD_CHAR)
return(NO);
if (*s && *s != '.')
++s;
break;
case FSUCCEED:
return(YES);
default:
return(NO);
}
}
BYTE bgchar()
{
if ((bu_ptr - bu_rec) >= hdr.recsize)
{
RF_read(bu_rec, bu_link);
bu_link = bglink();
}
return(*bu_ptr++);
}
VOID bgstr(s, c)
BYTE *s;
int c;
{
while (c--)
*s++ = bgchar();
}
WORD bgword()
{
BYTE c;
c = bgchar();
return( (c<<8) + (bgchar() & 0xff));
}
LONG bglong()
{
WORD w;
w = bgword();
return( (((LONG) w) << 16) + (bgword() & 0xffff));
}
LONG bglink()
{
bu_ptr = bu_rec;
return(bglong());
}
VOID bpchar(c)
BYTE c;
{
if ((bu_ptr - bu_rec) >= hdr.recsize)
data_write(NO);
*bu_ptr++ = c;
}
VOID bpstr(s, c)
BYTE *s;
int c;
{
while (c--)
bpchar(*s++);
}
VOID bpword(w)
WORD w;
{
bpchar( (BYTE) (w>>8));
bpchar( (BYTE) w);
}
VOID bplong(l)
LONG l;
{
bpword( (WORD) (l>>16));
bpword( (WORD) l);
}
VOID bplink(l)
LONG l;
{
bu_ptr = bu_rec;
bplong(l);
}
VOID bpfill()
{
while ((bu_ptr - bu_rec) < hdr.recsize)
bpchar(NULL);
}
VOID hdr_read()
{
bu_ptr = bu_rec;
hdr.recsize = BU_HDRSZ;
bgstr(hdr.version, BU_VERSZ);
hdr.recsize = bgword();
hdr.buckets = bgword();
hdr.hrec_count = bgchar();
hdr.hblocking = bgword();
hdr.free_first = bglong();
hdr.free_last = bglong();
hdr.file_last = bglong();
hdr.bu_date = bgword();
hdr.bu_time = bgword();
hdr.c_status = bgchar();
hdr.c_dupname = bgchar();
hdr.c_prior = bglong();
hdr.c_current = bglong();
hdr.c_bucket = bglong();
hdr.c_nfirst = bglong();
hdr.c_newdir = bglong();
hdr.c_odfirst = bglong();
hdr.c_odlast = bglong();
hdr.c_dir.syn_next = bglong();
hdr.c_dir.dfirst = bglong();
hdr.c_dir.dlast = bglong();
hdr.c_dir.fdate = bgword();
hdr.c_dir.ftime = bgword();
hdr.c_dir.fsize = bglong();
hdr.c_dir.ddate = bgword();
hdr.c_dir.dtime = bgword();
hdr.c_dir.dattr = bgchar();
bgstr(hdr.c_dir.fname, BU_FNSZ);
}
VOID hdr_write()
{
bu_ptr = bu_rec;
bpstr(hdr.version, BU_VERSZ);
bpword(hdr.recsize);
bpword(hdr.buckets);
bpchar(hdr.hrec_count);
bpword(hdr.hblocking);
bplong(hdr.free_first);
bplong(hdr.free_last);
bplong(hdr.file_last);
bpword(hdr.bu_date);
bpword(hdr.bu_time);
bpchar(hdr.c_status);
bpchar(hdr.c_dupname);
bplong(hdr.c_prior);
bplong(hdr.c_current);
bplong(hdr.c_bucket);
bplong(hdr.c_nfirst);
bplong(hdr.c_newdir);
bplong(hdr.c_odfirst);
bplong(hdr.c_odlast);
bplong(hdr.c_dir.syn_next);
bplong(hdr.c_dir.dfirst);
bplong(hdr.c_dir.dlast);
bpword(hdr.c_dir.fdate);
bpword(hdr.c_dir.ftime);
bplong(hdr.c_dir.fsize);
bpword(hdr.c_dir.ddate);
bpword(hdr.c_dir.dtime);
bpchar(hdr.c_dir.dattr);
bpstr(hdr.c_dir.fname, BU_FNSZ);
bpfill();
RF_write(bu_rec, 0L);
}
VOID checkpoint(st)
BYTE st;
{
FAST BYTE *p, *q;
FAST int i;
hdr.c_status = st;
hdr.c_dupname = dupname;
hdr.c_prior = prior;
hdr.c_current = current;
hdr.c_bucket = bucket;
hdr.c_nfirst = nfirst;
hdr.c_newdir = newdir;
hdr.c_odfirst = odfirst;
hdr.c_odlast = odlast;
hdr.c_dir.syn_next = dir.syn_next;
hdr.c_dir.dfirst = dir.dfirst;
hdr.c_dir.dlast = dir.dlast;
hdr.c_dir.fdate = dir.fdate;
hdr.c_dir.ftime = dir.ftime;
hdr.c_dir.fsize = dir.fsize;
hdr.c_dir.ddate = dir.ddate;
hdr.c_dir.dtime = dir.dtime;
hdr.c_dir.dattr = dir.dattr;
p = hdr.c_dir.fname;
q = dir.fname;
for (i = 0; i < BU_FNSZ; ++i)
*p++ = *q++;
hdr_write();
}
VOID info_restore()
{
FAST BYTE *p, *q;
FAST int i;
dupname = hdr.c_dupname;
prior = hdr.c_prior;
current = hdr.c_current;
bucket = hdr.c_bucket;
nfirst = hdr.c_nfirst;
newdir = hdr.c_newdir;
odfirst = hdr.c_odfirst;
odlast = hdr.c_odlast;
dir.syn_next = hdr.c_dir.syn_next;
dir.dfirst = hdr.c_dir.dfirst;
dir.dlast = hdr.c_dir.dlast;
dir.fdate = hdr.c_dir.fdate;
dir.ftime = hdr.c_dir.ftime;
dir.fsize = hdr.c_dir.fsize;
dir.ddate = hdr.c_dir.ddate;
dir.dtime = hdr.c_dir.dtime;
dir.dattr = hdr.c_dir.dattr;
p = dir.fname;
q = hdr.c_dir.fname;
for (i = 0; i < BU_FNSZ; ++i)
*p++ = *q++;
}
VOID hash_read(r)
LONG r;
{
FAST int offset, i;
RF_read(bu_rec, r);
offset = (r-1) * hdr.hblocking;
bu_ptr = bu_rec;
for (i = 0; i < hdr.hblocking; ++i)
if (offset < hdr.buckets)
htab[offset++] = bglong();
}
VOID hash_write(r)
LONG r;
{
FAST int offset, i;
offset = (r-1) * hdr.hblocking;
bu_ptr = bu_rec;
for (i = 0; i < hdr.hblocking; ++i)
if (offset < hdr.buckets)
bplong(htab[offset++]);
bpfill();
RF_write(bu_rec, r);
}
VOID dir_read(r)
LONG r;
{
RF_read(bu_rec, r);
dir.syn_next = bglink();
dir.dfirst = bglong();
dir.dlast = bglong();
dir.fdate = bgword();
dir.ftime = bgword();
dir.fsize = bglong();
dir.ddate = bgword();
dir.dtime = bgword();
dir.dattr = bgchar();
bgstr(dir.fname, BU_FNSZ);
bu_ptr = bu_rec + hdr.recsize + 1;
bu_link = dir.dfirst;
}
VOID dir_write(r)
LONG r;
{
bplink(dir.syn_next);
bplong(dir.dfirst);
bplong(dir.dlast);
bpword(dir.fdate);
bpword(dir.ftime);
bplong(dir.fsize);
bpword(dir.ddate);
bpword(dir.dtime);
bpchar(dir.dattr);
bpstr(dir.fname, BU_FNSZ);
bpfill();
RF_write(bu_rec, r);
}
#endif PART2
