[net.sources] minirb: YMODEM bootstrap

caf@omen.UUCP (Chuck Forsberg WA7KGX) (11/16/86)

Minirb is a lobotomized version of rz that uploads files to Unix using
YMODEM batch protocol.  I wrote it to provide a SHORT bootstrap for
Pro-YAM customers' use in uploading the complete rz and sz programs. 

Minirb calls stty(1) to manipulate the tty modes.  Minirb uses no
compile time options. 

Please let me know of any Unix systems this program has difficulty with.

Chuck Forsberg WA7KGX Author of Pro-YAM communications Tools for PCDOS and Unix
...!tektronix!reed!omen!caf  Omen Technology Inc "The High Reliability Software"
  Voice: 503-621-3406  17505-V Northwest Sauvie Island Road Portland OR 97231
TeleGodzilla BBS: 621-3746 2400/1200  CIS:70007,2304  Genie:CAF  Source:TCE022
  omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
  omen!/usr/spool/uucppublic/FILES lists all uucp-able files, updated hourly

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	minirb.1
#	minirb.c
# This archive created: Sat Nov 15 16:10:04 1986
cat << \SHAR_EOF > minirb.1
'\" Revision Level 
'\" Last Delta     11-15-86
.TH MINIRB 1 OMEN
.SH NAME
minirb \- Bootstrap YMODEM Batch file receive
.SH SYNOPSIS
.B minirb
.SH DESCRIPTION
.I Minirb
receives one or more files with YMODEM batch file transfer protocol.
.I Minirb
was developed for use as a bootstrap to simplify uploading of the longer
.I rz
and
.I sz
programs contained in the
.I rzsz1et2.sh
shell archive.
.SH SEE ALSO
YMODEM.DOC,
Professional-YAM manual,
sz(omen),
usq(omen),
undos(omen)
.SH NOTES
The source file
.I minirb.c
has been ruthlessly pruned to simplify uploading.
.I Minirb
uses 8 bit checksum which may not be compatible with all programs
claiming to support YMODEM batch transfers.
.I Minirb
calls stty(1) to set and reset raw tty mode.
SHAR_EOF
cat << \SHAR_EOF > minirb.c
/*
 * minirb.c By Chuck Forsberg Omen Technology INC
 *        "The High Reliability Communications Software"
 *
 * A bootstrap program for Unix to receive files from computers running
 *  YMODEM Batch (Professional-YAM, PowerCom, ZCOMM, etc.).
 *
 *  Minirb uses system(3) to call stty, avoiding system dependent code.
 *  Please refer to rz.c for comments, etc.
 */
char * Version = "minirb 1.00 11-15-86";

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>

#define OK 0
#define FALSE 0
#define TRUE 1
#define ERROR (-1)
#define CAN ('X'&037)
#define SOH 1
#define STX 2
#define EOT 4
#define ACK 6
#define NAK 025
#define TIMEOUT (-2)
#define RETRYMAX 9
#define WCEOT (-10)

FILE *fout;
long Bytesleft;
int Blklen;
char secbuf[1024];
char linbuf[1024];
int Lleft=0;
jmp_buf tohere;

alrm() { longjmp(tohere, -1); }

bibi(n) {
 canit(); mode(0);
 fprintf(stderr, "minirb: caught signal %d; exiting", n);
 exit(128+n);
}

mode(n) {
 if (n) system("stty raw -echo");
 else system("stty echo -raw");
}

main() {
 mode(1);
 if (signal(SIGINT, bibi) == SIG_IGN) {
  signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
 } else {
  signal(SIGINT, bibi); signal(SIGKILL, bibi);
 }
 printf("minirb: Now send file(s) with \042sb file ...\042 command\r\n");

 if (wcreceive()==ERROR)
  canit();
 mode(0); exit(0);
}

wcreceive() {
 for (;;) {
  if (wcrxpn(secbuf) == ERROR) break;
  if (secbuf[0]==0) return OK;
  if (procheader(secbuf)==ERROR || wcrx()==ERROR) break;
 }
 canit(); return ERROR;
}


wcrxpn(rpn) char *rpn; {
 register c;

 purgeline();
et_tu:
 sendline(NAK); Lleft=0;
 while ((c = wcgetsec(rpn, 100)) != 0) {
  if (c == WCEOT) { sendline(ACK); Lleft=0; readline(1); goto et_tu; }
  return ERROR;
 }
 sendline(ACK); return OK;
}

wcrx() {
 register int sectnum, sectcurr, sendchar, cblklen;

 sectnum=0; sendchar=NAK;
 for (;;) {
  sendline(sendchar); Lleft=0;
  sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
  if (sectcurr==(sectnum+1)) {
   sectnum++; cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
   if (putsec(secbuf, cblklen)==ERROR) return ERROR;
   if ((Bytesleft-=cblklen) < 0) Bytesleft = 0;
   sendchar=ACK;
  }
  else if (sectcurr==sectnum) sendchar=ACK;
  else if (sectcurr==WCEOT) {
   if (fclose(fout)==ERROR) return ERROR;
   sendline(ACK); Lleft=0; return OK;
  }
  else if (sectcurr==ERROR) return ERROR;
  else return ERROR;
 }
}

wcgetsec(rxbuf, maxtime) char *rxbuf; int maxtime; {
 register checksum, wcj, firstch; register char *p; int sectcurr, errors;
 for (errors=0; errors<RETRYMAX; errors++) {
  if ((firstch=readline(maxtime))==STX) { Blklen=1024; goto get2; }
  if (firstch==SOH) {
   Blklen=128;
get2:
   sectcurr=readline(1); checksum=0;
   if ((sectcurr+(readline(1)))==0377) {
    for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
     if ((firstch=readline(1)) < 0) goto bilge;
     checksum += (*p++ = firstch);
    }
    if ((firstch=readline(1)) < 0) goto bilge;
    if (((checksum-firstch)&0377)==0) return sectcurr;
   }
  }
  else if (firstch==EOT) return WCEOT;
  else if (firstch==CAN) return ERROR;
bilge:
  while(readline(1)!=TIMEOUT)
   ;
  maxtime=40; sendline(NAK); Lleft=0;
 }
 canit(); return ERROR;
}

readline(timeout) int timeout; {
 register n; static char *cdq;

 if (--Lleft >= 0) return (*cdq++ & 0377);
 n = timeout/10;
 if (n < 2) n = 3;
 if (setjmp(tohere)) { Lleft = 0; return TIMEOUT; }
 signal(SIGALRM, alrm); alarm(n);
 Lleft=read(0, cdq=linbuf, 1024); alarm(0);
 if (Lleft < 1) return TIMEOUT;
 --Lleft; return (*cdq++ & 0377);
}

purgeline() { Lleft = 0; lseek(0, 0L, 2); }


procheader(name) char *name; {
 register char *p;

 Bytesleft = 2000000000L; p = name + 1 + strlen(name);
 if (*p) sscanf(p, "%ld", &Bytesleft);
 if ((fout=fopen(name, "w")) == NULL) return ERROR;
 return OK;
}

putsec(buf, n) char *buf; register n;
{
 register char *p;
 for (p=buf; --n>=0; ) putc( *p++, fout);
 return OK;
}

sendline(c) { char d; d = c; write(1, &d, 1); }

char canistr[] = { 24,24,24,24,24,24,24,24,0 };

canit() { printf(canistr); Lleft=0; }

/* END of minirb.c */

SHAR_EOF
#	End of shell archive
exit 0