dan@i10s7.ira.uka.de (Dan Mosedale) (05/17/91)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 7 (of 9)."
# Contents: pf-bootstrap-v1.1a/tipx-p1/tip.c
# pf-bootstrap-v1.1a/xmodem-3.9/receive.c
# Wrapped by dan@nostromo on Fri May 17 02:31:43 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'pf-bootstrap-v1.1a/tipx-p1/tip.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pf-bootstrap-v1.1a/tipx-p1/tip.c'\"
else
echo shar: Extracting \"'pf-bootstrap-v1.1a/tipx-p1/tip.c'\" \(16153 characters\)
sed "s/^X//" >'pf-bootstrap-v1.1a/tipx-p1/tip.c' <<'END_OF_FILE'
Xchar *tipx_rev = "x1.21";
X#define PATCHLEVEL 1
X/*
X * Copyright (c) 1983 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley. The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X/*
X * Modifications by Warren Tucker <wht%n4hgf.uucp@emory.mathcs.emory.edu>
X * for eight-bit transparent pass through and file transfer protocols
X * are unencumbered in any way. They are yours, ours, everybody's, nobody's.
X */
X/*+:EDITS:*/
X/*:05-08-1990-15:05-wht@n4hgf-rawthru */
X/*:05-08-1990-15:00-wht@n4hgf-move tip.c original to tip-orig.c */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright(c) 1983 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)tip.c 5.8 (Berkeley) 9/2/88 (mod by wht@n4hgf)";
X#endif /* not lint */
X
X/*
X * tip - UNIX link to other systems
X * tip [-psv] [-speed] system-name [data]
X * or
X * cu phone-number [-s speed] [-l line] [-a acu]
X */
X#include "tip.h"
X
X/*
X * Baud rate mapping table
X */
Xint bauds[] =
X{
X 0,50,75,110,134,150,200,300,600,
X 1200,1800,2400,4800,9600,19200,38400,-1
X};
X
X#ifdef TIPX
Xint rawthru = 0;
Xchar *rawthru_msg = "\r\n--> raw tip: 3 ~ rapidly for ~ equivalent\r\n";
Xchar *no_rawthru_msg = "\r\n--> normal tip: 1 ~ == ~\r\n";
Xextern char opened_tty[];
X#endif
X
Xint page;
Xint disc = OTTYDISC; /* tip normally runs this way */
Xsigfunc_t intprompt();
Xsigfunc_t timeout();
Xsigfunc_t cleanup();
Xchar *login();
Xchar *sname();
Xchar PNbuf[256]; /* This limits the size of a number */
Xstruct sgttyb ttyarg;
X
X#ifdef TIPX
Xtypedef struct b_to_br
X{
X char *baud_rate;
X int B_code;
X} B_TO_BR;
X
XB_TO_BR speeds[] = /* ordered to put less common rates later in table */
X{ /* and the vagaries of baud rates above 9600 "handled" */
X "2400", B2400,
X "1200", B1200,
X "9600", B9600,
X#if defined(B19200)
X "19200",B19200,
X#endif
X#if defined(B38400)
X "38400",B38400,
X#endif
X "4800", B4800,
X "300", B300,
X "110", B110,
X "600", B600,
X "75", B75,
X "50", B50,
X "HUP", B0,
X "EXTA", EXTA,
X "EXTB", EXTB,
X
X (char *)0,0
X};
X#endif /* TIPX */
X
X/*+-------------------------------------------------------------------------
X B_to_baud_rate(code) - convert CBAUD B_ code to baud rate string
X--------------------------------------------------------------------------*/
X#ifdef TIPX
Xchar *
XB_to_baud_rate(code)
Xint code;
X{
Xregister int n;
X
X for(n=0; speeds[n].baud_rate; n++)
X if(speeds[n].B_code == code)
X return(speeds[n].baud_rate);
X return("-----");
X} /* end of B_to_baud_rate */
X#endif /* TIPX */
X
Xmain(argc,argv)
Xchar *argv[];
X{
X int uuid;
X char *system = NOSTR;
X char *data = NOSTR;
X register int i;
X register char *p;
X char sbuf[12];
X
X uid = getuid();
X gid = getgid();
X euid = geteuid(); /* should be root */
X egid = getegid();
X uuid = getuucpuid();
X
X if(equal(sname(argv[0]),"cu"))
X {
X setreuid(uid,uuid);
X cumode = 1;
X cumain(argc,argv);
X goto cucommon;
X }
X
X if(argc < 2)
X {
X fprintf(stderr,"usage: tip [-psv] [-speed] [system-name] [data]\n");
X exit(1);
X }
X
X for(; argc > 1; argv++,argc--)
X {
X if(argv[1][0] != '-')
X {
X if(system)
X data = argv[1];
X else
X system = argv[1];
X }
X else switch(argv[1][1])
X {
X
X case 'p':
X page++;
X break;
X case 's':
X slip++;
X break;
X case 'v':
X vflag++;
X break;
X
X case '0':
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X case '8':
X case '9':
X BR = atoi(&argv[1][1]);
X break;
X
X default:
X fprintf(stderr,"tip: %s, unknown option\n",argv[1]);
X break;
X }
X }
X if(!isatty(0) && !slip && !page)
X {
X fprintf(stderr,"tip: warning: input is not a tty\n");
X }
X if(slip)
X {
X setreuid(euid,uuid);
X uid = 0;
X }
X else
X {
X setreuid(uid,uuid);
X }
X euid = uuid;
X
X if(system == NOSTR)
X goto notnumber;
X if(isalpha(*system))
X goto notnumber;
X /*
X * System name is really a phone number...
X * Copy the number then stomp on the original (in case the number
X * is private, we don't want 'ps' or 'w' to find it).
X */
X if(strlen(system) > sizeof PNbuf - 1)
X {
X fprintf(stderr,"tip: phone number too long (max = %d bytes)\n",
X sizeof PNbuf - 1);
X exit(1);
X }
X strncpy( PNbuf,system,sizeof PNbuf - 1 );
X for(p = system; *p; p++)
X *p = '\0';
X PN = PNbuf;
X (void)sprintf(sbuf,"tip%d",BR);
X system = sbuf;
X
Xnotnumber:
X signal(SIGINT,cleanup);
X signal(SIGQUIT,cleanup);
X signal(SIGHUP,cleanup);
X signal(SIGTERM,cleanup);
X signal(SIGPIPE,cleanup);
X
X if((i = hunt(system)) == 0)
X {
X printf("all ports busy\n");
X exit(3);
X }
X if(i == -1)
X {
X printf("link down\n");
X (void)uu_unlock(uucplock);
X exit(3);
X }
X setbuf(stdout,NULL);
X loginit();
X
X /*
X * Kludge, their's no easy way to get the initialization
X * in the right order, so force it here
X */
X if((PH = getenv("PHONES")) == NOSTR)
X PH = "/etc/phones";
X vinit(); /* init variables */
X setparity("none"); /* set the parity table */
X if((i = speed(number(value(BAUDRATE)))) == NULL)
X {
X printf("tip: bad baud rate %d\n",number(value(BAUDRATE)));
X (void)uu_unlock(uucplock);
X exit(3);
X }
X
X if(slip)
X {
X if(SA == NOSTR)
X {
X printf("tip: local addr not set\n");
X uu_unlock(uucplock);
X exit(3);
X }
X if(DA == NOSTR)
X {
X printf("tip: destination addr not set\n");
X uu_unlock(uucplock);
X exit(3);
X }
X if(SM == NOSTR)
X {
X printf("tip: slip netmask not set\n");
X uu_unlock(uucplock);
X exit(3);
X }
X }
X
X /*
X * Now that we have the logfile and the ACU open
X * return to the real uid and gid. These things will
X * be closed on exit. Swap real and effective uid's
X * so we can get the original permissions back
X * for removing the uucp lock.
X */
X user_uid(); /* in the case of slip, we are now priviliged */
X
X /*
X * Hardwired connections require the
X * line speed set before they make any transmissions
X * (this is particularly true of things like a DF03-AC)
X */
X if(HW)
X ttysetup(i);
X if(p = lconnect())
X {
X printf("\07%s\n[EOT]\n",p);
X daemon_uid();
X (void)uu_unlock(uucplock);
X exit(1);
X }
X if(!HW)
X ttysetup(i);
X
X
X if(LS != NOSTR)
X {
X fprintf(stderr,"\07[Logging in...]\r\n");
X if(p = login())
X {
X printf("\07%s\n[EOT]\n",p);
X daemon_uid();
X (void)uu_unlock(uucplock);
X exit(1);
X }
X }
X
X if(page)
X {
X i = sendpage(data);
X daemon_uid();
X (void)uu_unlock(uucplock);
X exit(i);
X }
X
X if(slip)
X {
X i = runslip();
X daemon_uid();
X (void)uu_unlock(uucplock);
X exit(i);
X }
X
Xcucommon:
X /*
X * From here down the code is shared with
X * the "cu" version of tip.
X */
X
X ioctl(0,TIOCGETP,(char *)&defarg);
X ioctl(0,TIOCGETC,(char *)&defchars);
X ioctl(0,TIOCGLTC,(char *)&deflchars);
X ioctl(0,TIOCGETD,(char *)&odisc);
X arg = defarg;
X#ifdef TIPX
X arg.sg_flags = CBREAK;
X#else
X arg.sg_flags = ANYP | CBREAK;
X#endif
X tchars = defchars;
X tchars.t_intrc = tchars.t_quitc = -1;
X ltchars = deflchars;
X ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
X = ltchars.t_lnextc = -1;
X raw();
X
X pipe(fildes);
X pipe(repdes);
X signal(SIGALRM,timeout);
X
X /*
X * Everything's set up now:
X * connection established (hardwired or dialup)
X * line conditioned (baud rate, mode, etc.)
X * internal data structures (variables)
X * so, fork one process for local side and one for remote.
X */
X#ifdef TIPX
X printf("tipx (tip 4.3 mod by wht@n4hgf %s.%02d) connected to %s\r\n",
X tipx_rev,PATCHLEVEL,opened_tty);
X fputs("Copyright (c) 1983 The Regents of the University of California.\r\n",
X stdout);
X printf("line speed = %s, tandem = %s\r\n",
X B_to_baud_rate(ttyarg.sg_ospeed),
X (ttyarg.sg_flags & TANDEM) ? "yes" : "no");
X#else
X printf(cumode ? "Connected\r\n" : "\07connected\r\n");
X#endif
X if(pid = fork())
X tipin();
X else
X tipout();
X /*NOTREACHED*/
X}
X
Xsigfunc_t
Xcleanup()
X{
X
X daemon_uid();
X (void)uu_unlock(uucplock);
X if(pid)
X {
X (void) kill(pid,SIGTERM);
X unraw();
X }
X else if(odisc)
X ioctl(0,TIOCSETD,(char *)&odisc);
X exit(0);
X}
X
X/*
X * Muck with user ID's. We are setuid to the owner of the lock
X * directory when we start. user_uid() reverses real and effective
X * ID's after startup, to run with the user's permissions.
X * daemon_uid() switches back to the privileged uid for unlocking.
X * Finally, to avoid running a shell with the wrong real uid,
X * shell_uid() sets real and effective uid's to the user's real ID.
X */
Xstatic int uidswapped;
X
Xuser_uid()
X{
X if(uidswapped == 0)
X {
X setregid(egid,gid);
X setreuid(euid,uid);
X uidswapped = 1;
X }
X}
X
Xdaemon_uid()
X{
X if(uidswapped)
X {
X setreuid(uid,euid);
X setregid(gid,egid);
X uidswapped = 0;
X }
X}
X
Xshell_uid()
X{
X
X setreuid(uid,uid);
X setregid(gid,gid);
X}
X
X/*
X * put the controlling keyboard into raw mode
X */
Xraw()
X{
X
X ioctl(0,TIOCSETP,&arg);
X ioctl(0,TIOCSETC,&tchars);
X ioctl(0,TIOCSLTC,<chars);
X ioctl(0,TIOCSETD,(char *)&disc);
X}
X
X
X/*
X * return keyboard to normal mode
X */
Xunraw()
X{
X
X ioctl(0,TIOCSETD,(char *)&odisc);
X ioctl(0,TIOCSETP,(char *)&defarg);
X ioctl(0,TIOCSETC,(char *)&defchars);
X ioctl(0,TIOCSLTC,(char *)&deflchars);
X}
X
Xstatic jmp_buf promptbuf;
X
X/*
X * Print string ``s'', then read a string
X * in from the terminal. Handles signals & allows use of
X * normal erase and kill characters.
X */
Xprompt(s,p)
Xchar *s;
Xregister char *p;
X{
X register char *b = p;
X sigfunc_t(*oint)(),(*oquit)();
X
X stoprompt = 0;
X oint = signal(SIGINT,intprompt);
X oquit = signal(SIGQUIT,SIG_IGN);
X unraw();
X printf("%s",s);
X if(setjmp(promptbuf) == 0)
X while((*p = getchar()) != EOF && *p != '\n')
X p++;
X *p = '\0';
X
X raw();
X signal(SIGINT,oint);
X signal(SIGQUIT,oint);
X return(stoprompt || p == b);
X}
X
X/*
X * Interrupt service routine during prompting
X */
Xsigfunc_t
Xintprompt()
X{
X
X signal(SIGINT,SIG_IGN);
X stoprompt = 1;
X printf("\r\n");
X longjmp(promptbuf,1);
X}
X
X/*
X * ****TIPIN TIPIN****
X */
Xtipin()
X{
X char gch,bol = 1;
X
X /*
X * Kinda klugey here...
X * check for scripting being turned on from the .tiprc file,
X * but be careful about just using setscript(), as we may
X * send a SIGEMT before tipout has a chance to set up catching
X * it; so wait a second, then setscript()
X */
X if(boolean(value(SCRIPT)))
X {
X sleep(1);
X setscript();
X }
X
X#ifdef TIPX
X if(!rawthru)
X goto NORMAL_TIP2;
X
XRAWTHRU_TIP:
X printf(rawthru_msg);
X while(1)
X {
X long count;
X char chbuf[4];
X read(0,&gch,1);
X if((gch == character(value(ESCAPE))))
X {
X sleep(1);
X ioctl(0,FIONREAD,&count);
X if(count == 2)
X { /* might have raw mode escape */
X read(0,chbuf,2);
X if((chbuf[0] == character(value(ESCAPE))) &&
X (chbuf[1] == character(value(ESCAPE))))
X {
X printf("rawthru%s",ctrl(chbuf[0]));
X if(!(gch = escape()))
X {
X if(!rawthru)
X {
X bol = 1;
X goto NORMAL_TIP;
X }
X continue;
X }
X }
X else
X {
X gch = character(value(ESCAPE));
X write(FD,&gch,1);
X write(FD,chbuf,2);
X continue;
X }
X }
X }
X write(FD,&gch,1);
X }
X
XNORMAL_TIP:
X printf(no_rawthru_msg);
XNORMAL_TIP2:
X#endif /* TIPX */
X while(1)
X {
X gch = getchar()&0177;
X if((gch == character(value(ESCAPE))) && bol)
X {
X if(!(gch = escape()))
X#ifdef TIPX
X {
X if(rawthru)
X goto RAWTHRU_TIP;
X continue;
X }
X#else /* TIPX */
X continue;
X#endif /* TIPX */
X }
X else if(!cumode && gch == character(value(RAISECHAR)))
X {
X boolean(value(RAISE)) = !boolean(value(RAISE));
X continue;
X }
X else if(gch == '\r')
X {
X bol = 1;
X pwrite(FD,&gch,1);
X if(boolean(value(HALFDUPLEX)))
X printf("\r\n");
X continue;
X }
X else if(!cumode && gch == character(value(FORCE)))
X gch = getchar()&0177;
X bol = any(gch,value(EOL));
X if(boolean(value(RAISE)) && islower(gch))
X gch = toupper(gch);
X pwrite(FD,&gch,1);
X if(boolean(value(HALFDUPLEX)))
X printf("%c",gch);
X }
X}
X
X/*
X * Escape handler --
X * called on recognition of ``escapec'' at the beginning of a line
X */
Xescape()
X{
X register char gch;
X register esctable_t *p;
X char c = character(value(ESCAPE));
X extern esctable_t etable[];
X
X gch = (getchar()&0177);
X for(p = etable; p->e_char; p++)
X if(p->e_char == gch)
X {
X if((p->e_flags&PRIV) && uid)
X continue;
X#ifdef TIPX
X if(!rawthru)
X#endif
X printf("%s",ctrl(c));
X (*p->e_func)(gch);
X return(0);
X }
X /* ESCAPE ESCAPE forces ESCAPE */
X if(c != gch)
X pwrite(FD,&c,1);
X return(gch);
X}
X
Xspeed(n)
Xint n;
X{
X register int *p;
X
X for(p = bauds; *p != -1; p++)
X if(*p == n)
X return(p - bauds);
X return(NULL);
X}
X
Xany(c,p)
Xregister char c,*p;
X{
X while(p && *p)
X if(*p++ == c)
X return(1);
X return(0);
X}
X
Xsize(s)
Xregister char *s;
X{
X register int i = 0;
X
X while(s && *s++)
X i++;
X return(i);
X}
X
Xchar *
Xinterp(s)
Xregister char *s;
X{
X static char buf[256];
X register char *p = buf,c,*q;
X
X while(c = *s++)
X {
X for(q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
X if(*q++ == c)
X {
X *p++ = '\\';
X *p++ = *q;
X goto next;
X }
X if(c < 040)
X {
X *p++ = '^';
X *p++ = c + 'A'-1;
X }
X else if(c == 0177)
X {
X *p++ = '^';
X *p++ = '?';
X }
X else
X *p++ = c;
Xnext:
X ;
X }
X *p = '\0';
X return(buf);
X}
X
Xchar *
Xctrl(c)
Xchar c;
X{
X static char s[3];
X
X if(c < 040 || c == 0177)
X {
X s[0] = '^';
X s[1] = c == 0177 ? '?' : c+'A'-1;
X s[2] = '\0';
X }
X else
X {
X s[0] = c;
X s[1] = '\0';
X }
X return(s);
X}
X
X/*
X * Help command
X */
Xhelp(c)
Xchar c;
X{
X register esctable_t *p;
X extern esctable_t etable[];
X
X printf("%c\r\n",c);
X for(p = etable; p->e_char; p++)
X {
X if((p->e_flags&PRIV) && uid)
X continue;
X printf("%2s",ctrl(character(value(ESCAPE))));
X printf("%-2s %c %s\r\n",ctrl(p->e_char),
X p->e_flags&EXP ? '*': ' ',p->e_help);
X }
X}
X
X/*
X * Set up the "remote" tty's state
X */
Xttysetup(speed)
Xint speed;
X{
X unsigned bits = LDECCTQ;
X
X ttyarg.sg_ispeed = ttyarg.sg_ospeed = speed;
X ttyarg.sg_flags = RAW;
X if(boolean(value(TAND)))
X ttyarg.sg_flags |= TANDEM;
X if(boolean(value(DTRHUP)))
X {
X ioctl(FD,TIOCSDTR,0);
X ioctl(FD,TIOCHPCL,0);
X }
X ioctl(FD,TIOCSETP,(char *)&ttyarg);
X ioctl(FD,TIOCLBIS,(char *)&bits);
X}
X
X/*
X * Return "simple" name from a file name,
X * strip leading directories.
X */
Xchar *
Xsname(s)
Xregister char *s;
X{
X register char *p = s;
X
X while(*s)
X if(*s++ == '/')
X p = s;
X return(p);
X}
X
Xstatic char partab[0200];
X
X/*
X * Do a write to the remote machine with the correct parity.
X * We are doing 8 bit wide output, so we just generate a character
X * with the right parity and output it.
X */
Xpwrite(fd,buf,n)
Xint fd;
Xchar *buf;
Xregister int n;
X{
X register int i;
X register char *bp;
X extern int errno;
X#ifdef TIPX
X extern int rawthru;
X
X if(rawthru)
X {
X write(fd,buf,n);
X return;
X }
X#endif /* TIPX */
X
X bp = buf;
X for(i = 0; i < n; i++)
X {
X *bp = partab[(*bp) & 0177];
X bp++;
X }
X if(write(fd,buf,n) < 0)
X {
X if(errno == EIO)
X abort("Lost carrier.");
X /* this is questionable */
X perror("write");
X }
X}
X
X/*
X * Build a parity table with appropriate high-order bit.
X */
Xsetparity(defparity)
Xchar *defparity;
X{
X register int i;
X char *parity;
X extern char evenpartab[];
X
X if(value(PARITY) == NOSTR)
X value(PARITY) = defparity;
X parity = value(PARITY);
X for(i = 0; i < 0200; i++)
X partab[i] = evenpartab[i];
X if(equal(parity,"even"))
X return;
X if(equal(parity,"odd"))
X {
X for(i = 0; i < 0200; i++)
X partab[i] ^= 0200; /* reverse bit 7 */
X return;
X }
X if(equal(parity,"none") || equal(parity,"zero"))
X {
X for(i = 0; i < 0200; i++)
X partab[i] &= ~0200; /* turn off bit 7 */
X return;
X }
X if(equal(parity,"one"))
X {
X for(i = 0; i < 0200; i++)
X partab[i] |= 0200; /* turn on bit 7 */
X return;
X }
X fprintf(stderr,"%s: unknown parity value\n",PA);
X fflush(stderr);
X}
X
X/* The uid could be determined by stat()-ing ACULOG */
Xgetuucpuid()
X{
X struct passwd *pw;
X
X if((pw = getpwnam("uucp")) == NULL)
X {
X fprintf(stderr,"tip: unable to get uucp uid\n");
X exit(1);
X }
X return(pw->pw_uid);
X}
END_OF_FILE
if test 16153 -ne `wc -c <'pf-bootstrap-v1.1a/tipx-p1/tip.c'`; then
echo shar: \"'pf-bootstrap-v1.1a/tipx-p1/tip.c'\" unpacked with wrong size!
fi
# end of 'pf-bootstrap-v1.1a/tipx-p1/tip.c'
fi
if test -f 'pf-bootstrap-v1.1a/xmodem-3.9/receive.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pf-bootstrap-v1.1a/xmodem-3.9/receive.c'\"
else
echo shar: Extracting \"'pf-bootstrap-v1.1a/xmodem-3.9/receive.c'\" \(17709 characters\)
sed "s/^X//" >'pf-bootstrap-v1.1a/xmodem-3.9/receive.c' <<'END_OF_FILE'
X#include "xmodem.h"
X
X/** receive a file **/
X
X/* returns TRUE if in the midst of a batch transfer */
X/* returns FALSE if no more files are coming */
X
X/* This routine is one HUGE do-while loop with far to many indented levels.
X * I chose this route to facilitate error processing and to avoid GOTOs.
X * Given the troubles I've had keeping the nested IF statements straight,
X * I was probably mistaken...
X */
X
Xrfile(name)
Xchar *name;
X{
X
Xchar *sectdisp();
Xchar *cpm_unix();
Xchar *strcpy();
Xchar *ctime();
Xtime_t time();
X
Xint fd, /* file descriptor for created file */
Xchecksum, /* packet checksum */
Xfirstchar, /* first character of a packet */
Xsectnum, /* number of last received packet (modulo 128) */
Xsectcurr, /* second byte of packet--should be packet number (mod 128) */
Xsectcomp, /* third byte of packet--should be complement of sectcurr */
Xtmode, /* text mode if true */
Xamode, /* apple mode if true */
Xerrors, /* count of errors for each packet */
Xsterrors, /* count of errors during startup handshake */
Xerrorflag, /* set true when packet (or first char of putative packet) is invalid */
Xfatalerror, /* set within main "read-packet" Do-While when bad error found */
Xinchecksum, /* incoming checksum or CRC */
Xexpsect, /* expected number of sectors (YMODEM batch) */
Xfirstwait, /* seconds to wait for first character in a packet */
Xnocancanabort, /* if true, don't allow CAN-CAN abort */
Xbufsize; /* packet size (128 or 1024) */
Xlong recvsectcnt; /* running sector count (128 byte sectors) */
Xlong modtime; /* Unix style file mod time from YMODEM header */
Xint filemode; /* Unix style file mode from YMODEM header */
Xint serial; /* serial # from YMODEM header */
Xint filesleft; /* # of files left from YMODEM header */
Xlong totalleft; /* # of bytes left from YMODEM header */
Xint yfiletype; /* file type from YMODEM header */
Xlong readbackup; /* "backup" value for characters read in file */
Xtime_t timep[2]; /* used in setting mod time of received file */
Xchar *p; /* generic pointer */
Xint bufctr; /* number of real chars in read packet */
Xunsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
Xtime_t start; /* starting time of transfer */
Xint openflag = FALSE; /* is file open for writing? */
X
Xlogit("----\nXMODEM File Receive Function\n");
Xtlogit("----\nXMODEM File Receive Function\n");
Xif (CRCMODE)
X {
X logit("CRC mode requested on command line\n");
X tlogit("CRC mode requested on command line\n");
X }
X
Xif (YMODEMG)
X {
X logit("YMODEM-G mode requested on command line\n");
X tlogit("YMODEM-G mode requested on command line\n");
X }
X
XBATCH = FALSE; /* don't know if really are in batch mode ! */
Xfatalerror = FALSE;
Xfirstwait = WAITFIRST; /* For first packet, wait short time */
Xsectnum = errors = recvsectcnt = 0;
Xbufsize = 128;
Xmodtime = 0l; filemode = 0;
Xserial = 0; filesleft = 0; totalleft = 0l; yfiletype = 0;
Xfilelength = 0l; fileread =0l; CHECKLENGTH = FALSE;
Xnocancanabort = FALSE;
X
Xtmode = (XMITTYPE == 't') ? TRUE : FALSE;
Xamode = (XMITTYPE == 'a') ? TRUE : FALSE;
X
X/* start up transfer */
X
Xsterrors = 0;
Xflushin(); /* flush input queue */
X
Xif (YMODEMG)
X sendbyte(GCHR);
Xelse if (CRCMODE && !MDM7BAT)
X{
X sendbyte(CRCCHR);
X if (LONGPACK && !MDM7BAT)
X sendbyte(KCHR);
X}
Xelse
X sendbyte(NAK);
X
X
Xdo /* start of MAIN Do-While loop to read packets */
X{
X errorflag = FALSE;
X do /* start by reading first byte in packet */
X {
X firstchar = readbyte(firstwait);
X }
X while ((firstchar != SOH)
X && (firstchar != STX)
X && (firstchar != EOT)
X && (firstchar != ACK || recvsectcnt > 0)
X && (firstchar != TIMEOUT)
X && (firstchar != CAN || nocancanabort));
X
X if (firstchar == EOT && !NOEOT) /* check for REAL EOT */
X {
X flushin();
X sendbyte(NAK); /* NAK the EOT */
X if ((firstchar = readbyte(5)) != EOT) /* check next character */
X {
X logit("Spurious EOT detected; ignored\n");
X tlogit("Spurious EOT detected; ignored\n");
X if ((firstchar == SOH) || (firstchar == STX) ||
X (firstchar == ACK && recvsectcnt == 0) ||
X (firstchar == CAN && !nocancanabort) ||
X (firstchar == TIMEOUT))
X ;
X else
X {
X firstchar = 0;
X errorflag = TRUE;
X }
X }
X }
X
X if (firstchar == TIMEOUT) /* timeout? */
X {
X if (recvsectcnt > 0)
X {
X logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X tlogitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X }
X errorflag = TRUE;
X }
X
X if (firstchar == CAN) /* bailing out? (only at beginning or if CANCAN flag set) */
X {
X if ((readbyte(3) & 0x7f) == CAN)
X {
X if (openflag)
X {
X close(fd);
X unlink(name);
X error("Reception Canceled by CAN-CAN; partial file deleted",TRUE);
X }
X else
X error("Reception Canceled by CAN-CAN",TRUE);
X }
X else
X {
X errorflag = TRUE;
X logit("Received single CAN character\n");
X tlogit("Received single CAN character\n");
X }
X }
X
X if (firstchar == ACK) /* MODEM7 batch? (only at beginning) */
X {
X int i,c;
X
X logit("MODEM7 Batch Protocol\n");
X tlogit("MODEM7 Batch Protocol\n");
X nameptr = buff;
X checksum = 0;
X
X for (i=0; i<NAMSIZ; i++)
X {
X c = readbyte(3);
X
X if (c == CAN)
X {
X if (readbyte(3) == CAN)
X error("Program Canceled by CAN-CAN", TRUE);
X else
X {
X logit("Received single CAN character in MODEM7 filename\n");
X tlogit("Received single CAN character in MODEM7 filename\n");
X errorflag = TRUE;
X break;
X }
X }
X
X if (c == EOT && i == 0)
X {
X sendbyte(ACK); /* acknowledge EOT */
X logit("MODEM7 Batch Receive Complete\n");
X tlogit("MODEM7 Batch Receive Complete\n");
X return (FALSE);
X }
X
X if (c == TIMEOUT)
X {
X logit("Timeout waiting for MODEM7 filename character\n");
X tlogit("Timeout waiting for MODEM7 filename character\n");
X errorflag = TRUE;
X break;
X }
X
X if (c == BAD_NAME)
X {
X logit("Error during MODEM7 filename transfer\n");
X tlogit("Error during MODEM7 filename transfer\n");
X errorflag = TRUE;
X break;
X }
X
X *nameptr++ = c;
X checksum += c;
X sendbyte(ACK);
X }
X
X if (!errorflag)
X {
X c = readbyte(3);
X if (c == CTRLZ) /* OK; end of string found */
X {
X sendbyte(checksum + CTRLZ);
X if (readbyte(15) == ACK) /* file name found! */
X {
X xmdebug("MODEM7 file name OK");
X *nameptr = '\000'; /* unixify the file name */
X name = cpm_unix(buff);
X BATCH = TRUE;
X logitarg("MODEM7 file name: %s\n", name);
X tlogitarg("MODEM7 file name: %s\n", name);
X errors = 0; /* restart crc handshake */
X sleep(2); /* give other side a chance */
X }
X else
X {
X logit("Checksum error in MODEM7 filename\n");
X tlogit("Checksum error in MODEM7 filename\n");
X errorflag = TRUE;
X }
X }
X else
X {
X logit("Length error in MODEM7 filename\n");
X tlogit("Length error in MODEM7 filename\n");
X errorflag = TRUE;
X }
X }
X }
X
X
X if (firstchar == SOH || firstchar == STX) /* start reading packet */
X {
X bufsize = (firstchar == SOH) ? 128 : 1024;
X
X if (recvsectcnt == 0) /* 1st data packet, initialize */
X {
X if (bufsize == 1024)
X {
X logit("1K packet mode chosen\n");
X tlogit("1K packet mode chosen\n");
X }
X start = time((time_t *) 0);
X errors = 0;
X firstwait = 5;
X }
X
X sectcurr = readbyte(3);
X sectcomp = readbyte(3);
X if ((sectcurr + sectcomp) == 0xff) /* is packet number checksum correct? */
X {
X if (sectcurr == ((sectnum+1) & 0xff)) /* is packet number correct? */
X {
X if (DEBUG)
X fprintf(LOGFP,"DEBUG: packet with sector number %d started\n", sectnum);
X
X /* Read, process and calculate checksum for a buffer of data */
X
X readbackup = fileread;
X if (readbuf(bufsize, 1, tmode, amode, recvsectcnt, &checksum, &bufctr) != TIMEOUT)
X {
X
X /* verify checksum or CRC */
X
X if (CRCMODE)
X {
X checksum &= 0xffff;
X inchecksum = readbyte(3); /* get 16-bit CRC */
X inchecksum = (inchecksum<<8) | readbyte(3);
X }
X
X else
X inchecksum = readbyte(3); /* get simple 8-bit checksum */
X
X if (inchecksum == checksum) /* good checksum, hence good packet */
X {
X xmdebug("checksum ok");
X errors = 0;
X recvsectcnt += (bufsize == 128) ? 1 : 8;
X nocancanabort = CANCAN ? FALSE : TRUE;
X sectnum = sectcurr;
X
X if (!openflag) /* open output file if necessary */
X {
X openflag = TRUE;
X if ((fd = creat(name, CREATMODE)) < 0)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X error("Can't create file for receive", TRUE);
X }
X if (!BATCH)
X {
X logitarg("File Name: %s\n", name);
X tlogitarg("File Name: %s\n", name);
X }
X }
X
X if (write(fd, (char *) buff, bufctr) != bufctr)
X {
X close(fd);
X unlink(name);
X error("File Write Error", TRUE);
X }
X else
X {
X if (TIPFLAG && recvsectcnt % 32 == 0)
X tlogitarg("Sector %s received\n", sectdisp(recvsectcnt,bufsize,0));
X if (!YMODEMG)
X {
X flushin(); /* flush input */
X sendbyte(ACK); /* ACK the received packet */
X }
X }
X }
X
X /* Start handling various errors and special conditions */
X
X else /* bad checksum */
X {
X logitarg("Checksum Error on Sector %s: ", sectdisp(recvsectcnt,bufsize,1));
X logitarg("sent=%x ", inchecksum);
X logitarg("recvd=%x\n", checksum);
X tlogitarg("Checksum Error on Sector %s: ", sectdisp(recvsectcnt,bufsize,1));
X tlogitarg("sent=%x ", inchecksum);
X tlogitarg("recvd=%x\n", checksum);
X fileread = readbackup;
X errorflag = TRUE;
X if (YMODEMG)
X fatalerror = TRUE;
X }
X }
X
X else /* read timeout */
X {
X logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X tlogitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X fileread = readbackup;
X errorflag = TRUE;
X if (YMODEMG)
X fatalerror = TRUE;
X }
X }
X
X else /* sector number is wrong OR Ymodem filename */
X {
X if (sectcurr == 0 && recvsectcnt == 0) /* Ymodem file-name packet */
X {
X logit("YMODEM Batch Protocol\n");
X tlogit("YMODEM Batch Protocol\n");
X
X /* Read and process a file-name packet */
X
X if (readbuf(bufsize, 1, FALSE, FALSE, recvsectcnt, &checksum, &bufctr) != TIMEOUT)
X {
X
X /* verify checksum or CRC */
X
X if (CRCMODE)
X {
X checksum &= 0xffff;
X inchecksum = readbyte(3); /* get 16-bit CRC */
X inchecksum = (inchecksum<<8) | readbyte(3);
X }
X
X else
X inchecksum = readbyte(3); /* get simple 8-bit checksum */
X
X if (inchecksum == checksum) /* good checksum, hence good filename */
X {
X xmdebug("checksum ok");
X strcpy(name, (char *)buff);
X expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
X BATCH = TRUE;
X YMDMBAT = TRUE;
X if (strlen(name) == 0) /* check for no more files */
X {
X flushin(); /* flush input */
X sendbyte(ACK); /* ACK the packet */
X logit("YMODEM Batch Receive Complete\n");
X tlogit("YMODEM Batch Receive Complete\n");
X return (FALSE);
X }
X unixify(name); /* make filename canonical */
X
X /* read rest of YMODEM header */
X p = (char *)buff + strlen((char *)buff) + 1;
X if (DEBUG)
X fprintf(LOGFP, "DEBUG: header info: %s\n", p);
X sscanf(p, "%ld%lo%o%o%d%ld%d",
X &filelength, &modtime, &filemode,
X &serial, &filesleft, &totalleft,
X &yfiletype);
X logitarg("YMODEM file name: %s\n", name);
X tlogitarg("YMODEM file name: %s\n", name);
X fileread = 0l;
X if (filelength)
X {
X CHECKLENGTH = TRUE;
X logitarg("YMODEM file size: %ld\n", filelength);
X tlogitarg("YMODEM file size: %ld\n", filelength);
X }
X else if (expsect)
X logitarg("YMODEM estimated file length %d sectors\n", expsect);
X if (modtime)
X {
X logitarg("YMODEM file date: %s", ctime((time_t *)&modtime));
X }
X if (filemode)
X logitarg("YMODEM file mode: %o\n", filemode);
X
X if (filesleft)
X {
X logitarg("YMODEM %d file(s) left to receive ", filesleft);
X logitarg("containing %ld bytes\n", totalleft);
X tlogitarg("YMODEM %d file(s) left to receive ", filesleft);
X tlogitarg("containing %ld bytes\n", totalleft);
X }
X if (serial)
X logitarg("YMODEM sender's serial number: %d\n", serial);
X if (yfiletype)
X logitarg("YMODEM file type %d\n", yfiletype);
X
X openflag = TRUE; /* open the file for writing */
X if ((fd = creat(name, CREATMODE)) < 0)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X error("Can't create file for receive", TRUE);
X }
X if (!YMODEMG)
X {
X flushin(); /* flush the input stream */
X sendbyte(ACK); /* ACK the filename packet */
X }
X /* do initial handshake to start file transfer */
X if (YMODEMG)
X sendbyte(GCHR);
X else if (CRCMODE)
X {
X sendbyte(CRCCHR);
X if (LONGPACK)
X sendbyte(KCHR);
X }
X else
X sendbyte(NAK);
X firstwait = WAITFIRST; /* reset waiting time */
X }
X
X else /* bad filename checksum */
X {
X logit("checksum error on filename sector\n");
X tlogit("checksum error on filename sector\n");
X errorflag = TRUE;
X if (YMODEMG)
X fatalerror = TRUE;
X }
X }
X else
X {
X logit("Timeout while reading filename packet\n");
X tlogit("Timeout while reading filename packet\n");
X errorflag = TRUE;
X if (YMODEMG)
X fatalerror = TRUE;
X }
X }
X
X else if (sectcurr == sectnum) /* duplicate sector? */
X {
X logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X tlogitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X if (YMODEMG)
X {
X errorflag = TRUE;
X fatalerror = TRUE;
X }
X else
X {
X flushin(); /* REALLY flush input */
X while(readbyte(1) != TIMEOUT)
X ;
X sendbyte(ACK);
X }
X }
X else /* no, real phase error */
X {
X logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
X tlogitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
X errorflag = TRUE;
X fatalerror = TRUE;
X }
X }
X }
X
X else /* bad packet number checksum */
X {
X logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
X tlogitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
X errorflag = TRUE;
X if (YMODEMG)
X fatalerror = TRUE;
X }
X
X } /* END reading packet loop */
X
X if (errorflag && !fatalerror && recvsectcnt != 0) /* Handle errors */
X {
X errors++;
X
X if (errors >= ERRORMAX) /* over error limit? */
X fatalerror = TRUE;
X else /* flush input and NAK the packet */
X {
X flushin();
X while (readbyte(2) != TIMEOUT) /* wait for line to settle */
X ;
X sendbyte(NAK);
X }
X }
X
X if (recvsectcnt == 0 && errorflag && !fatalerror && firstchar != EOT) /* handle startup handshake */
X {
X sterrors++;
X
X if (sterrors >= STERRORMAX)
X fatalerror = TRUE;
X
X else if (CRCMODE && MDM7BAT && !BATCH)
X sendbyte(NAK);
X
X else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X {
X CRCMODE = FALSE;
X logit("Sender not accepting CRC request, changing to checksum\n");
X tlogit("Sender not accepting CRC request, changing to checksum\n");
X sendbyte(NAK);
X }
X
X else if (!CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X {
X CRCMODE = TRUE;
X logit("Sender not accepting checksum request, changing to CRC\n");
X tlogit("Sender not accepting checksum request, changing to CRC\n");
X sendbyte(CRCCHR);
X if (LONGPACK && !MDM7BAT)
X sendbyte(KCHR);
X }
X
X else if (YMODEMG)
X sendbyte(GCHR);
X
X else if (CRCMODE)
X {
X sendbyte(CRCCHR);
X if (LONGPACK && !MDM7BAT)
X sendbyte(KCHR);
X }
X
X else
X sendbyte(NAK);
X }
X}
Xwhile ((firstchar != EOT) && !fatalerror); /* end of MAIN Do-While */
X
Xif ((firstchar == EOT) && !fatalerror) /* normal exit? */
X{
X if (openflag) /* close the file */
X close(fd);
X sendbyte(ACK); /* ACK the EOT */
X logit("Receive Complete\n");
X tlogit("Receive Complete\n");
X if (LOGFLAG)
X prtime (recvsectcnt, time((time_t *) 0) - start, LOGFP);
X if (TIPFLAG)
X prtime (recvsectcnt, time((time_t *) 0) - start, stderr);
X
X if (openflag && modtime) /* set file modification time */
X {
X timep[0] = time((time_t *) 0);
X timep[1] = modtime;
X utime(name, timep);
X }
X
X if (BATCH) /* send appropriate return code */
X return(TRUE);
X else
X return(FALSE);
X}
Xelse /* no, error exit */
X{
X if (openflag)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X close(fd);
X unlink(name);
X flushin();
X while (readbyte(2) != TIMEOUT) /* wait for line to settle */
X ;
X error("ABORTED -- Too Many Errors -- Deleting File", TRUE);
X }
X else if (recvsectcnt != 0)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X flushin();
X while (readbyte(2) != TIMEOUT) /* wait for line to settle */
X ;
X error("ABORTED -- Too Many Errors", TRUE);
X }
X else
X {
X flushin();
X while (readbyte(2) != TIMEOUT) /* wait for line to settle */
X ;
X error("ABORTED -- Remote system is not responding", TRUE);
X }
X
X}
X
Xreturn(FALSE);
X}
END_OF_FILE
if test 17709 -ne `wc -c <'pf-bootstrap-v1.1a/xmodem-3.9/receive.c'`; then
echo shar: \"'pf-bootstrap-v1.1a/xmodem-3.9/receive.c'\" unpacked with wrong size!
fi
# end of 'pf-bootstrap-v1.1a/xmodem-3.9/receive.c'
fi
echo shar: End of archive 7 \(of 9\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 9 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0