home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
rzsz_3_24_3_src.lzh
/
rz.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-25
|
32KB
|
1,541 lines
#define VERSION "3.24 5-5-93"
#ifdef OS9
#define PUBDIR "/dd/SPOOL/UUCPPUBLIC"
#else /* !OS9 */
#define PUBDIR "/usr/spool/uucppublic"
#endif
/*
*
* rz.c By Chuck Forsberg
* Copyright 1993 Omen Technology Inc All Rights Reserved
*
* A program for Unix to receive files and commands from computers running
* Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
* rz uses Unix buffered input to reduce wasted CPU time.
*
*
* This version implements numerous enhancements including ZMODEM
* Run Length Encoding and variable length headers. These
* features were not funded by the original Telenet development
* contract.
*
* This software may be freely used for educational (didactic
* only) purposes. This software may also be freely used to
* support file transfer operations to or from licensed Omen
* Technology products. Use with other commercial or shareware
* programs (Crosstalk, Procomm, etc.) REQUIRES REGISTRATION.
*
* Any programs which use part or all of this software must be
* provided in source form with this notice intact except by
* written permission from Omen Technology Incorporated.
*
*
* Use of this software for commercial or administrative purposes
* except when exclusively limited to interfacing Omen Technology
* products requires a per port license payment of $20.00 US per
* port (less in quantity, see mailer.rz). Use of this code by
* inclusion, decompilation, reverse engineering or any other means
* constitutes agreement to these conditions and acceptance of
* liability to license the materials and payment of reasonable
* legal costs necessary to enforce this license agreement.
*
*
* Omen Technology Inc
* Post Office Box 4681
* Portland OR 97208
*
* This code is made available in the hope it will be useful,
* BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
* DAMAGES OF ANY KIND.
*
*
*
* Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
*
* SEGMENTS=n added 2-21-88 as a model for CP/M programs
* for CP/M-80 systems that cannot overlap modem and disk I/O.
*
* -DMD may be added to compiler command line to compile in
* Directory-creating routines from Public Domain TAR by John Gilmore
*
* HOWMANY may be tuned for best performance
*
* USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
*/
char *Copyrrz = "Copyright 1993 Omen Technology Inc All Rights Reserved";
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
extern int errno;
#ifdef OS9
#include <direct.h>
#include <modes.h>
#include <sgstat.h>
#include "os9.h"
#define LOGFILE "/dd/TMP/rzlog"
char logfile[128];
struct sgbuf stty;
struct sgbuf sttyold;
int u2oattr();
int getuid();
#ifndef m6809
long outime();
long c4tol();
#endif /* !m6809 */
#else /* !OS9 */
#define LOGFILE "/tmp/rzlog"
#endif /* !OS9 */
#define LOGFILE2 "rzlog"
#ifndef OS9
#define OK 0
#define FALSE 0
#define TRUE 1
#define ERROR (-1)
/*
* Max value for HOWMANY is 255.
* A larger value reduces system overhead but may evoke kernel bugs.
*/
#ifndef HOWMANY
#define HOWMANY 96
#endif
/* Ward Christensen / CP/M parameters - Don't change these! */
#define ENQ 005
#define CAN ('X'&037)
#define XOFF ('s'&037)
#define XON ('q'&037)
#define SOH 1
#define STX 2
#define EOT 4
#define ACK 6
#define NAK 025
#define CPMEOF 032
#define WANTCRC 0103 /* send C not NAK to get crc not checksum */
#define TIMEOUT (-2)
#define RCDO (-3)
#define GCOUNT (-4)
#define ERRORMAX 5
#define RETRYMAX 5
#define WCEOT (-10)
#define PATHLEN 257 /* ready for 4.2 bsd ? */
#define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */
#endif /* !OS9 */
int Zmodem=0; /* ZMODEM protocol requested */
int Nozmodem = 0; /* If invoked as "rb" */
unsigned Baudrate = 9600;
unsigned Effbaud = 9600;
#ifdef OS9
extern int Lleft;
extern int Readnum;
extern FILE *Ttystream;
extern int Verbose;
#ifdef m6809
unsigned updcrc();
#else /* !m6809 */
unsigned long updcrc();
#endif /* !m6809 */
#else /* !OS9 */
#include "rbsb.c" /* most of the system dependent stuff here */
#include "crctab.c"
#endif /* !OS9 */
char endmsg[90] = {0}; /* Possible message to display on exit */
char *substr();
FILE *fout;
/*
* Routine to calculate the free bytes on the current file system
* ~0 means many free bytes (unknown)
*/
#ifdef m6809
long getfree()
#else
unsigned long getfree()
#endif
{
return(~0L); /* many free bytes ... */
}
int Lastrx;
#ifdef m6809
long rxbytes;
#else
unsigned long rxbytes;
#endif
int Crcflg;
int Firstsec;
int Eofseen; /* indicates cpm eof (^Z) has been received */
int errors;
int Restricted=0; /* restricted; no /.. or ../ in filenames */
#ifndef OS9
#define DEFBYTL 2000000000L /* default rx file size */
#endif
#ifdef m6809
long Bytesleft; /* number of bytes of incoming file left */
#else
unsigned long Bytesleft; /* number of bytes of incoming file left */
#endif
long Modtime; /* Unix style mod time for incoming file */
int Filemode; /* Unix style mode for incoming file */
#ifdef m6809
long Totalleft;
long Filesleft;
#else
unsigned long Totalleft;
unsigned long Filesleft;
#endif
char Pathname[PATHLEN];
char *Progname; /* the name by which we were called */
int Batch=0;
int Thisbinary; /* current file is to be received in bin mode */
int Rxbinary=FALSE; /* receive all files in bin mode */
int Rxascii=FALSE; /* receive files in ascii (translate) mode */
int Blklen; /* record length of received packets */
#ifdef SEGMENTS
int chinseg = 0; /* Number of characters received in this data seg */
char secbuf[1+(SEGMENTS+1)*1024];
#else
char secbuf[1025];
#endif
#ifdef OS9
long timep[2];
#else
time_t timep[2];
#endif /* OS9 */
char Lzmanag; /* Local file management request */
char Lzconv; /* Local ZMODEM file conversion request */
char zconv; /* ZMODEM file conversion request */
char zmanag; /* ZMODEM file management request */
char ztrans; /* ZMODEM file transport request */
int Zctlesc; /* Encode control characters */
int Zrwindow = 1400; /* RX window size (controls garbage count) */
#ifdef OS9
#include "zmodem.h"
extern int Crc32r;
extern char Rxhdr[];
extern char Txhdr[];
extern Usevhdrs;
int zgethdr();
int zrdata();
#else /* !OS9 */
#include "zm.c"
#include "zmr.c"
#endif
int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */
/* called by signal interrupt or terminate to clean things up */
void
bibi(n)
{
if (Zmodem)
zmputs(Attn);
canit(); mode(0);
fprintf(stderr, "rz: caught signal %d; exiting", n);
#ifdef OS9
if(Verbose < 3)
_ss_opt(fileno(stderr), &sttyold);
#endif
exit(3);
}
main(argc, argv)
char *argv[];
{
register char *cp;
register npats;
char *virgin, **patts;
char *getenv();
int exitcode = 0;
#ifdef OS9
#ifdef m6809
pflinit();
#endif /* m6809 */
_gs_opt(fileno(stderr), &sttyold);
#ifdef m6809
_strass(&stty, &sttyold, sizeof(struct sgbuf));
#else
stty = sttyold;
#endif
stty.sg_pause = 0;
_ss_opt(fileno(stderr), &stty);
#endif
Rxtimeout = 100;
setbuf(stderr, NULL);
#ifdef OS9
#ifdef m6809
Restricted=TRUE;
#else
if ((cp=getenv("SHELL")) && (substr(cp, "shell") == 0))
Restricted=TRUE;
#endif
#else
if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
Restricted=TRUE;
#endif
chkinvok(virgin=argv[0]); /* if called as [-]rzCOMMAND set flag */
inittty();
npats = 0;
while (--argc) {
cp = *++argv;
if (*cp == '-') {
while( *++cp) {
switch(*cp) {
case '\\':
cp[1] = toupper(cp[1]); continue;
case 'a':
if (!Batch || Nozmodem)
Rxascii=TRUE;
else
usage();
break;
case 't':
if (--argc < 1) {
usage();
}
Rxtimeout = atoi(*++argv);
if (Rxtimeout<10 || Rxtimeout>1000)
usage();
break;
case 'w':
if (--argc < 1) {
usage();
}
Zrwindow = atoi(*++argv);
break;
case 'v':
++Verbose; break;
default:
usage();
}
}
}
else if ( !npats && argc>0) {
if (argv[0][0]) {
npats=argc;
patts=argv;
}
}
}
if (npats > 1)
usage();
if (Batch && npats)
usage();
#ifdef OS9
if (Verbose > 2) {
sprintf(logfile, "%s.%d", LOGFILE, getuid());
if (freopen(logfile, "a", stderr)==NULL)
if (freopen(LOGFILE2, "a", stderr)==NULL) {
printf("Can't open log file!");
_ss_opt(fileno(stderr), &sttyold);
exit(2);
}
setbuf(stderr, NULL);
fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
}
#else
if (Verbose) {
if (freopen(LOGFILE, "a", stderr)==NULL)
if (freopen(LOGFILE2, "a", stderr)==NULL) {
printf("Can't open log file!");
exit(2);
}
setbuf(stderr, NULL);
fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
}
#endif
vfile("%s %s for %s\n", Progname, VERSION, OS);
mode(1);
if (signal(SIGINT, bibi) == SIG_IGN) {
signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
#ifdef OS9
signal(SIGQUIT, SIG_IGN);
#endif
}
else {
signal(SIGINT, bibi); signal(SIGKILL, bibi);
#ifdef OS9
signal(SIGQUIT, bibi);
#endif
}
signal(SIGTERM, bibi);
if (wcreceive(npats, patts)==ERROR) {
exitcode=1;
canit();
}
mode(0);
if (exitcode && !Zmodem) /* bellow again with all thy might. */
canit();
if (endmsg[0])
fprintf(stderr, " %s: %s\n", Progname, endmsg);
fprintf(stderr, "\n%s %s finished.\n", Progname, VERSION);
#ifdef OS9
if (Verbose < 3)
_ss_opt(fileno(stderr), &sttyold);
#endif
fflush(stderr);
if(exitcode)
exit(1);
#ifndef REGISTERED
/* Removing or disabling this code without registering is theft */
if (!Usevhdrs) {
fprintf(stderr, "\n\n\nPlease read the License Agreement in rz.doc\n");
fflush(stderr);
sleep(2);
}
#endif
exit(0);
}
usage()
{
fprintf(stderr,
"Receive Files and Commands with ZMODEM/YMODEM/XMODEM Protocol\n\n");
fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
Progname, VERSION, OS);
#ifdef m6809
fprintf(stderr, " \042The High Reliability Software\042\n\n");
#else
fprintf(stderr, "\t\t\042The High Reliability Software\042\n\n");
#endif
fprintf(stderr,"Usage: rz [-v] (ZMODEM)\n");
fprintf(stderr,"or rb [-av] (YMODEM)\n");
fprintf(stderr,"or rc [-av] file (XMODEM-CRC)\n");
fprintf(stderr,"or rx [-av] file (XMODEM)\n\n");
fprintf(stderr,
"Supports incoming ZMODEM binary (-b), ASCII CR/LF>NL (-a), newer(-n),\n");
fprintf(stderr,
"newer+longer(-N), protect (-p), Crash Recovery (-r),\n");
fprintf(stderr,
"clobber (-y), match+clobber (-Y), compression (-Z), and append (-+).\n\n");
fprintf(stderr,"Copyright 1993 Omen Technology INC All Rights Reserved\n");
fprintf(stderr,
"See rz.doc for option descriptions and licensing information.\n\n");
exit(2);
}
/*
* Let's receive something already.
*/
char *rbmsg = "%s ready. Type \"%s file ...\" to your modem program\n\r";
wcreceive(argc, argp)
char **argp;
{
register c;
if (Batch || argc==0) {
Crcflg=1;
fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
if (c=tryz()) {
if (c == ZCOMPL)
return OK;
if (c == ERROR)
goto fubar;
c = rzfiles();
if (c)
goto fubar;
} else {
for (;;) {
if (wcrxpn(secbuf)== ERROR)
goto fubar;
if (secbuf[0]==0)
return OK;
if (procheader(secbuf) == ERROR)
goto fubar;
if (wcrx()==ERROR)
goto fubar;
}
}
} else {
Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
if ((fout=fopen(Pathname, "w")) == NULL)
return ERROR;
if (wcrx()==ERROR)
goto fubar;
}
return OK;
fubar:
canit();
Modtime = 1;
if (fout)
#ifdef OS9
{
fflush(fout);
fclose(fout);
}
#else
fclose(fout);
#endif
if (Restricted) {
unlink(Pathname);
fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
}
return ERROR;
}
/*
* Fetch a pathname from the other end as a C ctyle ASCIZ string.
* Length is indeterminate as long as less than Blklen
* A null string represents no more files (YMODEM)
*/
wcrxpn(rpn)
char *rpn; /* receive a pathname */
{
register c;
purgeline();
et_tu:
Firstsec=TRUE; Eofseen=FALSE;
sendline(Crcflg?WANTCRC:NAK); flushmo();
Lleft=0; /* Do read next time ... */
while ((c = wcgetsec(rpn, 100)) != 0) {
if (c == WCEOT) {
zperr( "Pathname fetch returned %d", c);
sendline(ACK); flushmo();
Lleft=0; /* Do read next time ... */
readline(1);
goto et_tu;
}
return ERROR;
}
sendline(ACK); flushmo();
return OK;
}
/*
* Adapted from CMODEM13.C, written by
* Jack M. Wierda and Roderick W. Hart
*/
wcrx()
{
register int sectnum, sectcurr;
register char sendchar;
register char *p;
int cblklen; /* bytes to dump this block */
Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
sendchar=Crcflg?WANTCRC:NAK;
for (;;) {
sendline(sendchar); /* send it now, we're ready! */
flushmo();
Lleft=0; /* Do read next time ... */
sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
if (sectcurr==(sectnum+1 &0377)) {
sectnum++;
cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
if (putsec(secbuf, cblklen)==ERROR)
return ERROR;
if (((int)(Bytesleft-=cblklen)) < 0)
Bytesleft = 0;
sendchar=ACK;
}
else if (sectcurr==(sectnum&0377)) {
zperr( "Received dup Sector");
sendchar=ACK;
}
else if (sectcurr==WCEOT) {
if (closeit())
return ERROR;
sendline(ACK); flushmo();
Lleft=0; /* Do read next time ... */
return OK;
}
else if (sectcurr==ERROR)
return ERROR;
else {
zperr( "Sync Error");
return ERROR;
}
}
}
/*
* Wcgetsec fetches a Ward Christensen type sector.
* Returns sector number encountered or ERROR if valid sector not received,
* or CAN CAN received
* or WCEOT if eot sector
* time is timeout for first char, set to 4 seconds thereafter
***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
* (Caller must do that when he is good and ready to get next sector)
*/
wcgetsec(rxbuf, maxtime)
char *rxbuf;
int maxtime;
{
register checksum, wcj, firstch;
#ifdef m6809
register unsigned oldcrc;
#else
register unsigned short oldcrc;
#endif
register char *p;
int sectcurr;
for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
if ((firstch=readline(maxtime))==STX) {
Blklen=1024; goto get2;
}
if (firstch==SOH) {
Blklen=128;
get2:
sectcurr=readline(1);
if ((sectcurr+(oldcrc=readline(1)))==0377) {
oldcrc=checksum=0;
for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
if ((firstch=readline(1)) < 0)
goto bilge;
oldcrc=updcrc(firstch, oldcrc);
checksum += (*p++ = firstch);
}
if ((firstch=readline(1)) < 0)
goto bilge;
if (Crcflg) {
oldcrc=updcrc(firstch, oldcrc);
if ((firstch=readline(1)) < 0)
goto bilge;
oldcrc=updcrc(firstch, oldcrc);
if (oldcrc & 0xFFFF)
zperr( "CRC");
else {
Firstsec=FALSE;
return sectcurr;
}
}
else if (((checksum-firstch)&0377)==0) {
Firstsec=FALSE;
return sectcurr;
}
else
zperr( "Checksum");
}
else
zperr("Sector number garbled");
}
/* make sure eot really is eot and not just mixmash */
else if (firstch==EOT && Lleft==0)
return WCEOT;
else if (firstch==CAN) {
if (Lastrx==CAN) {
zperr( "Sender CANcelled");
return ERROR;
} else {
Lastrx=CAN;
continue;
}
}
else if (firstch==TIMEOUT) {
if (Firstsec)
goto humbug;
bilge:
zperr( "TIMEOUT");
}
else
zperr( "Got 0%o sector header", firstch);
humbug:
Lastrx=0;
while(readline(1)!=TIMEOUT)
;
if (Firstsec) {
sendline(Crcflg?WANTCRC:NAK); flushmo();
Lleft=0; /* Do read next time ... */
} else {
maxtime=40; sendline(NAK); flushmo();
Lleft=0; /* Do read next time ... */
}
}
/* try to stop the bubble machine. */
canit();
return ERROR;
}
/*
* Process incoming file information header
*/
procheader(name)
char *name;
{
register char *openmode, *p, **pp;
static dummy;
#ifdef OS9
int pn;
struct fildes f;
#else
struct stat f;
#endif
/* set default parameters and overrides */
openmode = "w";
Thisbinary = (!Rxascii) || Rxbinary;
if (zconv == ZCBIN && Lzconv != ZCRESUM)
Lzconv = zconv; /* Remote Binary override */
if (Lzconv)
zconv = Lzconv;
if (Lzmanag)
zmanag = Lzmanag;
/*
* Process ZMODEM remote file management requests
*/
if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
Thisbinary = 0;
if (zconv == ZCBIN) /* Remote Binary override */
Thisbinary = TRUE;
else if (zmanag == ZMAPND)
openmode = "a";
Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
if (!name || !*name)
return OK;
p = name + 1 + strlen(name);
if (*p) { /* file coming from Unix or DOS system */
sscanf(p, "%ld%lo%lo%o%ld%ld%d%d",
&Bytesleft, &Modtime, &Filemode,
&dummy, &Filesleft, &Totalleft, &dummy, &dummy);
#ifdef OS9
if (!(Filemode & UNIXFILE))
#else
if (Filemode & UNIXFILE)
#endif
++Thisbinary;
if (Verbose) {
fprintf(stderr, "\nIncoming: %s %ld %lo %o\n",
name, Bytesleft, Modtime, Filemode);
fprintf(stderr, "YMODEM header: %s\n", p);
}
}
else { /* File coming from CP/M system */
for (p=name; *p; ++p) /* change / to _ */
if ( *p == '/')
*p = '_';
if ( *--p == '.') /* zap trailing period */
*p = 0;
}
strcpy(Pathname, name);
checkpath(name);
#ifdef OS9
openit(name, "r");
if (*name && _gs_gfd(fileno(fout), &f, sizeof(struct fildes)) != -1) {
closeit();
#else
if (*name && stat(name, &f)!= -1) {
#endif
zmanag &= ZMMASK;
#ifdef OS9
#ifdef m6809
vfile("Current %s is %ld %lo", name, f.fd_fsize, outime(f.fd_date));
#else
vfile("Current %s is %ld %lo", name, c4tol(f.fd_fsize), outime(f.fd_date));
#endif
#else
vfile("Current %s is %ld %lo", name, f.st_size, f.st_mtime);
#endif
if (Thisbinary && zconv==ZCRESUM) {
#ifdef OS9
#ifdef m6809
rxbytes = f.fd_fsize & ~511;
#else
rxbytes = c4tol(f.fd_fsize) & ~511;
#endif
#else
rxbytes = f.st_size & ~511;
#endif
if (Bytesleft < rxbytes) {
rxbytes = 0; goto doopen;
} else
openit(name, "r+");
if ( !fout)
return ZFERR;
if (fseek(fout, rxbytes, 0)) {
closeit();
return ZFERR;
}
vfile("Crash recovery at %ld", rxbytes);
return 0;
}
#ifdef OS9
#ifdef m6809
else if ((zmanag==ZMNEW) ||
((zmanag==ZMNEWL) && Bytesleft <= f.fd_fsize) ) {
if ((outime(f.fd_date)+60) >= Modtime)
#else
else if ((zmanag==ZMNEW) ||
((zmanag==ZMNEWL) && Bytesleft <= c4tol(f.fd_fsize)) ) {
if ((outime(f.fd_date)+60) >= Modtime)
#endif
#else
else if ((zmanag==ZMNEW) ||
((zmanag==ZMNEWL) && Bytesleft <= f.st_size) ) {
if ((f.st_mtime+1) >= Modtime)
#endif
goto skipfile;
goto doopen;
}
switch (zmanag & ZMMASK) {
case ZMCLOB:
case ZMAPND:
goto doopen;
default:
goto skipfile;
}
} else if (zmanag & ZMSKNOLOC) {
skipfile:
vfile("Skipping %s", name);
return ZSKIP;
}
doopen:
openit(name, openmode);
#ifdef MD
if ( !fout)
if (make_dirs(name))
openit(name, openmode);
#endif
if ( !fout)
return ZFERR;
return 0;
}
openit(name, openmode)
char *name, *openmode;
{
fout = fopen(name, openmode);
}
#ifdef MD
/*
* Directory-creating routines from Public Domain TAR by John Gilmore
*/
/*
* After a file/link/symlink/dir creation has failed, see if
* it's because some required directory was not present, and if
* so, create all required dirs.
*/
make_dirs(pathname)
register char *pathname;
{
register char *p; /* Points into path */
int madeone = 0; /* Did we do anything yet? */
int save_errno = errno; /* Remember caller's errno */
char *strchr();
#ifdef OS9
if (errno != E_PNNF)
#else
if (errno != ENOENT)
#endif
return 0; /* Not our problem */
for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
/* Avoid mkdir of empty string, if leading or double '/' */
if (p == pathname || p[-1] == '/')
continue;
/* Avoid mkdir where last part of path is '.' */
if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
continue;
*p = 0; /* Truncate the path there */
#ifdef OS9
if ( !mknod(pathname, S_IREAD | S_IWRITE | S_IEXEC |
S_IOREAD | S_IOWRITE | S_IOEXEC)) { /* Try to create it as a dir */
#else
if ( !mkdir(pathname, 0777)) { /* Try to create it as a dir */
#endif
vfile("Made directory %s\n", pathname);
madeone++; /* Remember if we made one */
*p = '/';
continue;
}
*p = '/';
#ifdef OS9
if (errno == E_CEF) /* Directory already exists */
#else
if (errno == EEXIST) /* Directory already exists */
#endif
continue;
/*
* Some other error in the mkdir. We return to the caller.
*/
break;
}
errno = save_errno; /* Restore caller's errno */
return madeone; /* Tell them to retry if we made one */
}
#ifndef MD2 /* #if (MD != 2) */
#define TERM_SIGNAL(status) ((status) & 0x7F)
#define TERM_COREDUMP(status) (((status) & 0x80) != 0)
#define TERM_VALUE(status) ((status) >> 8)
/*
* Make a directory. Compatible with the mkdir() system call on 4.2BSD.
*/
mkdir(dpath, dmode)
char *dpath;
int dmode;
{
int cpid, status;
struct stat statbuf;
if (stat(dpath,&statbuf) == 0) {
errno = EEXIST; /* Stat worked, so it already exists */
return -1;
}
/* If stat fails for a reason other than non-existence, return error */
if (errno != ENOENT) return -1;
switch (cpid = fork()) {
case -1: /* Error in fork() */
return(-1); /* Errno is set already */
case 0: /* Child process */
/*
* Cheap hack to set mode of new directory. Since this
* child process is going away anyway, we zap its umask.
* FIXME, this won't suffice to set SUID, SGID, etc. on this
* directory. Does anybody care?
*/
status = umask(0); /* Get current umask */
status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
execl("/bin/mkdir", "mkdir", dpath, (char *)0);
_exit(2); /* Can't exec /bin/mkdir */
default: /* Parent process */
while (cpid != wait(&status)) ; /* Wait for kid to finish */
}
if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
errno = EIO; /* We don't know why, but */
return -1; /* /bin/mkdir failed */
}
return 0;
}
#endif /* MD != 2 */
#endif /* MD */
/*
* Putsec writes the n characters of buf to receive file fout.
* If not in binary mode, carriage returns, and all characters
* starting with CPMEOF are discarded.
*/
putsec(buf, n)
char *buf;
register n;
{
register char *p;
if (n == 0)
return OK;
if (Thisbinary) {
for (p=buf; --n>=0; )
putc( *p++, fout);
}
else {
if (Eofseen)
return OK;
for (p=buf; --n>=0; ++p ) {
#ifdef OS9
if ( *p == '\l')
#else
if ( *p == '\r')
#endif
continue;
if (*p == CPMEOF) {
Eofseen=TRUE; return OK;
}
putc(*p ,fout);
}
}
return OK;
}
/*
* substr(string, token) searches for token in string s
* returns pointer to token within string if found, NULL otherwise
*/
char *
substr(s, t)
register char *s,*t;
{
register char *ss,*tt;
/* search for first char of token */
for (ss=s; *s; s++)
if (*s == *t)
/* compare token with substring */
for (ss=s,tt=t; ;) {
if (*tt == 0)
return s;
if (*ss++ != *tt++)
break;
}
return NULL;
}
/*
* If called as [-][dir/../]vrzCOMMAND set Verbose to 1
* If called as rb use YMODEM protocol
*/
chkinvok(s)
char *s;
{
register char *p;
p = s;
while (*p == '-')
s = ++p;
while (*p)
if (*p++ == '/')
s = p;
if (*s == 'v') {
Verbose=1; ++s;
}
Progname = s;
if (s[0]=='r' && s[1]=='z')
Batch = TRUE;
if (s[0]=='r' && s[1]=='c')
Crcflg = TRUE;
if (s[0]=='r' && s[1]=='b')
Batch = Nozmodem = TRUE;
}
/*
* Totalitarian Communist pathname processing
*/
checkpath(name)
char *name;
{
#ifdef OS9
char *p;
for (p = name; *p; ++p)
{
if (isalnum(*p))
continue;
switch(*p)
{
case '.':
case '/':
#ifndef m6809
case '$':
#endif
continue;
default:
*p = '_';
}
}
#endif
if (Restricted) {
if (fopen(name, "r") != NULL) {
canit();
fprintf(stderr, "\r\nrz: %s exists\n", name);
bibi(-1);
}
/* restrict pathnames to current tree or uucppublic */
if ( substr(name, "../")
|| (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
canit();
#ifdef m6809
fprintf(stderr,"\r\nrz: Security Violation\r\n");
#else
fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
#endif
bibi(-1);
}
}
}
/*
* Ack a ZFIN packet, let byegones be byegones
*/
void
ackbibi()
{
register n;
vfile("ackbibi:");
Readnum = 1;
stohdr(0L);
for (n=3; --n>=0; ) {
purgeline();
zshhdr(4,ZFIN, Txhdr);
switch (readline(100)) {
case 'O':
readline(1); /* Discard 2nd 'O' */
vfile("ackbibi complete");
return;
case RCDO:
return;
case TIMEOUT:
default:
break;
}
}
}
/*
* Initialize for Zmodem receive attempt, try to activate Zmodem sender
* Handles ZSINIT frame
* Return ZFILE if Zmodem filename received, -1 on error,
* ZCOMPL if transaction finished, else 0
*/
tryz()
{
register c, n;
register cmdzack1flg;
if (Nozmodem) /* Check for "rb" program name */
return 0;
for (n=15; --n>=0; ) {
/* Set buffer length (0) and capability flags */
#ifdef SEGMENTS
stohdr(SEGMENTS*1024L);
#else
stohdr(0L);
#endif
#ifdef OS9
Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
#else
#ifdef CANBREAK
Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
#else
Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
#endif
#endif
if (Zctlesc)
Txhdr[ZF0] |= TESCCTL;
Txhdr[ZF0] |= CANRLE;
Txhdr[ZF1] = CANVHDR;
/* tryzhdrtype may == ZRINIT */
zshhdr(4,tryzhdrtype, Txhdr);
if (tryzhdrtype == ZSKIP) /* Don't skip too far */
tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
again:
switch (zgethdr(Rxhdr, 0)) {
case ZRQINIT:
if (Rxhdr[ZF3] & 0x80)
Usevhdrs = 1; /* we can var header */
continue;
case ZEOF:
continue;
case TIMEOUT:
continue;
case ZFILE:
zconv = Rxhdr[ZF0];
zmanag = Rxhdr[ZF1];
ztrans = Rxhdr[ZF2];
if (Rxhdr[ZF3] & ZCANVHDR)
Usevhdrs = TRUE;
tryzhdrtype = ZRINIT;
c = zrdata(secbuf, 1024);
if (c == GOTCRCW)
return ZFILE;
zshhdr(4,ZNAK, Txhdr);
goto again;
case ZSINIT:
Zctlesc = TESCCTL & Rxhdr[ZF0];
if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
stohdr(1L);
zshhdr(4,ZACK, Txhdr);
goto again;
}
zshhdr(4,ZNAK, Txhdr);
goto again;
case ZFREECNT:
stohdr(getfree());
zshhdr(4,ZACK, Txhdr);
goto again;
case ZCOMMAND:
cmdzack1flg = Rxhdr[ZF0];
if (zrdata(secbuf, 1024) == GOTCRCW) {
if (cmdzack1flg & ZCACK1)
stohdr(0L);
else
stohdr((long)sys2(secbuf));
purgeline(); /* dump impatient questions */
do {
zshhdr(4,ZCOMPL, Txhdr);
}
while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
ackbibi();
if (cmdzack1flg & ZCACK1)
exec2(secbuf);
return ZCOMPL;
}
zshhdr(4,ZNAK, Txhdr); goto again;
case ZCOMPL:
goto again;
default:
continue;
case ZFIN:
ackbibi(); return ZCOMPL;
case ZCAN:
return ERROR;
}
}
return 0;
}
/*
* Receive 1 or more files with ZMODEM protocol
*/
rzfiles()
{
register c;
for (;;) {
switch (c = rzfile()) {
case ZEOF:
case ZSKIP:
switch (tryz()) {
case ZCOMPL:
return OK;
default:
return ERROR;
case ZFILE:
break;
}
continue;
default:
return c;
case ERROR:
return ERROR;
}
}
}
rpt()
{
if (Verbose>1)
#ifdef OS9
#ifdef m6809
fprintf(stderr, "\r\t%7ld ZMODEM%s ",
rxbytes, Crc32r?" CRC-32":"");
#else
fprintf(stderr, "\r\x1b\x5b A%7ld ZMODEM%s ",
rxbytes, Crc32r?" CRC-32":"");
#endif
#else
fprintf(stderr, "\r%7ld ZMODEM%s ",
rxbytes, Crc32r?" CRC-32":"");
#endif
}
/*
* Receive a file with ZMODEM protocol
* Assumes file name frame is in secbuf
*/
rzfile()
{
register c, n;
Eofseen=FALSE;
n = 20; rxbytes = 0l;
if (c = procheader(secbuf)) {
return (tryzhdrtype = c);
}
for (;;) {
#ifdef SEGMENTS
chinseg = 0;
#endif
stohdr(rxbytes);
zshhdr(4,ZRPOS, Txhdr);
nxthdr:
switch (c = zgethdr(Rxhdr, 0)) {
default:
vfile("rzfile: Wrong header %d", c);
if ( --n < 0) {
sprintf(endmsg, "rzfile: Wrong header %d", c);
return ERROR;
}
continue;
case ZCAN:
sprintf(endmsg, "Sender CANcelled");
return ERROR;
case ZNAK:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if ( --n < 0) {
sprintf(endmsg, "rzfile: got ZNAK", c);
return ERROR;
}
continue;
case TIMEOUT:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if ( --n < 0) {
sprintf(endmsg, "rzfile: TIMEOUT", c);
return ERROR;
}
continue;
case ZFILE:
zrdata(secbuf, 1024);
continue;
case ZEOF:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if (rclhdr(Rxhdr) != rxbytes) {
/*
* Ignore eof if it's at wrong place - force
* a timeout because the eof might have gone
* out before we sent our zrpos.
*/
errors = 0; goto nxthdr;
}
if (closeit()) {
tryzhdrtype = ZFERR;
vfile("rzfile: closeit returned <> 0");
sprintf(endmsg,"Error closing file");
return ERROR;
}
vfile("rzfile: normal EOF");
return c;
case ERROR: /* Too much garbage in header search error */
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if ( --n < 0) {
sprintf(endmsg, "Persistent CRC or other ERROR");
return ERROR;
}
zmputs(Attn);
continue;
case ZSKIP:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
Modtime = 1;
closeit();
sprintf(endmsg, "Sender SKIPPED file");
return c;
case ZDATA:
if (rclhdr(Rxhdr) != rxbytes) {
if ( --n < 0) {
sprintf(endmsg,"Data has bad addr");
return ERROR;
}
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
zmputs(Attn); continue;
}
moredata:
#ifdef SEGMENTS
if (chinseg >= (1024 * SEGMENTS)) {
putsec(secbuf, chinseg);
chinseg = 0;
}
switch (c = zrdata(secbuf+chinseg, 1024))
#else
switch (c = zrdata(secbuf, 1024))
#endif
{
case ZCAN:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
sprintf(endmsg, "Sender CANcelled");
return ERROR;
case ERROR: /* CRC error */
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if ( --n < 0) {
sprintf(endmsg, "Persistent CRC or other ERROR");
return ERROR;
}
zmputs(Attn);
continue;
case TIMEOUT:
#ifdef SEGMENTS
putsec(secbuf, chinseg);
chinseg = 0;
#endif
if ( --n < 0) {
sprintf(endmsg, "TIMEOUT");
return ERROR;
}
continue;
case GOTCRCW:
n = 20;
#ifdef SEGMENTS
chinseg += Rxcount;
putsec(secbuf, chinseg);
chinseg = 0;
#else
putsec(secbuf, Rxcount);
#endif
rxbytes += Rxcount;
rpt();
stohdr(rxbytes);
sendline(XON);
zshhdr(4,ZACK, Txhdr);
goto nxthdr;
case GOTCRCQ:
n = 20;
#ifdef SEGMENTS
chinseg += Rxcount;
#else
putsec(secbuf, Rxcount);
#endif
rxbytes += Rxcount;
rpt();
stohdr(rxbytes);
zshhdr(4,ZACK, Txhdr);
goto moredata;
case GOTCRCG:
n = 20;
#ifdef SEGMENTS
chinseg += Rxcount;
#else
putsec(secbuf, Rxcount);
#endif
rxbytes += Rxcount;
rpt();
goto moredata;
case GOTCRCE:
n = 20;
#ifdef SEGMENTS
chinseg += Rxcount;
#else
putsec(secbuf, Rxcount);
#endif
rxbytes += Rxcount;
rpt();
goto nxthdr;
}
}
}
}
/*
* Close the receive dataset, return OK or ERROR
*/
closeit()
{
#ifdef OS9
long time();
fflush(fout);
if (Filemode & 0777)
_ss_attr(fileno(fout), u2oattr(Filemode));
#else
time_t time();
#endif
if (fclose(fout)==ERROR) {
fprintf(stderr, "file close ERROR\n");
return ERROR;
}
if (Modtime) {
timep[0] = time(NULL);
timep[1] = Modtime;
utime(Pathname, timep);
}
#ifndef OS9
if (
#ifdef POSIX
S_ISREG(Filemode)
#else
(Filemode&S_IFMT) == S_IFREG
#endif
)
chmod(Pathname, (unsigned short)(07777 & Filemode));
#endif
return OK;
}
/*
* Strip leading ! if present, do shell escape.
*/
sys2(s)
register char *s;
{
if (*s == '!')
++s;
return system(s);
}
/*
* Strip leading ! if present, do exec.
*/
exec2(s)
register char *s;
{
if (*s == '!')
++s;
mode(0);
#ifdef OS9
system(s);
#else
execl("/bin/sh", "sh", "-c", s);
#endif
}
/* End of rz.c */