[net.sources] TU58 emulator, part 1 of 2

dan@rna.UUCP (Dan Ts'o) (07/25/85)

#

#	Finally. This part 1 of the TU58 emulator program mentioned on the
#	USENET about a month ago. Due to great demand, we are posting it.
#	You are free to use it except for commercial advantage (don't sell
#	it). Its basic usage is:
#
#		tu58 -s9600 serial_device tu58_filesystem0 [filesystem1] &
#
#	where "serial_device" is a tty line the other end of which will look
#	like a TU58 and the two filesystems are UNIX files which contain the
#	image of the TU58 drives to be emulated. Of course /etc/getty must
#	not be running on the tty line.
#
#	This program has been extensively used to provide TU58-like mass
#	storage for otherwise standalone DEC PDP-11/23's and 11/03's. It has
#	been used to provide bootable RT-11 filesystems, but there is no
#	reason why any TU58 filesystem couldn't be emulated (e.g. 11/750
#	diagnostic supervisor).
#
#	On a VAX 11/750 running 4.2BSD, the character handling is not quite
#	fast enough to handle writes into the emulator. Writes do work at
#	2400 and 4800 baud. It is still much faster than a real TU58 for
#	most applications since the average access time on a real TU58 is
#	30 seconds. It boots RT-11 in less than 30 seconds - a real TU58 takes
#	more than 5 minutes
#
#	If anyone needs a bootable RT-11 TU58 image (and has an RT-11 license)
#	we could probably send you one. They run about 256kbytes each.
#
#	I have included the rtpip utility which we use to write these RT-11
#	filesystems on the UNIX host side.
#
#	Areas for improvement. If anyone knows about or make mods towards
#	these items, please feed it back to us.
#
#		- A real TU58 contains 512blocks of 512bytes. Is this limited
#		by the TU58 protocol. Could the emulator meanfully support
#		larger filesystems ? It looks like there is 16bit block #s.
#
#		- A real TU58 has one or two drives. Can the protocol support
#		more than two drives ? It looks like there is 8bit unit #s.
#
#		- Would a stripped down tty line discipline (e.g. the Purdue
#		8bit line discipline) allow the TU58 to be more efficient
#		and possibly allow writes at 9600baud ?
#
#		- Does anyone have a TU58 UNIX driver for the (absolutely)
#		crazy idea of running UNIX off the emulator ? (or maybe
#		XINU)
#
#		- It sometimes crashes, especially after long (hours, days)
#		of idle time, probably due to noise/garbage on the line.
#		It could probably use improvements in this area. A quick
#		hack which we'll probably add is to restart (either re-exec()
#		or longjmp()) itself when it gets a e.g. SIGTERM or SIGHUP
#		to allow easy restarting in case it hangs.
#
#		- It should work for VAX 750 diags. Let us know if it does.
#
#	Let us know how it works out.
#
#					Cheers,
#					Dan Ts'o
#					Dept. Neurobiology
#					Rockefeller Univ.
#					1230 York Ave.
#					NY, NY 10021
#					212-570-7671
#					...cmcl2!rna!dan
#					rna!dan@cmcl2.arpa

echo ./README
sed 's/^X//' > ./README << 'All work and no play makes Jack a dull boy'
XThis is the TU58 emulation program written at Rockefeller Univ., Dept. of
XNeurobiology. We copyright (C) it and permit its use provided it is not
Xsold to others.
X
XIt has been tested and extensively used as a mass storage replacement for
XDEC LSI 11/23's and 11/03's running RT-11 at 9600 baud. On a VAX 11/750
Xrunning 4.2BSD, the character handling is not quite fast enough to permit
Xreliable writes at 9600 baud. I believe writes work fine at 2400 and 4800
Xbaud. Given a faster host machine or a strip-down tty driver, 9600 baud and
Xpossibly above should be feasible.
X
XAs it is, it is much faster in booting up RT-11 than a real TU58 - it can
Xboot RT-11 in less than 30 seconds, a real TU58 takes more than five minutes.
XThis speed difference is obviously because the real TU58 has a average access
Xtime of 30 seconds whereas the access time for the emulator is just the
Xprotocol overhead plus the UNIX filesystem lacency.
X
XIt should be possible, though we have yet to try it, to replace the diagnostic
XTU58 on the VAX 11/750 with a serial line to this program running on another
Xmachine. This arrangement should speed up 11/750 diagnostics. If someone is
Xreally interested in this but doesn't have a real TU58 to dump the 11/750
Xdiagnostics to a UNIX file, we might do that.
X
XThe TU58 emulator uses a non-blocking read() call which is possible under 4.2BSD
Xand implementable using a call like the old RAND empty(), which checks if
Xa read() on a tty would block (is the read queue empty ?). If you don't have
X4.2bsd, most versions of UNIX support some form of this functionality.
X	
XThe command to use to mount filesystems is:
X
X	tu58 [-flags] serial_device filesys1 [filesys2] 2> /dev/null &
X
XTo create a bootable 'tu58' tape it is easiest to copy an RT-11
Xbootable filesystem and add the your own files with rtpip.
X
XIf you need a sample RT-11 TU58 bootable filesystem and you have an RT-11
Xlicense, I could send you one (they are usually 256kbytes of binary).
X
XWe please report bug fixes and enhancements to us, we would like to track
Xthis program.
X
XSorry if the documentation is not up to snuff.
X
X					Cheers,
X					Dan Ts'o
X					Dept. Neurobiology
X					Rockefeller Univ.
X					1230 York Ave.
X					NY, NY 10021
X					212-570-7671
X					...cmcl2!rna!dan
X					rna!dan@cmcl2.arpa
All work and no play makes Jack a dull boy
echo ./checksum.c
sed 's/^X//' > ./checksum.c << 'All work and no play makes Jack a dull boy'
X#include "tu58.h"
X
Xu_short docksum(header,mbuf)
Xstruct packet *header;
Xu_char *mbuf;
X{
X	register int cnt;
X	register u_char *cp;
X	register u_short psum;
X	unsigned long sum;
X
X	cp = mbuf;
X	cnt = 0xff & header->pk_mcount;
X	sum = 0xffff&(header->pk_mcount<<8) + (0xff&header->pk_flag);
X
X	while( --cnt >= 0 ) {			/* have at least one */
X		psum = 0xff&(*cp++);
X		if( --cnt >= 0 ) 		/* have at least two */
X			psum += 0xffff&((*cp++)<<8);
X		sum += psum + ( (long)psum + (0xffff&sum) > 0xffff ? 1 : 0 );
X	}
X
X	return (u_short)sum;
X}
All work and no play makes Jack a dull boy
echo ./debug.c
sed 's/^X//' > ./debug.c << 'All work and no play makes Jack a dull boy'
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X
X#define DBDIR	"/usr/local/tu"
X
XFILE *dbfd;
X
Xchar *ctime();
X
X/* open a debug info file.  Use the major and minor dev num of the
X output serial port so that subsequent invocations of the tu58 emulator
X (for a given line) share a file name, and so that multiple
X simultaneous invocations don't share a file name */
X
Xdb_open(fd)
X{
Xchar name[50];
Xstruct stat buf;
Xlong t;
X
Xfstat(fd,&buf);
Xsprintf(name,"%s/tu58debug.%d.%d",DBDIR,major(buf.st_rdev),minor(buf.st_rdev));
Xdbfd = fopen(name,"w");
Xif (dbfd == NULL)
X	fprintf(stderr,"Cannot open %s for debug output\n",name);
Xtime(&t);
Xfprintf(dbfd,"Tu58 starting at ");
Xfprintf(dbfd,ctime(&t));
Xfflush(dbfd);
X}
X
Xdb_close()
X{
Xlong t;
X
Xtime(&t);
Xfprintf(dbfd,"Tu58 finished at ");
Xfprintf(dbfd,ctime(&t));
Xfflush(dbfd);
Xfclose(dbfd);
X}
All work and no play makes Jack a dull boy
echo ./debug.h
sed 's/^X//' > ./debug.h << 'All work and no play makes Jack a dull boy'
X#ifdef DEBUG
X
Xextern FILE *dbfd;
X#undef stderr
X#define stderr dbfd
X#define debugs(st) \
X	do { fprintf(dbfd,"%s\n",(st)); fflush(dbfd); } while (0)
X#define debugd(st,dec) \
X	do { fprintf(dbfd,"%s %d\n",(st),(dec)); fflush(dbfd); } while (0)
X#define debugo(st,oct) \
X	do { fprintf(dbfd,"%s 0%o\n",(st),(oct)); fflush(dbfd); } while (0)
X#define debugx(st,hex) \
X	do { fprintf(dbfd,"%s 0x%x\n",(st),(hex)); fflush(dbfd); } while (0)
X
X#else
X
X#define debugs(st);
X#define debugd(st,dec); 
X#define debugo(st,oct); 
X#define debugx(st,hex); 
X
X#endif
All work and no play makes Jack a dull boy
echo ./empty.c
sed 's/^X//' > ./empty.c << 'All work and no play makes Jack a dull boy'
X#ifdef NEEDEMPTY
X#ifdef VENIX
X
X/*
X * VENIX empty call - check if tty has any characters in input queue
X */
X
Xempty(fd)
Xint fd;
X{
X	struct sgttyb sg;
X
X	ioctl(fd, TIOCQCNT, &sg);
X	return (sg.sg_ispeed == 0);
X}
X
Xfull(fd)
Xint fd;
X{
X	struct sgttyb sg;
X
X	ioctl(fd, TIOCQCNT, &sg);
X	return sg.sg_ispeed;
X}
X
X#else
X#ifdef	BSD
X
X/*
X * empty(fildes) - For BSD systems
X * Is the tty or pipe empty ? (Will a read() block)
X */
X
Xempty(fd)
Xint fd;
X{
X	long nchar;
X	int f;
X
X	f = ioctl(fd, FIONREAD, &nchar);
X	if (f == -1)
X		return -1;
X	if (nchar)
X		return 0;
X	return 1;
X}
X#else
X	/* Need to write empty() for USG or rewrite using MINTIME */
X#endif
X#endif
X#endif
All work and no play makes Jack a dull boy
echo ./file.c
sed 's/^X//' > ./file.c << 'All work and no play makes Jack a dull boy'
X#include "tu58.h"
X#include "rtdir.h"
X#include <stdio.h>
X#define FBLOCKIO
X#include "debug.h"
X
X int file[NTU58];			/* file descriptors */
X char *fname[NTU58];			/* file names */
X int fflags[NTU58];
X int fmode[NTU58];
X int fpt;				/* number of active file descriptors */
X char ronly[NTU58];			/* write permission */
X char cflag[NTU58];			/* create file */
X char iflag[NTU58];			/* init RT-11 Dir */
X
X#ifdef FBLOCKIO
X#define FSIZE 512			/* must be integral number of DATALEN */
X char fobuf[FSIZE];			
X char fibuf[FSIZE];			
X char *wpt;				/* pointer to data quanta. len DATALEN*/
X char *rpt;
X#endif
X
X#define fileck(dev)	( dev <= NTU58 || file[dev] != -1 )
X
Xfileinit()
X{
X	register int i;
X
X	for (i = 0; i < NTU58; i++) {
X		file[i] = -1;
X		ronly[i] = 0;
X		cflag[i] = 0;
X		iflag[i] = 0;
X	}
X	fpt = 0;
X#ifdef FBLOCKIO
X	fwclear();	frclear();
X#endif
X}
X
Xreadonly(index)
X{
X	setoption(index, ronly);
X}
X
Xcreateflag(index)
X{
X	setoption(index, cflag);
X}
X
Xinitrtflag(index)
X{
X	setoption(index, iflag);
X}
X
Xsetoption(index, option)
Xregister char *index; register char *option;
X{
X	register int i;
X
X	if (index[2] == 0)
X		for (i = 0; i < NTU58; i++)
X			option[i] = 1;
X	else {
X		i = index[2] - '0';
X		if (0 <= i && i < NTU58)
X			option[i] = 1;
X		else
X			fprintf(stderr,"Bad option: %s", index);
X	}
X}
X
Xfileopen(name,flags,mode)
Xchar *name; int flags, mode;
X{
X	register int fd;
X
X	if ( ronly[fpt] )
X		fd = open(name, 0);
X	else {
X		fd = open(name, flags, mode);
X		if( flags > 0 && fd < 0 ) {
X			fd = open(name, 0);
X			if( fd >= 0 )
X				ronly[fpt] = 1;
X		}
X	}
X
X	if (fd < 0 && cflag[fpt])
X		fd = creat(name, mode);
X
X	if (fd < 0) {
X		fprintf(stderr, "Cannot open or create: %s", name);
X		exit(-1);
X	}
X
X	file[fpt] = fd;
X	fname[fpt] = name;
X	fflags[fpt] = flags;
X	fmode[fpt] = mode;
X
X	if (iflag[fpt])
X		frt11_init(file[fpt], name);
X
X	fpt++;
X	return 1;
X}
X
Xfrt11_init(fd, name)
Xint fd; char *name;
X{
X	char buf[512];
X	register int i;
X	register char *cp;
X
X	fprintf(stderr, "tu58: Initialize RT-11 directory on %s ?", name);
X	if (gets(buf, 80) == NULL || !(*buf == 'y' || *buf == 'Y')) 
X			return -1;
X
X	for( cp=buf, i=0; i<512; i++)
X		*cp++=0;
X
X	for( i=0; i<RTFS; i++)
X		if( 512 != write(fd, buf, 512)) 
X			goto quit;
X	lseek(fd, RTBBPOS, 0);
X	if( RTBB != write(fd, (char *)bootbuf, RTBB))
X		goto quit;
X	lseek(fd, RTDIRPOS, 0);
X	if( RTDIR != write(fd, (char *)dirbuf, RTDIR))
X		goto quit;
X	lseek(fd, RTDIR2POS, 0);
X	if( RTDIR2 != write(fd, (char *)dir2buf, RTDIR2))
X		goto quit;
X	return(1);
X		
Xquit:	fprintf(stderr, "frt11_init: Can't\n");
X	return -1;
X}
X
Xfposition(dd,mod,block)			/* seek file (tape) position */
Xint dd, mod, block;
X{
X	if( !fileck(dd) ) {
X		fprintf( stderr, "position on bad unit\n");
X		sendend( TUOP_END, TUE_BADU, 0, 0);
X		return 0;
X	}
X	if( mod & TUMD_128 ) {
X		if(   lseek( file[dd], block*128, 0) < 0   ) {
X			fprintf( stderr, "position bad \n");
X			sendend( TUOP_END, TUE_BADB, 0, 0);
X			return 0;
X		}
X	}
X	if( block == 6 )
X		fupdate(dd);		/* allow for rtpip insert */
X	if(  lseek( file[dd], block*512, 0) < 0   ) {
X		fprintf( stderr, " position bad \n");
X		sendend( TUOP_END, TUE_BADB, 0, 0);
X		return 0;
X	}
X	debugo("position",block);
X	debugo("mod",mod);
X	return 1;
X}
X
X#ifdef FBLOCKIO
Xchar *fread(dd)			/* get pointer to data from file */
Xint dd;
X{
X	int i;
X		char *cp; 
X	rpt += DATALEN;
X	if( rpt >= &fibuf[FSIZE]) {
X		if( FSIZE != (i=read(file[dd],fibuf,FSIZE)) )
X			return 0;
X		rpt = fibuf; 
X	}
X	return rpt;
X}
X
Xchar *fwrite(dd)		/* get pointer to write buf */
Xint dd;
X{
X	register char *cp;
X
X	if(wpt == &fobuf[FSIZE - DATALEN]) 
X		if( !fwflush(dd) )
X			return 0;
X
X	if(wpt)
X		wpt += DATALEN;
X	else
X		wpt = fobuf;
X
X	return wpt;
X}
X
Xfwflush(dd)			/* flush write buf to file. return 1 or 0 */
Xint dd;
X{
X		register char *cp;
X
X		for(cp = wpt + DATALEN; cp < &fobuf[FSIZE]; cp++)
X			*cp = 0;
X		wpt = 0;
X		if( FSIZE != write(file[dd],fobuf,FSIZE) )
X			return 0;
X		return 1;
X}
X
Xfwclear()			/* init write buf */
X{
X	wpt = 0;
X}
X
Xfrclear()			/* init read buf */
X{
X	rpt = &fibuf[FSIZE];
X}
X#endif
X
Xfupdate(dev)
Xint dev;
X{
X	close(file[dev]);
X	fileopen(fname[dev],fflags[dev],fmode[dev]);
X}
All work and no play makes Jack a dull boy
echo ./io.c
sed 's/^X//' > ./io.c << 'All work and no play makes Jack a dull boy'
X#include "tu58.h"
X#include <stdio.h>
X#ifndef	EMPTY
X#include <fcntl.h>
X#endif
X#include "debug.h"
X
X extern int r_device, w_device;
X extern int errno;
X
X char wbuf[512];
X int wcnt = 0;
X char rbuf[512];
X int rcnt = 0;
X char *rptr;
X
Xcpeak()
X{
X#ifndef	EMPTY
X	fcntl( r_device, F_SETFL, FNDELAY | fcntl(r_device,F_GETFL,0) );
X	rcnt = read(r_device, rbuf, sizeof rbuf);
X	fcntl( r_device, F_SETFL, ~FNDELAY & fcntl(r_device,F_GETFL,0) );
X#else
X	if (empty(r_device))
X		return -1;
X	rcnt = read(r_device, rbuf, sizeof rbuf);
X#endif
X	if( rcnt < 0 ) 
X		return -1;
X	rptr = rbuf;
X	return (*rptr&0377);
X}
X
Xcget()				/* return char from rbuf */
X{
X	register char *cp;
X	register int cnt;
X
X	if (rcnt <= 0) {
X		if( (rcnt = read(r_device, rbuf, sizeof rbuf)) < 0) {
X			debugd("Read file: err %d\n",errno);
X			return -1;
X			}
X		rptr = rbuf;
X	}
X	rcnt--;
X	return 0377&(*rptr++);
X}
X
Xcflush()
X{
X		if (wcnt && write(w_device, wbuf, wcnt) != wcnt)
X			fprintf(stderr, "Packet write error\n");
X		wcnt = 0;
X}
X
Xcput(c)			/* put char on wbuf */
Xregister char c;
X{
X	static char *wpnt;
X	static char *wptr;
X
X	if (wcnt >= sizeof wbuf)
X		cflush();
X	if (wcnt == 0)
X		wptr = wbuf;
X	wcnt++;
X	*wptr++ = c;
X}
X
Xsendpacket(header,mbuf)
Xu_char *mbuf;
Xstruct packet *header;
X{
X	register int cnt;
X	register u_char *cp;
X	u_short docksum(), sum;
X
X	cput(header->pk_flag);
X	cput(header->pk_mcount);
X	for( cp = mbuf, cnt = 0xff & header->pk_mcount; cnt; cnt--, cp++)
X		cput(*cp);
X	sum = docksum(header,mbuf);
X	debugx("chsum",sum);
X	cput(0377&sum);
X	cput(0377&sum>>8);
X	cflush();
X}
X
Xgetpacket(header,mbuf)	/* get message part of packet. already got header */
Xu_char *mbuf;
Xstruct packet *header;
X{
X	register int cnt;
X	register u_char *cp;
X	u_short docksum();
X
X	for(cnt = 0xff & header->pk_mcount, cp = mbuf; cnt; cnt--)
X		*cp++ = 0377&cget();
X	cnt = 0377&cget();		/* checksum */
X	cnt += cget()<<8;
X	return( (u_short)cnt == docksum(header, mbuf) );
X}
X
Xclearcbuf()
X{
X	rcnt = wcnt = 0;
X}
X
Xbootio(fd)			/* read of boot is not in packet format */
Xint fd;
X{
X	int count;
X
X	if( lseek(fd, 0, 0) < 0)
X		fprintf(stderr,"Boot seek error\n");
X	if( (count = read(fd, wbuf, 512)) != 512 )
X		fprintf(stderr,"Boot read error\n");
X	if( 512 != write(w_device, wbuf, 512) )
X		fprintf(stderr,"Boot write error\n");
X}
All work and no play makes Jack a dull boy
echo ./main.c
sed 's/^X//' > ./main.c << 'All work and no play makes Jack a dull boy'
X/*
X * tu58 - Emulate a TU58 over a serial line
X *
X *	Copyright (C) Rockefeller Univ. Dept. of Neurobiology
X *
X * Usage: tu58 [-options] serial_device file0 [file1]
X * Options:	-s####	set line speed
X *		-r[#]	readonly drive
X *		-c[#]	create files
X *		-i[#]	initialize RT-11 directory
X */
X
X#ifdef	PWBTTY
X
X#include <sys/sgtty.h>
X#define	sg_ispeed	sg_ispd
X#define	sg_ospeed	sg_ospd
X#define	sg_flags	sg_flag
X#define	sgttyb		sgtty
X
X#else
X
X#include <sgtty.h>
X
X#endif
X
X#include "tu58.h"
X#include <stdio.h>
X#include "debug.h"
X
X int r_device = 0;			/* Default to stdin */
X int w_device = 1;			/* Default to stdout */
X int speed = B2400;			/* Default line speed */
X struct sgttyb osg[2];
X
Xmain(c, v)
Xint c; char **v;
X{
X	register int i;
X	register char *s;
X
X	/*
X	 * init
X	 */
X
X	fileinit();
X
X	/*
X	 * parse command line for flags
X	 */
X
X	while (c > 1 && *(s = v[1]) == '-' && s[1]) {
X		v++;
X		c--;
X		switch (s[1]) {
X		case 's':
X			i = baud(atoi(&s[2]));
X			if (i < 0)
X				error("Bad speed: %s", &s[2]);
X			else
X				speed = i;
X			break;
X		case 'r':
X			readonly(s);
X			break;
X		case 'c':
X			createflag(s);
X			break;
X		case 'i':
X			initrtflag(s);
X			break;
X		default:
X			error("Bad option: %s\n", s);
X		}
X	}
X
X	/* 
X	 * Open the files
X	 */
X
X	if (c < 3 || c > (2+NTU58))
X		error("Usage: tu58 [-options] serial_device file0 [file1]");
X
X	if (strcmp("-", v[1]))  {
X		root();
X		if( (r_device = w_device = open(v[1], 2)) < 0 )
X			error("No serial line");
X		notroot();
X	}
X
X	c -= 2;
X	v += 2;
X	for (i = 0; i < c; i++) 
X		if( fileopen(v[i], 2, 0644) < 0 )
X			error("Can't open %s nohow\n",v[i]);
X
X#ifdef DEBUG
X	/*
X	 * open debug file
X	 */
X	db_open(r_device);
X#endif
X	
X	/*
X	 * setup serial lines and play tu58
X	 */
X
X	init_device(r_device);
X	if (r_device != w_device)
X		init_device(w_device);
X
X	tu58();
X
X	restore_device(r_device);
X	if (r_device != w_device)
X		restore_device(w_device);
X#ifdef DEBUG
X	db_close();
X#endif
X}
X
X/*
X * set and reset serial lines
X */
X
Xinit_device(fd)
Xint fd;
X{
X	static int sgx = 0;
X	struct sgttyb sg;
X
X	if (gtty(fd, &osg[sgx]))
X		error("Bad serial device");
X	sg = osg[sgx];
X	if (speed >= 0)
X		sg.sg_ospeed = sg.sg_ispeed = speed;
X	sg.sg_flags &= ~(CBREAK|ECHO|XTABS);
X	sg.sg_flags |= (RAW);
X	stty(fd, &sg);
X	sgx++;
X}
X
Xrestore_device(fd)
Xint fd;
X{
X	static int sgx = 0;
X
X	stty(fd, &osg[sgx++]);
X}
X
X int baud_map[] = {	19200,	EXTA,	9600,	B9600,	4800,	B4800,
X			2400,	B2400,	1200,	B1200,	600,	B600,
X			300,	B300,	200,	B200,	150,	B150,
X			110,	B110,	75,	B75,	50,	B50,
X			0,	B0,	-1 };
X
Xbaud(spd)
Xregister int spd;
X{
X	register int *p;
X
X	for (p = baud_map; *p != -1; p++)
X		if (*p++ == spd)
X			return *p;
X	return -1;
X}
X
Xerror(a, b, c, d, e)
Xchar *a, *b, *c, *d, *e;
X{
X	fprintf(stderr, "tu58: ");
X	fprintf(stderr, a, b, c, d, e);
X	fprintf(stderr, "\n");
X	exit(-1);
X}
X
Xint uid, euid;
X
Xroot()
X{
X	euid = geteuid();
X	uid = getuid();
X	setreuid(euid,-1);
X}
X
Xnotroot()
X{
X	setreuid(uid,euid);
X}
All work and no play makes Jack a dull boy
echo ./makefile
sed 's/^X//' > ./makefile << 'All work and no play makes Jack a dull boy'
XCFLAGS= -O -c -DDEBUG
X# CFLAGS= -O -c
X
Xtu58:   main.o tu58.o io.o checksum.o file.o tu58.h debug.o
X	cc -o tu58 main.o tu58.o io.o checksum.o file.o  debug.o
X	chgrp micro tu58
X	chmod 4755 tu58
X	rm err
Xchecksum.o: tu58.h
X	cc $(CFLAGS) checksum.c 2>err
X	echo 
Xio.o:	tu58.h  debug.h
X	cc $(CFLAGS) io.c 2>err
X	echo 
Xmain.o: tu58.h debug.h
X	cc $(CFLAGS) main.c 2>err
X	echo 
Xtu58.o: tu58.h debug.h
X	cc $(CFLAGS) tu58.c 2>err
X	echo 
Xfile.o:	file.c tu58.h debug.h rtdir.h
X	cc $(CFLAGS) file.c 2>err
X	echo 
Xdebug.o: debug.c
X	cc $(CFLAGS) debug.c 2>err
X	echo 
All work and no play makes Jack a dull boy
echo ./rtdir.h
sed 's/^X//' > ./rtdir.h << 'All work and no play makes Jack a dull boy'
X#define RTBB 80
X#define RTBBPOS 0
Xshort bootbuf[40] = {
X0000240, 0000005, 0000404, 0000000, 0000000, 0041420, 0116020, 0000400,
X0004067, 0000044, 0000015, 0000000, 0005000, 0041077, 0047517, 0026524,
X0026525, 0067516, 0061040, 0067557, 0020164, 0067157, 0073040, 0066157,
X0066565, 0006545, 0005012, 0000200, 0105737, 0177564, 0100375, 0112037,
X0177566, 0100372, 0000777, 0000000, 0000000, 0000000, 0000000, 0000000
X};
X
X#define RTDIR 48
X#define RTDIRPOS 01720
Xshort dirbuf[24] = {
X0000000, 0000001, 0000006, 0107123, 0052122, 0030461, 0020101, 0020040,
X0020040, 0020040, 0020040, 0020040, 0020040, 0020040, 0020040, 0020040,
X0042504, 0051103, 0030524, 0040461, 0020040, 0020040, 0000000, 0000000
X};
X
X#define RTDIR2 48
X#define RTDIR2POS 06000
Xshort dir2buf[24] = {
X0000001, 0000000, 0000001, 0000000, 0000010, 0001000, 0000325, 0063471,
X0023364, 0000770, 0000000, 0024514, 0004000, 0000000, 0000000, 0000000,
X0000000, 0000000, 0000000, 0000000, 0000000, 0000000, 0000000, 0000000
X};
X
X#define RTFS 012
All work and no play makes Jack a dull boy
echo ./rtpip/
mkdir ./rtpip
echo ./rtpip/rtclose.2
sed 's/^X//' > ./rtpip/rtclose.2 << 'All work and no play makes Jack a dull boy'
X.th RTCLOSE II 1/1/76
X.sh NAME
Xrtclose *- close RT-11 file
X.sh SYNOPSIS
X.br
X.ft B
Xrtclose (fildes)
X.br
X.ft R
X.sh DESCRIPTION
XGiven the file descriptor returned from
X.it rtopen,
X.it rtclose
Xcloses the associated RT-11 file.
X.sh FILES
XIn Nymegen,
X.it rtclose
Xis in the C-library (member name RTUN.O).
X.sh "SEE ALSO"
Xclose(II), rtpip(I), rtmount(II), rtumount(II), rtopen(II), 
Xrtread(II), rtwrite(II), rtdelete(II)
X.sh AUTHOR
XT. Forgacs, Informatics Dept. Nymegen Univ. the Netherlands.
X.sh DIAGNOSTICS
XFrom C, a -1 value gets returned on error. A 0 value
Xindicates success.
X.sh GLOBALS
XDo not use the following external names:
X.S3
Xrttabl, rtdev, rtcurse, rtdirta, rtbuffe,
Xrtwrop, rtoldfl, rtsegfu, rtextb, rtconvr,
Xrtgetna, rtphio, rtpseek, rtheade, rtinitd,
Xrtserdi, rtconde, rtucond, rtadjus.
X.sh BUGS
All work and no play makes Jack a dull boy
echo ./rtpip/rtdelete.2
sed 's/^X//' > ./rtpip/rtdelete.2 << 'All work and no play makes Jack a dull boy'
X.th RTDELETE II 1/1/76
X.sh NAME
Xrtdelete *- delete RT-11 file
X.sh SYNOPSIS
X.br
X.ft B
Xrtdelete (name)
X.br
Xchar *name;
X.br
X.ft R
X.sh DESCRIPTION
X.it Rtdelete
Xdeletes the RT-11 file
X.it name.
X.it Name
Xis the address of a string of ASCII characters representing
Xa file name according to RT-11 conventions.
X.sh FILES
XIn Nymegen,
X.it rtdelete
Xis in the C-library (member name RTUN.O).
X.sh "SEE ALSO"
Xrtpip(I), rtmount(II), rtumount(II), rtopen(II), rtclose(II),
Xrtread(II), rtwrite(II)
X.sh AUTHOR
XT. Forgacs, Informatics Dept. Nymegen Univ. the Netherlands.
X.sh DIAGNOSTICS
XFrom C, a -1 value is returned if the delete fails, e.g.
Xthere exists no file called
X.it name.
XA 0 value indicates success.
X.sh GLOBALS
XDo not use the following external names:
X.S3
Xrttabl, rtdev, rtcurse, rtdirta, rtbuffe,
Xrtwrop, rtoldfl, rtsegfu, rtextb, rtconvr,
Xrtgetna, rtphio, rtpseek, rtheade, rtinitd,
Xrtserdi, rtconde, rtucond, rtadjus.
X.sh BUGS
XThere are no routines provided to do
Xcompacting or other garbage collection
Xon the RT-11 device.
All work and no play makes Jack a dull boy
echo ./rtpip/rtmount.2
sed 's/^X//' > ./rtpip/rtmount.2 << 'All work and no play makes Jack a dull boy'
X.th RTMOUNT II 1/1/76
X.sh NAME
Xrtmount *- mount RT-11 file structured device
X.sh SYNOPSIS
X.br
X.ft B
Xrtmount (special, rwflag)
X.br
Xchar *special;
X.br
X.ft R
X.sh DESCRIPTION
X.s3
X.it Rtmount
Xannounces to the system that a removable RT-11 file system
Xhas been mounted on the block structured special file
X.it special;
Xusually disk or DECtape.
X.s3
X.it Special
Xmust be a fully specified special file name, e.g /DEV/RK1.
X.s3
XThe
X.it rwflag
Xargument determines how the file system has to be mounted. If it is
X0, read is allowed; if it is 1, write is allowed, and if it is 2,
Xupdate (read and write) is allowed.
X.s3
XThe
Xreturned file descriptor of the mounted special file can be saved, but
Xin most cases the caller won't need it anymore.
X.sh FILES
XIn Nymegen,
X.it rtmount
Xis in the C-library (member name RTUN.O).
X.sh "SEE ALSO"
Xmount(II), rtpip(I),  rtumount(II), rtopen(II), rtclose(II),
Xrtread(II), rtwrite(II), rtdelete(II)
X.sh AUTHOR
XT. Forgacs, Informatics Dept. Nymegen Univ. the Netherlands.
X.sh DIAGNOSTICS
XFrom C, a -1 gets returned if mounting fails, e.g. if any RT-11 device
Xis already mounted. It is not possible to have more than one RT-11
Xdevice mounted at the same time.
X.sh GLOBALS
XDo not use the following external names:
X.S3
Xrttabl, rtdev, rtcurse, rtdirta, rtbuffe,
Xrtwrop, rtoldfl, rtsegfu, rtextb, rtconvr,
Xrtgetna, rtphio, rtpseek, rtheade, rtinitd,
Xrtserdi, rtconde, rtucond, rtadjus.
X.sh BUGS
XTables are kept in user storage.
XIf your process forks, they will
Xbe duplicated and no integrity is
Xensured anymore.
X.s3
XMultiple users mounting the same RT-11 device
Xmay expect lots of trouble.
All work and no play makes Jack a dull boy
echo ./rtpip/rtopen.2
sed 's/^X//' > ./rtpip/rtopen.2 << 'All work and no play makes Jack a dull boy'
X.th RTOPEN II 1/1/76
X.sh NAME
Xrtopen *- open RT-11 file for reading, writing or updating
X.sh SYNOPSIS
X.br
X.ft B
Xrtopen (name, mode)
X.br
Xchar *name;
X.br
X.ft R
X.sh DESCRIPTION
X.it Rtopen
Xopens the file
X.it name
Xfor reading (if
X.it mode
Xis 0), writing (if
X.it mode
Xis 1), or for updating, i.e. both reading and writing (if
X.it mode
Xis 2).
X.it Name
Xis the address of a string of ASCII characters
Xrepresenting a file name according to RT-11 conventions,
Xterminated by a null character.
X.s3
XThe returned file descriptor should be saved for subsequent
Xcalls to
X.it rtread,
X.it rtwrite
Xand
X.it rtclose.
X.s3
XAt most 4 files may be open at the same time,
Xof which only one for write or update.
X.sh FILES
XIn Nymegen,
X.it rtopen
Xis in the C-library (member name RTUN.O).
X.sh "SEE ALSO"
Xopen(II), rtpip(I), rtmount(II), rtumount(II), rtclose(II),
Xrtread(II), rtwrite(II), rtdelete(II)
X.sh AUTHOR
XT. Forgacs, Informatics Dept. Nymegen Univ. the Netherlands.
X.sh DIAGNOSTICS
XFrom C, a -1 value is returned on error.
X.sh GLOBALS
XDo not use the following external names:
X.S3
Xrttabl, rtdev, rtcurse, rtdirta, rtbuffe,
Xrtwrop, rtoldfl, rtsegfu, rtextb, rtconvr,
Xrtgetna, rtphio, rtpseek, rtheade, rtinitd,
Xrtserdi, rtconde, rtucond, rtadjus.
X.sh BUGS
X.it Rtopen
Xfor update is not very useful, since there is no (not yet)
X.it 'rtseek'
Xtype of operation to scan through a file.
XReading and writing both will be done
Xsequentially from the beginning of the file.
All work and no play makes Jack a dull boy
echo ./rtpip/rtpip.1
sed 's/^X//' > ./rtpip/rtpip.1 << 'All work and no play makes Jack a dull boy'
X.th RTPIP I 1/1/76
X.sh NAME
Xrtpip - manipulate RT-11 files from UNIX
X.sh SYNOPSIS
X.bd rtpip
Xkey [ file ... ]
X.sh DESCRIPTION
X.it key
Xconsists of two or three characters;
X.it file
Xis either a UNIX filename or an RT-11 filename.
XRT-11 filenames must be preceded immediately by a '+'
Xand UNIX filenames must have standard shell formats.
XThe meanings of the
X.it key
Xcharacters are:
X.s3
XThe first character is the function to be performed:
X.s3
X.bd r
Xcopy the file(s) to the RT-11 device.
X.s3
X.bd x
Xcopy the file(s) from the RT-11 device.
X.s3
X.bd l
Xlist the directory of the RT-11 device on the standard output.
XIf no filename is given, the entire directory will be listed.
X.s3
X.bd e
Xsame as l, but list only filenames with extension as given by
Xthe filename argument(s) (+EXT or +EXT.).
X.s3
X.bd n
Xsame as l, but list only filenames with name-part as given by
Xthe filename argument(s) (+.FILNAM or +FILNAM).
X.s3
X.bd f
Xlist, on the standard output, the sizes of all empty entries on the RT-11 device.
X.s3
X.bd d
Xdelete the RT-11 file(s).
X.s3
XThe second character identifies the RT-11 device:
X.s3
X.bd r
X/dev/rkx RK disk
X.s3
X.bd k
X/dev/rkx RK disk
X.s3
X.bd l
X/dev/rlx RL disk
X.s3
X.bd p
X/dev/rpx RP disk
X.s3
X.bd x
X/dev/rxx RX floppy disk
X.s3
X.bd h
X/dev/hkx RK06/07 disk
X.s3
X.bd f
Xdisk file dkx
X.s3
X.bd t
X/dev/tapx DECtape
X.s3
XIf none of the device keys are present, 'p' (RP disk) is assumed.
X.s3
XThe next key character, which must be present, specifies the device unit number:
X.s3
X.bd 0-9
X.sh "SEE ALSO"
Xrtmount(II), rtumount(II), rtopen(II), rtclose(II),
Xrtread(II), rtwrite(II), rtdelete(II).
X.sh AUTHOR
XT. Forgacs, Informatics Dept. Nymegen Univ. the Netherlands.
X.sh DIAGNOSTICS
XIf appropriate, rtpip tries to match pairs of UNIX and RT-11 filenames
Xin the sequence in which
Xthey occur in the
X.it file
Xargument. If there is a UNIX or RT-11 filename without
Xcorresponding filename from the other side, the same name is taken.
XIf the UNIX name contains slashes, all characters up to and including the last
Xslash are disregarded, and the result is taken as the RT-11 filename.
X.s1
X.sh BUGS
All work and no play makes Jack a dull boy
echo ./rtpip/rtpip.c
sed 's/^X//' > ./rtpip/rtpip.c << 'All work and no play makes Jack a dull boy'
X/*************************************************************/
X/*********                                                   */
X/**rtpip *                                                   */
X/*********                                                   */
X/*                                                           */
X/* status: 1 dec 75 version 1.                               */
X/*         jan 79, Modified by D. Ts'o                       */
X/*            to use rk0-9, tap0-9                           */
X/*            with a three-letter key                        */
X/*	   feb 82, Modified by D. Ts'o			     */
X/*	      to accept k,l,p as second letter for rk,rl,rp  */
X/*	      or f for file dk?				     */
X/*	   jan 85, Modified by J. Kourlas for vax.	     */
X/*	      compile with -DVAX flag.			     */
X/* author: t. forgacs univ of nijmegen comp. graphics        */
X/* compiler: c unix version 6                                */
X/* function: this is a program callable by shell in unix     */
X/*           resides on direct0ry /usr/bin                   */
X/*           it provides file shipping between rt11 and unix */
X/* calling sequence:                                         */
X/*        rtpip key filenames                                */
X/*         where                                             */
X/*           key is composed from 2 or 3 letters             */
X/*             the first letters specifies the function      */
X/*             the second one the rt11 device to be mounted  */
X/*             and the third, the unit number                */
X/*             the first letter                              */
X/*                  r    restore on rt11 device              */
X/*                  x    extract from rt11 device            */
X/*                  d    delete rt11 file                    */
X/*                  l    list directory                      */
X/*                     (if no filename specified , all)      */
X/*                  e list directory filenames specify       */
X/*                           only the ext part of the file   */
X/*                  n same as  e but namepart is specified   */
X/*                  f   list free spaces available           */
X/*            the second letter                              */
X/*                   r        rk disk default                */
X/*		     k,x,p,h,l rk, rx, rp, hk, rl	     */
X/*		     f	      disk file dkx		     */
X/*                   t        tap DEC-tape                   */
X/*                   and the third,                          */
X/*                   0...9    unit0...unit9                  */
X/*          filenames can be unix filenames as appr for      */
X/*           shell or rt11 filenames as appr for rt11        */
X/*           but the latter ones must be preceeded by'+'     */
X/* externals: rtun.c subroutines are called see unix sources */
X/**************************************************************/
X
X#ifdef VAX
X#define r_short short
X#else
X#define r_short int
X#endif
X
Xchar *device = "/dev/rkx";	/* ## dyt default device */
X
Xint rtarg[20],unarg[20];/*tables containing indecies of
X                          rt11 and unix filename arguments in argv*/
Xchar rtbuffer[1024];/*rtun internal buffer */
X
Xmain(argc,argv) int argc; char **argv;
X{
X  int devindex,rwf,i,j,k,l,m,n;
X  if( argc < 2 ) {
X    printf("Usage: %s abc [file ..]\n",argv[0]);
X    printf("	where\n");
X    printf("	a is a command:\n");
X    printf("		r restore on rt11 device\n");
X    printf("		x extract from rt11 device\n");
X    printf("		d delete rt11 file\n");
X    printf("		l list directory\n");
X    printf("		e list those with specific ext\n");
X    printf("		n list those with specific namepart\n");
X    printf("		f list free space\n");
X    printf("	b is rt11 device:\n");
X    printf("		r,k,x,p,h,l rk,rk,rx,rp,hk,rl\n");
X    printf("		f disk file dk? (unix file)\n");
X    printf("		t DEC-tape\n");
X    printf("	c is the unit number (0-9)\n");
X    printf("	\n");
X    printf("	file is either a unix file or a rt11 file (preceeded by +)\n");
X    printf("	or an extension or a namepart\n");
X    printf("	\n");
X    printf("\t\texample: %s xf1 +junk.sav\t(extract JUNK.SAV from dk1)\n",argv[0]);
X    printf("\t\texample: %s lx0 \t\t(list dir on rx0)\n",argv[0]);
X    printf("\t\texample: %s ef2 +.com\t(list *.COM from dk2)\n",argv[0]);
X    exit(0);
X  }
X  switch (argv[1][0] ) /*establish rwflag for rtmount */
X    {
X    case 'x': case 'l': case 'e': 
X    case 'n': case 'f': rwf=0; break;
X    case 'r':  case 'd': rwf=1;break;
X    default: printf("bad usage\n");
X             goto end;
X    }
X  devindex= 7;	/* index to unit number of device */
X  switch (argv[1][1]) /* second letter is either the device or unit number */
X   {
X    case 'r':
X	break;		/* /dev/rkx */
X    case 'x':
X    case 'k':
X    case 'l':
X    case 'p':
X	device[6] = argv[1][1];
X	break;
X    case 'h':
X	device = "/dev/hkx";
X	break;
X    case 'f':
X	device = "dkx";
X	devindex = 2;
X	break;
X    case 't':
X	device = "/dev/tapx";
X	devindex++;	/* unit index kicked by one */
X	break;
X    default:
X	if(argv[1][1] >= '0' && argv[1][1] <= '9') {
X		device[devindex] = argv[1][1];	/* copy unit number */
X		break;
X	}
X	printf("bad usage\n");
X	goto end;
X    }
X  if(device[devindex] == 'x' || argv[1][2] != 0) {
X	if(device[devindex] == 'x' && argv[1][2] >= '0' && argv[1][2] <= '9'
X		&& argv[1][3] == 0) {
X		device[devindex] = argv[1][2];	/* copy unit number */
X	}
X	else {
X	    printf("bad usage \n"); goto end;
X	}
X  }
X  if(rtmount(device,rwf)== -1)
X    {printf("%s can not be mounted\n",device); goto end;}
X/*argc ==2 is allowed only for function l and f */
X  if (argc==2)
X    {
X    if (argv[1][0]== 'l') {dirlist(0,"0");goto umou;}
X    else if(argv[1][0]== 'f') {freespace();goto umou;}
X    else {printf("bad usage\n"); goto umou;}
X    }
X  /*fill out rtarg unarg */
X  j=0; k=0;
X  for(i=2; i!=argc; i++)
X    if(argv[i][0]=='+') rtarg[k++]=i;
X    else unarg[j++]=i;
X  l=k;
X/*fill with zeros the untouched element of the arrays if the 
X  corresponding element of the other array was filled out */
X  if(k>j) for(l=j; l!= k; l++) unarg[l]=0;
X  else if (j>k) for(l=k; l!= j; l++)rtarg[l]=0;
X  /*l now contains the number of rt11-unix pairs+1*/
X  switch (argv[1][0])
X    {
X    case 'r': case 'x': 
X/*establish indecies to be used in the rucop or urcop call */
X    for(i=0; i!=l;i++)
X      {
X      if(unarg[i]==0)
X        {
X        j=rtarg[i]; k=1;
X        m=rtarg[i]; n=1;
X        }
X      else if(rtarg[i]==0)
X        {
X        j=unarg[i];k=0;
X        m=unarg[i];n=lastslash(argv[m]);
X        }
X      else
X        {
X        j=unarg[i];k=0;
X        m=rtarg[i];n=1;
X        }
X      if(argv[1][0]=='r')
X        {
X        if(urcop(&argv[j][k],&argv[m][n])== -1)
X        printf("copy between %s and %s is not possible\n",argv[j],argv[m]);
X        }
X      else
X        if(rucop(&argv[j][k],&argv[m][n])== -1)
X        printf("copy between %s and %s is not possible\n",argv[j],argv[m]);
X      }
X    break;
X    case 'l':
X    for(i=2; i!= argc; i++)
X      {
X      if(dirlist(1,&argv[i][0])== -1)
X      printf("%s invalid name\n",argv[i]);
X      }
X    break;
X    case 'e':
X    for(i=2; i!= argc; i++)
X      {
X      if(dirlist(2,&argv[i][0])== -1)
X      printf("%s invalide name\n",argv[i]);
X      }
X    break;
X    case 'n': 
X    for(i=2; i !=argc; i++)
X      {
X      if(dirlist(3,&argv[i][0])== -1)
X      printf("%s invalide name\n",argv[i]);
X      }
X    break;
X    case 'f':
X    freespace(); break;
X    case 'd':
X    for(i=2; i!=argc;i++)
X      {
X      if(argv[i][0]!='+'){printf("%s invalid\n",argv[i]);
X                           continue;}
X      if(rtdelete(&argv[i][1])== -1)
X      printf("%s can not be deleted\n",argv[i]);
X      }
X    }
X  umou: rtumount();
X  end:;
X} /*rtpip end*/
X
X                      /*---convasc---*/
X
X
Xconvasc(radname,ascii) char *ascii; r_short radname;
X/*interprets radname as 3 rad50 letters converts them and    
X  puts them into ascii */
X
X{
X  int i, k;
X  /* to get the first char needs special treatment because
X    radname can be negative and then "/" gives false result */
X  if(radname & 01)k=1;
X  else k=0;
X  radname >>= 1;
X  radname &= 077777;
X  ascii[2]=((radname % 024)*2)+k;
X  radname /= 024;
X/*for the rest follow the normal way*/
X  ascii[1]=radname % 050;
X  radname /= 050;
X  ascii[0]= radname %050;
X  for(i=0; i!= 3;i++)
X    if(ascii[i]==0)ascii[i]=040;
X    else if(ascii[i]==033)ascii[i]=044;
X    else if(ascii[i]==034)ascii[i]=056;
X    else if(ascii[i]<=032 && ascii[i]>=001)ascii[i]=ascii[i]+0100;
X    else if(ascii[i]<=047 && ascii[i]>=036)ascii[i]=ascii[i]+022;
X  return;
X}
X
X
X                      /*---getradn---*/
X
Xgetradn(radname,name) r_short *radname; char *name;
X/*converts radname radix filename into name ascii filename */
X
X{
X
X  int i,j;
X  convasc(radname[0],name);
X  convasc(radname[1],name+3);
X  name[6]='.';
X  convasc(radname[2],name+7);
X  name[10]=0;
X  return;
X}
X
X
X                      /*---lastslash---*/
X
Xlastslash(name) char *name;
X/*returns the index of char after the last slash in name
X  if there is no slash it returns 0 */
X
X{
X  int i,j;
X  j=0;
X  for(i=0; name[i] != 0; i++)
X    if(name[i]=='/') j=i+1;
X  return(j);
X}
X
X
X
X                      /*---rucop---*/
X
Xrucop(nam1,nam2) char *nam1, *nam2;
X/*copies rt11 file nam2 into unix file nam1 */
X{
X  char *cbuff; int a,b,c,d;
X  cbuff=rtbuffer;
X  if((a=rtopen(nam2,0))== -1)return(-1);
X  if((b=creat(nam1,0777))== -1)return(-1);
X  do
X    {
X    if((c=rtread(a,cbuff,1024))== -1)return(-1);
X    if((d=write(b,cbuff,c))== -1)return(-1);
X    }
X  while(c && d);
X  if(close(b)== -1)return(-1);
X  if(rtclose(a)== -1)return(-1);
X  return(0);
X}
X
X
X                        /*---urcop---*/
X
Xurcop(nam1,nam2) char *nam1, *nam2;
X/*copies unix file  nam1 into rt11 file nam2 */
X
X{
X  char  *cbuff; int a,b,c,d,i;
X  cbuff=rtbuffer;
X  if((a=rtopen(nam2,1))== -1)return(-1);
X  if((b=open(nam1,0))== -1)return(-1);
X  do
X    {
X    if((c=read(b,cbuff,1024))== -1)return(-1);
X    if((d=rtwrite(a,cbuff,c))== -1)return(-1);
X    }
X  while(c && d);
X  if(close(b)== -1)return(-1);
X  if(rtclose(a)== -1)return(-1);
X  return(0);
X}
X
X
X
X                      /*---dirlist---*/
X
Xdirlist(dflag,name) char *name;
X/*dirlist list the rt11 directory on the standard output
X  device,partially or totally depending on dflag
X  if dflag =
X     0      the whole directory is listed
X     1      name is taken as a whole filename(filnam.ext)
X             and  it is  printed if present
X     2      name is taken as .ext and all file with ext are printed
X     3        same as 2 but name is taken as filnam
X*/
X
X{
X  r_short radname[3],radnam1[3];
X  int size,mess[2],a;
X  char ascii[11];
X  int k;
X  if(dflag != 0 && name[0]!='+')return(-1);
X  if(dflag == 2  && name[1]== '.')k=2;
X  else k=1;
X  rtinitdir();
X  if(dflag != 0)
X    if(rtgetname(name+k,radnam1)== -1)return(-1);
X  while((a=rtserdir(radname,mess,&size,mess,mess)) != -1)
X    {
X    if(a==0400 || a==01000)/*entry is empty or tentative*/continue;
X    switch(dflag)
X      {
X      case 0: getradn(radname,ascii);
X              printf("%s  %d\n",ascii,size);
X              break;
X      case 1: if(radname[0]== radnam1[0] &&
X                 radname[1]== radnam1[1] &&
X                    radname[2]== radnam1[2])
X                  {
X                   getradn(radname,ascii);
X                   printf("%s   %d\n",ascii,size);
X                    }
X                 break;
X      case 2: if(radname[2]== radnam1[0])
X                {
X                getradn(radname,ascii);
X                printf("%s   %d\n",ascii,size);
X                }
X              break;
X      case 3: if(radname[0]==radnam1[0] &&
X                 radname[1]==radnam1[1])
X                {
X                getradn(radname,ascii);
X                printf("%s   %d\n",ascii,size);
X                }
X              break;
X    }
X  }
X  return(0);
X}
X
X
X                       /*---freespace---*/
X
Xfreespace()
X/* list freespaces on rt11 device */
X{
X  int mess[3],size,a;
X  rtinitdir();
X  while((a=rtserdir(mess,mess,&size,mess,mess))!= -1)
X    if(a==01000)printf("%d\n",size);
X  return;
X}
All work and no play makes Jack a dull boy