[net.sources] rtar/rdd/rmt for 4.2 BSD

donn@sdchema.UUCP (03/17/84)

#! /bin/sh

: This is a Bourne Shell script, not a C-shell script.

: Make a directory 'rtar', copy this file to 'rtar/SCRIPT' and change
:	directories to 'rtar'.  Strip any mail or news headers from
:	SCRIPT and run 'sh SCRIPT'.

cat > README << "EOF"
The files in this directory will allow you to make the following
programs:

	rtar	-- remote tape archiver
	rdd	-- generalized remote tape I/O
	rmt	-- remote tape manipulator

The distribution comes as a set of 'ed' scripts, a Makefile and a
document.  To create the source files to the programs, run 'make
sources' -- this copies the original source files into this directory
and runs 'ed' on them with the appropriate script.  (You may need to
customize the makefile.)  After making the sources, you can run 'make
install' to install them.  You must run 'make install' as root.  To
install the documentation, run 'make document'.

Simple, huh?  (Gasp, wheeze, pant, etc.)

You may direct bug reports to:

	Donn Seeley
	Chemistry Dept., B-014
	UC San Diego
	La Jolla, CA 92093
	(619) 452-4016
	ucbvax!sdcsvax!sdchema!donn

BTW, the sources are no doubt (c) 1984 Regents of the University of
California, although I haven't asked about them.
EOF

cat > rtar.1 << "EOF"
.TH RTAR 1 "16 March 1984"
.UC 4
.SH NAME
rtar, rdd, rmt \- remote tape manipulation programs
.SH SYNOPSIS
.B rtar
\&...\f3f\f1...
.I host:device
[ files ] ...
.PP
.B rdd
\&... [ \f3if=\f2host:device\f1 ] ... [ \f3of=\f2host:device\f1 ] ...
.PP
.B rmt
[
.B \-f
.I host:device
] ...
.SH DESCRIPTION
.IR Rtar ,
.I rdd
and
.I rmt
are versions of
.IR tar (1),
.IR dd (1)
and
.IR mt (1)
which work on remote tapes in much the same way as
.IR rdump (8)
and
.IR rrestore (8).
These programs cause another program
.I /etc/rmt
(\c
.IR rmt (8))
to be executed on the remote host,
which in turn manipulates the specified device
according to commands issued by the local program,
passing data back and forth as necessary.
All keys and options for the remote flavor programs
are the same as for the local flavor programs;
the only difference is that if a tape device
of the form
.I host:device
is specified,
the tape operations are performed on the named device
on the named host.
.SH DIAGNOSTICS
Diagnostics are the same as for the local flavor programs,
with the exception of a few possible socket errors.
Remote errors are reported to the local program.
.SH "SEE ALSO"
dd(1), mt(1), tar(1), mtio(4), rdump(8), rmt(8), rrestore(8)
.SH BUGS
.I Rmt
is clearly a bad name for 'remote
.IR mt ',
since it clashes with
.IR /etc/rmt .
It is suggested that one simply install
.I rmt
as
.IR mt ,
since the overhead of using the remote routines is low for this program.
.PP
.IR Rtar ,
.I rdd
and
.I rmt
must all be setuid to root,
since they use a privileged socket.
The programs know enough to setuid back to the real user id
after opening the socket, but there are undoubtedly security problems here.
.PP
Only one remote tape may be specified.
Thus
.I rdd
may not have a remote tape for both input and output.
.PP
The program
.I /etc/rmt
has bugs in it.
Most of these bugs appear to be handled by
.I rtar
and friends, but beware.
EOF

cat > Makefile << "EOF"
#
# Makefile for rtar, rdd and rmt (4.2 BSD)
#
# If you are making these programs for the first time, using the editor
#	scripts, run 'make sources'.  The variables TAR, DD, MT and DUMPRMT
#	below should be set to the names of file containing VANILLA versions
#	of their respective sources.  If you have modified your sources you
#	will need to change the default assignments.
#

TAR	= /usr/src/bin/tar.c
DD	= /usr/src/bin/dd.c
MT	= /usr/src/bin/mt.c
DUMPRMT	= /usr/src/etc/dump/dumprmt.c

CFLAGS	= -O
BINDIR	= /usr/local/bin

#
# 'make install' puts the programs in $(BINDIR).
# Be sure to run 'make install' as user root.
#
install: all
	cp rtar rdd rmt $(BINDIR)
	cd $(BINDIR); /etc/chown root rtar rdd rmt
	cd $(BINDIR); chmod u+s rtar rdd rmt

all:	rtar rdd rmt

rtar:	rtar.o rsubs.o
	$(CC) $(CFLAGS) -o $@ rtar.o rsubs.o

rdd:	rdd.o rsubs.o
	$(CC) $(CFLAGS) -o $@ rdd.o rsubs.o

rmt:	rmt.o rsubs.o
	$(CC) $(CFLAGS) -o $@ rmt.o rsubs.o

#
# Run 'make sources' to make sources from the editor scripts.
# Use 'make sources' with discretion -- it clobbers the sources.
# 
sources:
	cp $(TAR) rtar.c
	chmod u+w rtar.c
	ed rtar.c < rtar.script
	cp $(DD) rdd.c
	chmod u+w rdd.c
	ed rdd.c < rdd.script
	cp $(MT) rmt.c
	chmod u+w rmt.c
	ed rmt.c < rmt.script
	cp $(DUMPRMT) rsubs.c
	chmod u+w rsubs.c
	ed rsubs.c < rsubs.script

#
# Run 'make document' to install the manual page.
# Set SECTION to determine the section (1 for section 1, l for LOCAL, etc.)
#
MANDIR	= /usr/man
SECTION	= l
document:
	cp rtar.1 $(MANDIR)/man$(SECTION)/rtar.$(SECTION)
	echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
		$(MANDIR)/man$(SECTION)/rdd.$(SECTION)
	echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
		$(MANDIR)/man$(SECTION)/rmt.$(SECTION)
EOF

cat > rtar.script << "EOF"
1151c
		lastread = rmtread(fd, buf, size - count);

donn@sdchema.UUCP (03/18/84)

	#! /bin/sh

	: This is a Bourne Shell script, not a C-shell script.

	# Make a directory 'rtar', copy this file to 'rtar/SCRIPT' and change
	#	directories to 'rtar'.  Strip any mail or news headers from
	#	'SCRIPT', remove the initial tab from each line (e.g. with the
	#	command '%<' in 'ex') and run 'sh SCRIPT'.  The tabs are
	#	necessary because some news programs stop reading after a
	#	line consisting of a single '.' (sigh -- thanks to Mark Horton
	#	for help on this).

	cat > README << "EOF"
	The files in this directory will allow you to make the following
	programs:

		rtar	-- remote tape archiver
		rdd	-- generalized remote tape I/O
		rmt	-- remote tape manipulator

	The distribution comes as a set of 'ed' scripts, a Makefile and a
	document.  To create the source files to the programs, run 'make
	sources' -- this copies the original source files into this directory
	and runs 'ed' on them with the appropriate script.  (You may need to
	customize the makefile.)  After making the sources, you can run 'make
	install' to install them.  You must run 'make install' as root.  To
	install the documentation, run 'make document'.

	Simple, huh?  (Gasp, wheeze, pant, etc.)

	You may direct bug reports to:

		Donn Seeley
		Chemistry Dept., B-014
		UC San Diego
		La Jolla, CA 92093
		(619) 452-4016
		ucbvax!sdcsvax!sdchema!donn

	BTW, the sources are no doubt (c) 1984 Regents of the University of
	California, although I haven't asked about them.
	EOF

	cat > rtar.1 << "EOF"
	.TH RTAR 1 "16 March 1984"
	.UC 4
	.SH NAME
	rtar, rdd, rmt \- remote tape manipulation programs
	.SH SYNOPSIS
	.B rtar
	\&...\f3f\f1...
	.I host:device
	[ files ] ...
	.PP
	.B rdd
	\&... [ \f3if=\f2host:device\f1 ] ... [ \f3of=\f2host:device\f1 ] ...
	.PP
	.B rmt
	[
	.B \-f
	.I host:device
	] ...
	.SH DESCRIPTION
	.IR Rtar ,
	.I rdd
	and
	.I rmt
	are versions of
	.IR tar (1),
	.IR dd (1)
	and
	.IR mt (1)
	which work on remote tapes in much the same way as
	.IR rdump (8)
	and
	.IR rrestore (8).
	These programs cause another program
	.I /etc/rmt
	(\c
	.IR rmt (8))
	to be executed on the remote host,
	which in turn manipulates the specified device
	according to commands issued by the local program,
	passing data back and forth as necessary.
	All keys and options for the remote flavor programs
	are the same as for the local flavor programs;
	the only difference is that if a tape device
	of the form
	.I host:device
	is specified,
	the tape operations are performed on the named device
	on the named host.
	.SH DIAGNOSTICS
	Diagnostics are the same as for the local flavor programs,
	with the exception of a few possible socket errors.
	Remote errors are reported to the local program.
	.SH "SEE ALSO"
	dd(1), mt(1), tar(1), mtio(4), rdump(8), rmt(8), rrestore(8)
	.SH BUGS
	.I Rmt
	is clearly a bad name for 'remote
	.IR mt ',
	since it clashes with
	.IR /etc/rmt .
	It is suggested that one simply install
	.I rmt
	as
	.IR mt ,
	since the overhead of using the remote routines is low for this program.
	.PP
	.IR Rtar ,
	.I rdd
	and
	.I rmt
	must all be setuid to root,
	since they use a privileged socket.
	The programs know enough to setuid back to the real user id
	after opening the socket, but there are undoubtedly security problems here.
	.PP
	Only one remote tape may be specified.
	Thus
	.I rdd
	may not have a remote tape for both input and output.
	.PP
	The program
	.I /etc/rmt
	has bugs in it.
	Most of these bugs appear to be handled by
	.I rtar
	and friends, but beware.
	EOF

	cat > Makefile << "EOF"
	#
	# Makefile for rtar, rdd and rmt (4.2 BSD)
	#
	# If you are making these programs for the first time, using the editor
	#	scripts, run 'make sources'.  The variables TAR, DD, MT and DUMPRMT
	#	below should be set to the names of file containing VANILLA versions
	#	of their respective sources.  If you have modified your sources you
	#	will need to change the default assignments.
	#

	TAR	= /usr/src/bin/tar.c
	DD	= /usr/src/bin/dd.c
	MT	= /usr/src/bin/mt.c
	DUMPRMT	= /usr/src/etc/dump/dumprmt.c

	CFLAGS	= -O
	BINDIR	= /usr/local/bin

	#
	# 'make install' puts the programs in $(BINDIR).
	# Be sure to run 'make install' as user root.
	#
	install: all
		cp rtar rdd rmt $(BINDIR)
		cd $(BINDIR); /etc/chown root rtar rdd rmt
		cd $(BINDIR); chmod u+s rtar rdd rmt

	all:	rtar rdd rmt

	rtar:	rtar.o rsubs.o
		$(CC) $(CFLAGS) -o $@ rtar.o rsubs.o

	rdd:	rdd.o rsubs.o
		$(CC) $(CFLAGS) -o $@ rdd.o rsubs.o

	rmt:	rmt.o rsubs.o
		$(CC) $(CFLAGS) -o $@ rmt.o rsubs.o

	#
	# Run 'make sources' to make sources from the editor scripts.
	# Use 'make sources' with discretion -- it clobbers the sources.
	# 
	sources:
		cp $(TAR) rtar.c
		chmod u+w rtar.c
		ed rtar.c < rtar.script
		cp $(DD) rdd.c
		chmod u+w rdd.c
		ed rdd.c < rdd.script
		cp $(MT) rmt.c
		chmod u+w rmt.c
		ed rmt.c < rmt.script
		cp $(DUMPRMT) rsubs.c
		chmod u+w rsubs.c
		ed rsubs.c < rsubs.script

	#
	# Run 'make document' to install the manual page.
	# Set SECTION to determine the section (1 for section 1, l for LOCAL, etc.)
	#
	MANDIR	= /usr/man
	SECTION	= l
	document:
		cp rtar.1 $(MANDIR)/man$(SECTION)/rtar.$(SECTION)
		echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
			$(MANDIR)/man$(SECTION)/rdd.$(SECTION)
		echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
			$(MANDIR)/man$(SECTION)/rmt.$(SECTION)
	EOF

	cat > rtar.script << "EOF"
	1151c
			lastread = rmtread(fd, buf, size - count);
	.
	1144c
			return (rmtread(fd, buf, size));
	.
	1132c
		rmtwrite(mt, tbuf, TBLOCK*nblock);
	.
	1126c
			rmtseek(mt, (long) -TBLOCK*nblock, 1);
	.
	1121c
			if (rmtioctl(mt, MTIOCTOP, &mtop) < 0) {
	.
	1119c
			mtdev = rmtioctl(mt, MTIOCGET, &mtget);
	.
	1103c
			if (rmtwrite(mt, tbuf, TBLOCK*nblock) < 0) {
	.
	1095c
			if (rmtwrite(mt, tbuf, TBLOCK*nblock) < 0) {
	.
	260,262c
			fprintf(stderr, "tar: can't use local standard input\n");
			fprintf(stderr, "tar: use 'tar' not 'rtar'\n");
			done(1);
		} else if ((mt = rmtopen(usefile, 0)) < 0) {
	.
	242,254c
				fprintf(stderr, "tar: can't use remote standard output\n");
				fprintf(stderr, "tar: use 'tar' not 'rtar'\n");
				done(1);
			} else if ((mt = rmtopen(usefile, 2)) < 0) {
				fprintf(stderr, "tar: can't open remote tape\n");
				done(1);
	.
	65c
	int	mt = -1;
	.
	7a

	.
	6c
	 * rtar.c
	 *
	 * Remote Tape Archival Program
	 *
	 * UCSD Chemistry modification history:
	 *
	 * $Log:	rtar.c,v $
	 * Revision 1.2  84/03/16  17:47:01  donn
	 * Changed to use remote tape routines from rsubs.c.
	 * 
	.
	2c
	/* static	char *sccsid = "@(#)tar.c	4.19 (Berkeley) 9/22/83"; */
	static char *rcsid = "$Header: rtar.c,v 1.2 84/03/16 17:47:01 donn Exp $";
	.
	w
	q
	EOF

	cat > rdd.script << "EOF"
	362c
			c = rmtwrite(obf, obuf, obc);
	.
	307c
				ibc = rmtread(ibf, ibuf, ibs);
	.
	296c
			rmtseek(obf, (long)obs, 1);
	.
	292c
			rmtread(ibf, ibuf, ibs);
	.
	258c
			obf = rmtopen(ofile, O_WRONLY | O_CREAT, 0666);
	.
	250c
			ibf = rmtopen(ifile, O_RDONLY);
	.
	3a
	#include <sys/file.h>
	.
	1c
	/* static char *sccsid = "@(#)dd.c	4.3 (Berkeley) 4/29/83"; */
	static char *rcsid = "$Header: rdd.c,v 1.2 84/03/16 17:15:15 donn Exp $";

	/*
	 * rdd.c
	 *
	 * Dump data program (remote tape version).
	 *
	 * UCSD Chemistry modification history:
	 *
	 * $Log:	rdd.c,v $
	 * Revision 1.2  84/03/16  17:15:15  donn
	 * Added changes to allow one file (either input or output) to be a tape on
	 * a remote machine.  Must be loaded with rsubs.c.
	 * 
	 */

	.
	w
	q
	EOF

	cat > rmt.script << "EOF"
	81c
			if (rmtioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) {
	.
	74c
			if (rmtioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
	.
	63c
		if ((mtfd = rmtopen(tape, comp->c_ronly ? 0 : 2)) < 0) {
	.
	60c
			fprintf(stderr, "mt: unknown command \"%s\"\n", cp);
	.
	5a

	.
	3,4c
	 * rmt.c
	 *
	 * Remote magnetic tape manipulation program.
	 *
	 * UCSD Chemistry modification history:
	 *
	 * $Log:	rmt.c,v $
	 * Revision 1.2  84/03/16  17:38:54  donn
	 * Changed to use remote tape subroutines from rsubs.c.
	 * 
	.
	1c
	/* static	char *sccsid = "@(#)mt.c	4.8 (Berkeley) 83/05/08"; */
	static char *rcsid = "$Header: rmt.c,v 1.2 84/03/16 17:38:54 donn Exp $";

	.
	w
	q
	EOF

	cat > rsubs.script << "EOF"
	223c
		fprintf(stderr, "Protocol to remote tape server botched (in rmtgets).\n");
	.
	193c
			fprintf(stderr, "Protocol to remote tape server botched (code %s?).\n",
	.
	185c
	/*		fprintf(stderr, "%s: %s\n", cmd, emsg); */
			errno = atoi(code + 1);
	.
	180a
		extern int errno;
	.
	163,164c
		}
	.
	161c
		if (f != rmtape)
			return (ioctl(f, cmd, count));

		switch (cmd) {

		case MTIOCTOP:
			pmtop = (struct mtop *) data;
			if (pmtop->mt_count <= 0)
				return (-1);
			sprintf(buf, "I%d\n%d\n", pmtop->mt_op, pmtop->mt_count);
			return (rmtcall("ioctl", buf));

		case MTIOCGET:
			/*
			 * 'Rmt' has a bug -- the mtget structure is returned BEFORE
			 *	the acknowledgement, despite the documentation.
			 *	Fortunately the first byte of an error code is either
			 *	'E' or 'F', neither of which are legal MT types.
			 */
			if (write(rmtape, "S\n", 2) != 2)
				rmtconnaborted();
			if (recv(rmtape, buf, 1, MSG_PEEK) < 1)
				rmtconnaborted();
			if (buf[0] == 'E' || buf[0] == 'F')
				return (rmtreply("ioctl"));
			if (buf[0] == 'A') {
				/*
				 * This 'rmt' has been fixed.
				 */
				if ((count = rmtreply("ioctl")) < 0)
					return (-1);
				for (i = 0; i < count; ++i)
					data[i] = rmtgetb();
				return (0);
			}

			/*
			 * Normal (buggy) 'rmt'.
			 */
			count = sizeof (struct mtget);
			for (i = 0; i < count; ++i)
				data[i] = rmtgetb();
			if (count != rmtreply("ioctl"))
				return (-1);
			return (0);

		default:
	.
	159a
		register int i;
		struct mtop *pmtop;
		int count;
	.
	156,157c
	rmtioctl(f, cmd, data)
		int f, cmd;
		char *data;
	.
	135a
		if (f != rmtape)
			return (lseek(f, offset, pos));
	.
	131,132c
	rmtseek(f, offset, pos)
		int f, offset, pos;
	.
	129a
	#endif notdef
	.
	106a
	#ifdef notdef
	.
	100a
		if (f != rmtape)
			return (write(f, buf, count));
	.
	95c
	rmtwrite(f, buf, count)
		int f;
	.
	79a
		if (f != rmtape)
			return (read(f, buf, count));
	.
	72c
	rmtread(f, buf, count)
		int f;
	.
	69a
		return (0);
	.
	67c
			return (-1);
	.
	65a
		if (f != rmtape)
			return (close(f));
	.
	63c
	rmtclose(f)
		int f;
	.
	60a
		return (rmtape);
	.
	58,59c
		if (rmtstate == TS_OPEN) {
			if (access(name, 0x6) != 0)
				return (-1);
			return (open(name, mode, mask));
		}
		host = malloc(strlen(name) + 1);
		strcpy(host, name);
		tape = index(host, ':');
		if (tape == NULL) {
			if (access(name, 0x6) != 0)
				return (-1);
			return (open(name, mode, mask));
		}
		*tape++ = '\0';
		if (strncmp(tape, "/dev/rmt", 8) != 0 &&
		    strncmp(tape, "/dev/mt", 7) != 0) {
			errno = EACCES;
			return (-1);
		}
		if (rmthost(host) < 0)
			return (-1);

		sprintf(buf, "O%s\n%d\n", tape, mode & 03);
		if (rmtcall(tape, buf) < 0)
			return (-1);
	.
	56a
		char *host, *tape;
		char *index();
		char *malloc();
		extern int errno;
	.
	54a
		int mask;
	.
	52,53c
	/*
	 * rmtopen opens a tape device on the remote machine.  We assume that if a name
	 *	has a colon in it, then it refers to a remote tape; otherwise it is
	 *	caught and a normal operation is done on it.  Only one remote tape
	 *	is allowed to be open at a time.
	 */
	rmtopen(name, mode, mask)
		char *name;
	.
	49a
		setuid(getuid());	/* Patch security hole */
	.
	45c
				fprintf(stderr, "rtar: shell/tcp: unknown service\n");
	.
	27,28c
		if (rmtape < 0) {
			if (errno == 0)
				errno = EACCES;
			return (-1);
		}
		return (0);
	.
	22a
		extern int errno;
	.
	16c
	int	rmtape = -1;
	.
	11a
	#include <errno.h>

	.
	7a
	#include <sys/socket.h>
	.
	2a
	/*
	 * rsubs.c
	 *
	 * Handle protocol with remote 'rmt' program for 'rtar' and 'rdd'.
	 * Stolen from 'rdump'.
	 *
	 * UCSD Chemistry modification history:
	 *
	 * $Log:	rsubs.c,v $
	 * Revision 1.4  84/03/16  21:45:17  donn
	 * The remote device name is now restricted to '/dev/rmt*' or '/dev/mt*' to
	 * prevent 'rdd if=host:/usr/lib/uucp/L.sys' etc.  Quick and dirty.  Also
	 * the error reporting has been changed -- EACCES is returned if the host
	 * doesn't exist or if the remote device name was illegal.
	 * 
	 * Revision 1.3  84/03/16  18:46:18  donn
	 * Attempted (again) to plug security holes.
	 * 
	 * Revision 1.2  84/03/16  17:22:25  donn
	 * Made several small modifications.  It is permitted to use a non-remote
	 * file (although only one remote file may be used).  Instead of making its
	 * own complaints, the acknowledgement routine sets errno.  Tape ioctls are
	 * handled correctly.  The bug in /etc/rmt regarding the 'S' message that
	 * causes the status bytes to be handed back before the byte count is now
	 * picked up and handled appropriately.
	 * 
	 */

	.
	1c
	static	char *rcsid = "$Header: rsubs.c,v 1.4 84/03/16 21:45:17 donn Exp $";
	.
	w
	q
	EOF

	exit 0