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