[net.sources] New version of rtar/rdd/rmt

donn@sdchema.UUCP (04/08/84)

: Run this shell script with "sh" not "csh"

# Make a directory 'rtar', copy this article into 'rtar/SCRIPT'.
# Use an editor to remove any mail or news headers from 'SCRIPT'.
# Run 'sh SCRIPT'.  This will extract the distribution.
# Read the file 'README' to find out how to build 'rtar'.

PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting README'
sed 's/^X//' <<'//go.sysin dd *' >README
XThe files in this directory will allow you to make the following
Xprograms:
X
X	rtar	-- remote tape archiver
X	rdd	-- generalized remote tape I/O
X	rmt	-- remote tape manipulator
X
XThe distribution comes as a set of 'ed' scripts, a Makefile and a
Xdocument.  To create the source files to the programs, run 'make
Xsources' -- this copies the original source files into this directory
Xand runs 'ed' on them with the appropriate script.  (You may need to
Xcustomize the makefile.)  After making the sources, you can run 'make
Xinstall' to install them.  You must run 'make install' as root.  To
Xinstall the documentation, run 'make document'.
X
XSimple, huh?  (Gasp, wheeze, pant, etc.)
X
XYou may direct bug reports to:
X
X	Donn Seeley
X	Chemistry Dept., B-014
X	UC San Diego
X	La Jolla, CA 92093
X	(619) 452-4016
X	ucbvax!sdcsvax!sdchema!donn
X
XBTW, the sources are no doubt (c) 1984 Regents of the University of
XCalifornia, although I haven't asked about them.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 README
	/bin/echo -n '	'; /bin/ls -ld README
fi
/bin/echo 'Extracting Makefile'
sed 's/^X//' <<'//go.sysin dd *' >Makefile
X#
X# Makefile for rtar, rdd and rmt (4.2 BSD)
X#
X# If you are making these programs for the first time, using the editor
X#	scripts, run 'make sources'.  The variables TAR, DD, MT and DUMPRMT
X#	below should be set to the names of file containing VANILLA versions
X#	of their respective sources.  If you have modified your sources you
X#	will need to change the default assignments.
X#
X
XTAR	= /usr/src/bin/tar.c
XDD	= /usr/src/bin/dd.c
XMT	= /usr/src/bin/mt.c
XDUMPRMT	= /usr/src/etc/dump/dumprmt.c
X
XCFLAGS	= -O
XBINDIR	= /usr/local/bin
X
X#
X# 'make install' puts the programs in $(BINDIR).
X# Be sure to run 'make install' as user root.
X#
Xinstall: all
X	cp rtar rdd rmt $(BINDIR)
X	cd $(BINDIR); /etc/chown root rtar rdd rmt
X	cd $(BINDIR); chmod u+s rtar rdd rmt
X
Xall:	rtar rdd rmt
X
Xrtar:	rtar.o rsubs.o
X	$(CC) $(CFLAGS) -o $@ rtar.o rsubs.o
X
Xrdd:	rdd.o rsubs.o
X	$(CC) $(CFLAGS) -o $@ rdd.o rsubs.o
X
Xrmt:	rmt.o rsubs.o
X	$(CC) $(CFLAGS) -o $@ rmt.o rsubs.o
X
X#
X# Run 'make sources' to make sources from the editor scripts.
X# Use 'make sources' with discretion -- it clobbers the sources.
X# 
Xsources:
X	cp $(TAR) rtar.c
X	chmod u+w rtar.c
X	ed rtar.c < rtar.script
X	cp $(DD) rdd.c
X	chmod u+w rdd.c
X	ed rdd.c < rdd.script
X	cp $(MT) rmt.c
X	chmod u+w rmt.c
X	ed rmt.c < rmt.script
X	cp $(DUMPRMT) rsubs.c
X	chmod u+w rsubs.c
X	ed rsubs.c < rsubs.script
X
X#
X# Run 'make document' to install the manual page.
X# Set SECTION to determine the section (1 for section 1, l for LOCAL, etc.)
X#
XMANDIR	= /usr/man
XSECTION	= l
Xdocument:
X	cp rtar.1 $(MANDIR)/man$(SECTION)/rtar.$(SECTION)
X	echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
X		$(MANDIR)/man$(SECTION)/rdd.$(SECTION)
X	echo '.so $(MANDIR)/man$(SECTION)/rtar.$(SECTION)' > \
X		$(MANDIR)/man$(SECTION)/rmt.$(SECTION)
X
Xclean:
X	rm -f *[Ee]rrs* *.o rtar rdd rmt
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 Makefile
	/bin/echo -n '	'; /bin/ls -ld Makefile
fi
/bin/echo 'Extracting rtar.1'
sed 's/^X//' <<'//go.sysin dd *' >rtar.1
X.TH RTAR 1 "16 March 1984"
X.UC 4
X.SH NAME
Xrtar, rdd, rmt \- remote tape manipulation programs
X.SH SYNOPSIS
X.B rtar
X\&...\f3f\f1...
X.I host:device
X[ files ] ...
X.PP
X.B rdd
X\&... [ \f3if=\f2host:device\f1 ] ... [ \f3of=\f2host:device\f1 ] ...
X.PP
X.B rmt
X[
X.B \-f
X.I host:device
X] ...
X.SH DESCRIPTION
X.IR Rtar ,
X.I rdd
Xand
X.I rmt
Xare versions of
X.IR tar (1),
X.IR dd (1)
Xand
X.IR mt (1)
Xwhich work on remote tapes in much the same way as
X.IR rdump (8)
Xand
X.IR rrestore (8).
XThese programs cause another program
X.I /etc/rmt
X(\c
X.IR rmt (8))
Xto be executed on the remote host,
Xwhich in turn manipulates the specified device
Xaccording to commands issued by the local program,
Xpassing data back and forth as necessary.
XAll keys and options for the remote flavor programs
Xare the same as for the local flavor programs;
Xthe only difference is that if a tape device
Xof the form
X.I host:device
Xis specified,
Xthe tape operations are performed on the named device
Xon the named host.
X.SH DIAGNOSTICS
XDiagnostics are the same as for the local flavor programs,
Xwith the exception of a few possible socket errors.
XRemote errors are reported to the local program.
X.SH "SEE ALSO"
Xdd(1), mt(1), tar(1), mtio(4), rdump(8), rmt(8), rrestore(8)
X.SH BUGS
X.I Rmt
Xis clearly a bad name for 'remote
X.IR mt ',
Xsince it clashes with
X.IR /etc/rmt .
XIt is suggested that one simply install
X.I rmt
Xas
X.IR mt ,
Xsince the overhead of using the remote routines is low for this program.
X.PP
X.IR Rtar ,
X.I rdd
Xand
X.I rmt
Xmust all be setuid to root,
Xsince they use a privileged socket.
XThe programs know enough to setuid back to the real user id
Xafter opening the socket, but there are undoubtedly security problems here.
X.PP
XThe program
X.I /etc/rmt
Xhas bugs in it.
XMost of these bugs appear to be handled by
X.I rtar
Xand friends, but beware.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rtar.1
	/bin/echo -n '	'; /bin/ls -ld rtar.1
fi
/bin/echo 'Extracting rdd.script'
sed 's/^X//' <<'//go.sysin dd *' >rdd.script
X362c
X		c = rmtwrite(obf, obuf, obc);
X.
X307c
X			ibc = rmtread(ibf, ibuf, ibs);
X.
X296c
X		rmtseek(obf, (long)obs, 1);
X.
X292c
X		rmtread(ibf, ibuf, ibs);
X.
X258c
X		obf = rmtopen(ofile, O_WRONLY | O_CREAT, 0666);
X.
X250c
X		ibf = rmtopen(ifile, O_RDONLY);
X.
X3a
X#include <sys/file.h>
X.
X1c
X/* static char *sccsid = "@(#)dd.c	4.3 (Berkeley) 4/29/83"; */
Xstatic char *rcsid = "$Header: rdd.c,v 1.2 84/03/16 17:15:15 donn Exp $";
X
X/*
X * rdd.c
X *
X * Dump data program (remote tape version).
X *
X * UCSD Chemistry modification history:
X *
X * $Log:	rdd.c,v $
X * Revision 1.2  84/03/16  17:15:15  donn
X * Added changes to allow one file (either input or output) to be a tape on
X * a remote machine.  Must be loaded with rsubs.c.
X * 
X */
X
X.
Xw
Xq
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 rdd.script
	/bin/echo -n '	'; /bin/ls -ld rdd.script
fi
/bin/echo 'Extracting rmt.script'
sed 's/^X//' <<'//go.sysin dd *' >rmt.script
X81c
X		if (rmtioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) {
X.
X74c
X		if (rmtioctl(mtfd, MTIOCTOP, &mt_com) < 0) {
X.
X63c
X	if ((mtfd = rmtopen(tape, comp->c_ronly ? 0 : 2)) < 0) {
X.
X60c
X		fprintf(stderr, "mt: unknown command \"%s\"\n", cp);
X.
X5a
X
X.
X3,4c
X * rmt.c
X *
X * Remote magnetic tape manipulation program.
X *
X * UCSD Chemistry modification history:
X *
X * $Log:	rmt.c,v $
X * Revision 1.2  84/03/16  17:38:54  donn
X * Changed to use remote tape subroutines from rsubs.c.
X * 
X.
X1c
X/* static	char *sccsid = "@(#)mt.c	4.8 (Berkeley) 83/05/08"; */
Xstatic char *rcsid = "$Header: rmt.c,v 1.2 84/03/16 17:38:54 donn Exp $";
X
X.
Xw
Xq
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 rmt.script
	/bin/echo -n '	'; /bin/ls -ld rmt.script
fi
/bin/echo 'Extracting rsubs.script'
sed 's/^X//' <<'//go.sysin dd *' >rsubs.script
X223c
X	fprintf(stderr, "Protocol to remote tape server botched (in rmtgets).\n");
X.
X215c
X		*cp = rmtgetb(f);
X.
X209c
Xrmtgets(f, cp, len)
X	int f;
X.
X204c
X	if (read(f, &c, 1) != 1)
X.
X200c
Xint
Xrmtgetb(f)
X	int f;
X.
X193c
X		fprintf(stderr, "Protocol to remote tape server botched (code %s?).\n",
X.
X187c
X			rmtstate[f] = TS_CLOSED;
X.
X184,185c
X		rmtgets(f, emsg, sizeof (emsg));
X/*		fprintf(stderr, "%s: %s\n", cmd, emsg); */
X		errno = atoi(code + 1);
X.
X182c
X	rmtgets(f, code, sizeof (code));
X.
X180a
X	extern int errno;
X.
X176c
Xint
Xrmtreply(f, cmd)
X	int f;
X.
X173c
X	return (rmtreply(f, cmd));
X.
X171c
X	if (write(f, buf, strlen(buf)) != strlen(buf))
X.
X167c
Xint
Xrmtcall(f, cmd, buf)
X	int f;
X.
X163,164c
X	}
X.
X161c
X	case MTIOCTOP:
X		pmtop = (struct mtop *) data;
X		if (pmtop->mt_count <= 0)
X			return (-1);
X		sprintf(buf, "I%d\n%d\n", pmtop->mt_op, pmtop->mt_count);
X		return (rmtcall(f, "ioctl", buf));
X
X	case MTIOCGET:
X		/*
X		 * '/etc/rmt' has a bug -- the mtget structure is returned
X		 *	BEFORE the acknowledgement, despite the documentation.
X		 *	Fortunately the first byte of an error code is either
X		 *	'E' or 'F', neither of which are legal MT types.
X		 */
X		if (write(f, "S\n", 2) != 2)
X			rmtconnaborted();
X		if (recv(f, buf, 1, MSG_PEEK) < 1)
X			rmtconnaborted();
X		if (buf[0] == 'E' || buf[0] == 'F')
X			return (rmtreply(f, "ioctl"));
X		if (buf[0] == 'A') {
X			/*
X			 * This 'rmt' has been fixed.
X			 */
X			if ((count = rmtreply(f, "ioctl")) < 0)
X				return (-1);
X			for (i = 0; i < count; ++i)
X				data[i] = rmtgetb(f);
X			return (0);
X		}
X
X		/*
X		 * Normal (buggy) 'rmt'.
X		 */
X		count = sizeof (struct mtget);
X		for (i = 0; i < count; ++i)
X			data[i] = rmtgetb(f);
X		if (count != rmtreply(f, "ioctl"))
X			return (-1);
X		return (0);
X
X	default:
X.
X156,159c
X	switch (cmd) {
X.
X148,154c
X	if (rmtstate[f] == TS_CLOSED)
X		return (ioctl(f, cmd, data));
X.
X146c
X	struct mtop *pmtop;
X	int count;
X.
X144a
X	char buf[256];
X.
X140,143c
Xrmtioctl(f, cmd, data)
X	int f, cmd;
X	char *data;
X.
X137c
X	return (rmtcall(f, "seek", line));
X.
X135a
X	if (rmtstate[f] == TS_CLOSED)
X		return (lseek(f, offset, pos));
X.
X131,132c
Xrmtseek(f, offset, pos)
X	int f, offset, pos;
X.
X129a
X#endif notdef
X.
X106a
X#ifdef notdef
X.
X102,104c
X	write(f, line, strlen(line));
X	write(f, buf, count);
X	return (rmtreply(f, "write"));
X.
X100a
X	if (rmtstate[f] == TS_CLOSED)
X		return (write(f, buf, count));
X.
X95c
Xrmtwrite(f, buf, count)
X	int f;
X.
X87c
X		cc = read(f, buf+i, n - i);
X.
X81c
X	n = rmtcall(f, "read", line);
X.
X79a
X	if (rmtstate[f] == TS_CLOSED)
X		return (read(f, buf, count));
X.
X72c
Xrmtread(f, buf, count)
X	int f;
X.
X66,69c
X	if (rmtstate[f] == TS_CLOSED)
X		return (close(f));
X	rmtcall(f, "close", "C\n");
X	rmtstate[f] = TS_CLOSED;
X	return (0);
X.
X63c
Xrmtclose(f)
X	int f;
X.
X58,60c
X	host = malloc(strlen(name) + 1);
X	strcpy(host, name);
X	tape = index(host, ':');
X	if (tape == NULL) {
X		/*
X		 * Security patches.  Open() pays attention to the effective uid
X		 *	even if the real uid is root.  If the real uid is root
X		 *	we can cause the effective uid to be root.  By going
X		 *	back to root as the effective uid, we allow ourselves
X		 *	to open a remote tape later on.  The only problem in
X		 *	this scheme is that the cpu time for the open() gets
X		 *	charged to root!
X		 */
X		setreuid(geteuid(), getuid());
X		f = open(name, mode, mask);
X		setreuid(geteuid(), getuid());
X		return (f);
X	}
X	*tape++ = '\0';
X	if (strncmp(tape, "/dev/rmt", 8) != 0 &&
X	    strncmp(tape, "/dev/mt", 7) != 0) {
X		errno = EACCES;
X		return (-1);
X	}
X	if ((f = rmthost(host)) < 0)
X		return (-1);
X
X	sprintf(buf, "O%s\n%d\n", tape, mode & 03);
X	if (rmtcall(f, tape, buf) < 0)
X		return (-1);
X	rmtstate[f] = TS_OPEN;
X	return (f);
X.
X56a
X	char *host, *tape;
X	char *index();
X	char *malloc();
X	extern int errno;
X	int f;
X.
X54a
X	int mask;
X.
X52,53c
X/*
X * rmtopen opens a tape device on the remote machine.  We assume that if a name
X *	has a colon in it, then it refers to a remote tape; otherwise it is
X *	caught and a normal operation is done on it.
X */
Xint
Xrmtopen(name, mode, mask)
X	char *name;
X.
X49c
X	return (rcmd(&rmtpeer, sp->s_port, pwd->pw_name, pwd->pw_name, "/etc/rmt", 0));
X.
X45c
X			fprintf(stderr, "shell/tcp: unknown service\n");
X.
X41a
X	if ((pwd = getpwuid(getuid())) == NULL) {
X		fprintf(stderr, "Who are you?\n");
X		exit(1);
X	}
X.
X40a
X	struct passwd *pwd;
X.
X37a
Xint
X.
X26,28c
X	if ((f = rmtgetconn()) < 0)
X		if (errno == 0)
X			errno = EACCES;
X	return (f);
X.
X22a
X	extern int errno;
X	int f;
X.
X19a
Xint
X.
X15,16c
Xstatic	int rmtstate[NOFILE];
X.
X11a
X#include <pwd.h>
X#include <errno.h>
X
X.
X7a
X#include <sys/socket.h>
X.
X2a
X/*
X * rsubs.c
X *
X * Handle protocol with remote 'rmt' program for 'rtar' and 'rdd'.
X * Stolen from 'rdump'.
X *
X * UCSD Chemistry modification history:
X *
X * $Log:	rsubs.c,v $
X * Revision 1.6  84/04/06  00:13:47  donn
X * Norm Seethoff of John Fluke Mfg. Co. sent in a fix to prevent users from
X * accessing remote tapes on systems for which they have no privileges; I
X * added a security hack to prevent local files from being opened while under
X * effective root uid and used the opportunity to provide a capability for
X * multiple remote tapes.  Also fixed some bugs which 'lint' found.
X * 
X * Revision 1.5  84/04/05  21:10:51  donn
X * Changed file protection scheme to flip real and effective uid's when opening
X * files -- it seems that one access() isn't enough to determine the
X * permissions we need and this method guarantees the correct outcome.
X * 
X * Revision 1.4  84/03/16  21:45:17  donn
X * The remote device name is now restricted to '/dev/rmt*' or '/dev/mt*' to
X * prevent 'rdd if=host:/usr/lib/uucp/L.sys' etc.  Quick and dirty.  Also
X * the error reporting has been changed -- EACCES is returned if the host
X * doesn't exist or if the remote device name was illegal.
X * 
X * Revision 1.3  84/03/16  18:46:18  donn
X * Attempted (again) to plug security holes.
X * 
X * Revision 1.2  84/03/16  17:22:25  donn
X * Made several small modifications.  It is permitted to use a non-remote
X * file (although only one remote file may be used).  Instead of making its
X * own complaints, the acknowledgement routine sets errno.  Tape ioctls are
X * handled correctly.  The bug in /etc/rmt regarding the 'S' message that
X * causes the status bytes to be handed back before the byte count is now
X * picked up and handled appropriately.
X * 
X */
X
X.
X1c
Xstatic	char *rcsid = "$Header: rsubs.c,v 1.6 84/04/06 00:13:47 donn Exp $";
X.
Xw
Xq
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 rsubs.script
	/bin/echo -n '	'; /bin/ls -ld rsubs.script
fi
/bin/echo 'Extracting rtar.script'
sed 's/^X//' <<'//go.sysin dd *' >rtar.script
X1151c
X		lastread = rmtread(fd, buf, size - count);
X.
X1144c
X		return (rmtread(fd, buf, size));
X.
X1132c
X	rmtwrite(mt, tbuf, TBLOCK*nblock);
X.
X1126c
X		rmtseek(mt, (long) -TBLOCK*nblock, 1);
X.
X1121c
X		if (rmtioctl(mt, MTIOCTOP, &mtop) < 0) {
X.
X1119c
X		mtdev = rmtioctl(mt, MTIOCGET, &mtget);
X.
X1103c
X		if (rmtwrite(mt, tbuf, TBLOCK*nblock) < 0) {
X.
X1095c
X		if (rmtwrite(mt, tbuf, TBLOCK*nblock) < 0) {
X.
X265a
X	setuid(getuid());
X.
X260,262c
X		fprintf(stderr, "tar: can't use local standard input\n");
X		fprintf(stderr, "tar: use 'tar' not 'rtar'\n");
X		done(1);
X	} else if ((mt = rmtopen(usefile, 0)) < 0) {
X.
X255a
X		setuid(getuid());
X.
X242,254c
X			fprintf(stderr, "tar: can't use remote standard output\n");
X			fprintf(stderr, "tar: use 'tar' not 'rtar'\n");
X			done(1);
X		} else if ((mt = rmtopen(usefile, 2)) < 0) {
X			fprintf(stderr, "tar: can't open remote tape\n");
X			done(1);
X.
X65c
Xint	mt = -1;
X.
X7a
X
X.
X6c
X * rtar.c
X *
X * Remote Tape Archival Program
X *
X * UCSD Chemistry modification history:
X *
X * $Log:	rtar.c,v $
X * Revision 1.3  84/04/06  00:10:03  donn
X * Fixed gaping security holes where setuid remained on after remote tape
X * was opened with a local file.
X * 
X * Revision 1.2  84/03/16  17:47:01  donn
X * Changed to use remote tape routines from rsubs.c.
X * 
X.
X2c
X/* static	char *sccsid = "@(#)tar.c	4.19 (Berkeley) 9/22/83"; */
Xstatic char *rcsid = "$Header: rtar.c,v 1.3 84/04/06 00:10:03 donn Exp $";
X.
Xw
Xq
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 rtar.script
	/bin/echo -n '	'; /bin/ls -ld rtar.script
fi