Date: Sun, 2 Jan 2000 02:59:34 +0100 (CET) From: Christian Weisgerber <naddy@mips.rhein-neckar.de> To: FreeBSD-gnats-submit@freebsd.org Subject: bin/15830: PATCH: rdump over ssh Message-ID: <200001020159.CAA88226@bigeye.rhein-neckar.de>
next in thread | raw e-mail | index | archive | help
>Number: 15830
>Category: bin
>Synopsis: PATCH: rdump over ssh
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sat Jan 1 18:10:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator: Christian Weisgerber
>Release: FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:
>Description:
The included patch adds to dump/restore the capability to access
tape devices on remote hosts over an arbitrary rsh-like program.
In particular, this is intended to allow the use of ssh.
Currently, dump/restore offer remote tape access using rcmd(3) to
call rmt on the remote host. This patch adds a flag "-P <rshcmd>"
to spawn a coprocess using <rshcmd>, in lieu of rcmd(3). "-P" was
chosen because it is used for the same purpose by rdist(1). Most
of the actual code has been taken from rdist, too.
Issues:
* The biggest chunk of the patch is the addition of a dump/rshrcmd.c
module, which is almost literally copied from rdist/rshrcmd.c.
Alas, the latter can't be used directly. The module adds the
function rshrcmd(), which is mostly a drop-in replacement for
rcmd(), transparently calling a rsh-like program.
- rdist uses a local function error() to display error messages,
dump uses msg(). This could be handled by compiling with
-Derror=msg or by adding error() as wrapper for msg(). Both
solutions appear questionable to me.
- If the operator presses the interrupt character (^C), SIGINT
is delivered to all processes in the foreground process group.
The five processes spawned by the dump command variously catch
or ignore SIGINT. The operator is offered a choice of aborting
or continuing the dump run. Alas, the coprocess also receives
the SIGINT, and ssh apparently installs a handler and terminates
on SIGINT, so the whole dump run would always abort on interrupt.
Diverging from the rdist code, I solved this by putting the
coprocess in its own process group. I'm not sure I fully
understand all the consequences of this, but it works. An
interrupt doesn't kill the dump run, and if I forcefully
terminate dump, the coprocess dies along with it.
* rshrcmd() doesn't really handle rcmd()'s final "fd2p" argument.
Adding this appears to be rather complex, judging by the rcmd
code. Considering the limited use (added post 4.4Lite) this sees
in dump, I think it is a negligible omission.
* I didn't add "#ifdef RDUMP" around the changes, since I couldn't
decide whether this is appropriate.
>How-To-Repeat:
Usage example:
$ dump 0aPf ssh host:/dev/nrsa0 /
>Fix:
diff -u -uNr /usr/src/sbin/dump/Makefile dump/Makefile
--- /usr/src/sbin/dump/Makefile Tue Oct 26 21:47:56 1999
+++ dump/Makefile Sat Jan 1 20:06:13 2000
@@ -17,7 +17,8 @@
LINKS= ${BINDIR}/dump ${BINDIR}/rdump
CFLAGS+=-DRDUMP
CFLAGS+=-I${.CURDIR}/../../libexec/rlogind
-SRCS= itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c
+SRCS= itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c \
+ rshrcmd.c
BINGRP= tty
BINMODE=2555
MAN8= dump.8
diff -u -uNr /usr/src/sbin/dump/dump.8 dump/dump.8
--- /usr/src/sbin/dump/dump.8 Sat Sep 11 03:51:55 1999
+++ dump/dump.8 Sat Jan 1 22:18:54 2000
@@ -47,6 +47,7 @@
.Op Fl d Ar density
.Op Fl f Ar file
.Op Fl h Ar level
+.Op Fl P Ar rshcmd
.Op Fl s Ar feet
.Op Fl T Ar date
.Ar filesystem
@@ -177,6 +178,13 @@
.Dq operator
by means similar to a
.Xr wall 1 .
+.It Fl P Ar rshcmd
+Program to provide
+.Xr rsh 1 -like Ns
+transport to the remote tape server.
+It must provide a binary-transparent path to the remote host
+and must have a command argument syntax that is compatible with
+.Xr rsh 1 .
.It Fl s Ar feet
Attempt to calculate the amount of tape needed
at a particular density.
diff -u -uNr /usr/src/sbin/dump/dump.h dump/dump.h
--- /usr/src/sbin/dump/dump.h Tue Jul 14 11:19:45 1998
+++ dump/dump.h Sat Jan 1 20:42:34 2000
@@ -102,7 +102,7 @@
void timeest __P((void));
time_t unctime __P((char *str));
-/* mapping rouintes */
+/* mapping routines */
struct dinode;
long blockest __P((struct dinode *dp));
int mapfiles __P((ino_t maxino, long *tapesize));
@@ -137,6 +137,8 @@
int rmtopen __P((char *tape, int mode));
int rmtwrite __P((char *buf, int count));
#endif /* RDUMP */
+int rshrcmd __P((char **ahost, u_short port, char *luser, char *ruser,
+ char *cmd, int *fd2p));
void interrupt __P((int signo)); /* in case operator bangs on console */
diff -u -uNr /usr/src/sbin/dump/dumprmt.c dump/dumprmt.c
--- /usr/src/sbin/dump/dumprmt.c Sat Sep 11 03:51:55 1999
+++ dump/dumprmt.c Sat Jan 1 20:36:52 2000
@@ -92,6 +92,7 @@
static int errfd = -1;
extern int dokerberos;
extern int ntrec; /* blocking factor on tape */
+extern char *path_rsh;
int
rmthost(host)
@@ -141,7 +142,7 @@
rmtgetconn()
{
register char *cp;
- register const char *rmt;
+ register char *rmt;
static struct servent *sp = NULL;
static struct passwd *pwd = NULL;
char *tuser;
@@ -173,6 +174,10 @@
if ((rmt = getenv("RMT")) == NULL)
rmt = _PATH_RMT;
msg("");
+ if (path_rsh)
+ rmtape = rshrcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name,
+ tuser, rmt, 0);
+ else
#ifdef KERBEROS
if (dokerberos)
rmtape = krcmd(&rmtpeer, sp->s_port, tuser, rmt, &errfd,
@@ -186,6 +191,8 @@
return;
}
(void)fprintf(stderr, "Connection to %s established.\n", rmtpeer);
+ if (path_rsh)
+ return;
size = ntrec * TP_BSIZE;
if (size > 60 * 1024) /* XXX */
size = 60 * 1024;
diff -u -uNr /usr/src/sbin/dump/main.c dump/main.c
--- /usr/src/sbin/dump/main.c Sat Sep 11 03:51:55 1999
+++ dump/main.c Sat Jan 1 22:11:40 2000
@@ -86,6 +86,7 @@
long dev_bsize = 1; /* recalculated below */
long blocksperfile; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
+char *path_rsh = NULL; /* rsh (or equiv command) path */
static long numarg __P((char *, long, long));
static void obsolete __P((int *, char **[]));
@@ -122,9 +123,9 @@
obsolete(&argc, &argv);
#ifdef KERBEROS
-#define optstring "0123456789aB:b:cd:f:h:kns:T:uWw"
+#define optstring "0123456789aB:b:cd:f:h:knP:s:T:uWw"
#else
-#define optstring "0123456789aB:b:cd:f:h:ns:T:uWw"
+#define optstring "0123456789aB:b:cd:f:h:nP:s:T:uWw"
#endif
while ((ch = getopt(argc, argv, optstring)) != -1)
#undef optstring
@@ -177,6 +178,10 @@
notify = 1;
break;
+ case 'P':
+ path_rsh = optarg;
+ break;
+
case 's': /* tape size, feet */
tsize = numarg("tape size", 1L, 0L) * 12 * 10;
break;
@@ -491,7 +496,8 @@
"k"
#endif
"nu] [-B records] [-b blocksize] [-d density] [-f file]\n"
- " [-h level] [-s feet] [-T date] filesystem\n"
+ " [-h level] [-P rshcmd] [-s feet] [-T date] "
+ "filesystem\n"
" dump [-W | -w]\n");
exit(X_STARTUP);
}
@@ -598,6 +604,7 @@
case 'd':
case 'f':
case 'h':
+ case 'P':
case 's':
case 'T':
if (*argv == NULL) {
diff -u -uNr /usr/src/sbin/dump/rshrcmd.c dump/rshrcmd.c
--- /usr/src/sbin/dump/rshrcmd.c Thu Jan 1 01:00:00 1970
+++ dump/rshrcmd.c Sat Jan 1 22:05:35 2000
@@ -0,0 +1,110 @@
+
+/*
+ * This is an rcmd() replacement originally by
+ * Chris Siebenmann <cks@utcc.utoronto.ca>.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dump.h"
+
+extern char *path_rsh;
+
+static char *
+xbasename(s)
+ char *s;
+{
+ char *ret;
+
+ ret = strrchr(s, '/');
+ if (ret && ret[1])
+ return (ret + 1);
+ return s;
+}
+
+
+/*
+ * This is a replacement rcmd() function that uses the rsh(1c)
+ * program in place of a direct rcmd() function call so as to
+ * avoid having to be root.
+ */
+int
+rshrcmd(ahost, port, luser, ruser, cmd, fd2p)
+ char **ahost;
+ u_short port;
+ char *luser, *ruser, *cmd;
+ int *fd2p;
+{
+ int cpid;
+ struct hostent *hp;
+ int sp[2];
+
+ /* insure that we are indeed being used as we thought. */
+ if (fd2p != 0)
+ return -1;
+ /* validate remote hostname. */
+ hp = gethostbyname(*ahost);
+ if (hp == 0) {
+ msg("%s: unknown host", *ahost);
+ return -1;
+ }
+ *ahost = hp->h_name; /* This makes me nervous. */
+
+ /* get a socketpair we'll use for stdin and stdout. */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+ msg("socketpair(AF_UNIX, SOCK_STREAM, 0) failed: %s.",
+ strerror(errno));
+ return -1;
+ }
+
+ cpid = fork();
+ if (cpid < 0) {
+ msg("fork failed: %s.", strerror(errno));
+ return -1; /* error. */
+ }
+ if (cpid == 0) {
+ /* child. we use sp[1] to be stdin/stdout, and close
+ sp[0]. */
+ (void) close(sp[0]);
+ if (dup2(sp[1], 0) < 0 || dup2(0,1) < 0) {
+ msg("dup2 failed: %s.", strerror(errno));
+ _exit(255);
+ }
+ /* fork again to lose parent. */
+ cpid = fork();
+ if (cpid < 0) {
+ msg("fork to lose parent failed: %s.", strerror(errno));
+ _exit(255);
+ }
+ if (cpid > 0)
+ _exit(0);
+ /* in grandchild here. */
+ setpgid(0, getpid()); /* run in background */
+ execlp(path_rsh, xbasename(path_rsh),
+ *ahost, "-l", ruser, cmd, (char *) NULL);
+ msg("execlp %s failed: %s.", path_rsh, strerror(errno));
+ _exit(255);
+ }
+ if (cpid > 0) {
+ /* parent. close sp[1], return sp[0]. */
+ (void) close(sp[1]);
+ /* reap child. */
+ (void) wait(0);
+ return sp[0];
+ }
+ /*NOTREACHED*/
+ return (-1);
+}
diff -u -uNr /usr/src/sbin/restore/Makefile restore/Makefile
--- /usr/src/sbin/restore/Makefile Tue Oct 26 21:48:16 1999
+++ restore/Makefile Sat Jan 1 22:06:28 2000
@@ -6,7 +6,7 @@
CFLAGS+=-DRRESTORE
CFLAGS+=-I${.CURDIR}/../../libexec/rlogind
SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c \
- dumprmt.c
+ dumprmt.c rshrcmd.c
BINGRP= tty
BINMODE=2555
MAN8= restore.8
diff -u -uNr /usr/src/sbin/restore/main.c restore/main.c
--- /usr/src/sbin/restore/main.c Sat Sep 11 03:52:25 1999
+++ restore/main.c Sat Jan 1 22:12:13 2000
@@ -74,6 +74,7 @@
time_t dumptime;
time_t dumpdate;
FILE *terminal;
+char *path_rsh = NULL;
static void obsolete __P((int *, char **[]));
static void usage __P((void));
@@ -99,9 +100,9 @@
inputdev = _PATH_DEFTAPE;
obsolete(&argc, &argv);
#ifdef KERBEROS
-#define optlist "b:cdf:hikmNRrs:tuvxy"
+#define optlist "b:cdf:hikmNP:Rrs:tuvxy"
#else
-#define optlist "b:cdf:himNRrs:tuvxy"
+#define optlist "b:cdf:himNP:Rrs:tuvxy"
#endif
while ((ch = getopt(argc, argv, optlist)) != -1)
switch(ch) {
@@ -148,6 +149,9 @@
case 'N':
Nflag = 1;
break;
+ case 'P':
+ path_rsh = optarg;
+ break;
case 's':
/* Dumpnum (skip to) for multifile dump tapes. */
dumpnum = strtol(optarg, &p, 10);
@@ -292,12 +296,14 @@
static void
usage()
{
- (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
- "restore -i [-chkmuvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -r [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -R [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
- "restore -x [-chkmuvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
- "restore -t [-chkuvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
+ (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
+ "restore -i [-chkmuvy] [-b blocksize] [-f file] [-P rshcmd] [-s fileno]",
+ "restore -r [-ckuvy] [-b blocksize] [-f file] [-P rshcmd] [-s fileno]",
+ "restore -R [-ckuvy] [-b blocksize] [-f file] [-P rshcmd] [-s fileno]",
+ "restore -x [-chkmuvy] [-b blocksize] [-f file] [-P rshcmd] [-s fileno]",
+ " [file ...]",
+ "restore -t [-chkuvy] [-b blocksize] [-f file] [-P rshcmd] [-s fileno]",
+ " [file ...]");
done(1);
}
@@ -335,6 +341,7 @@
switch (*ap) {
case 'b':
case 'f':
+ case 'P':
case 's':
if (*argv == NULL) {
warnx("option requires an argument -- %c", *ap);
diff -u -uNr /usr/src/sbin/restore/restore.8 restore/restore.8
--- /usr/src/sbin/restore/restore.8 Sat Sep 11 03:52:25 1999
+++ restore/restore.8 Sat Jan 1 22:19:10 2000
@@ -44,24 +44,28 @@
.Op Fl chkmuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
+.Op Fl P Ar rshcmd
.Op Fl s Ar fileno
.Nm restore
.Fl R
.Op Fl ckuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
+.Op Fl P Ar rshcmd
.Op Fl s Ar fileno
.Nm restore
.Fl r
.Op Fl ckuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
+.Op Fl P Ar rshcmd
.Op Fl s Ar fileno
.Nm restore
.Fl t
.Op Fl chkuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
+.Op Fl P Ar rshcmd
.Op Fl s Ar fileno
.Op file ...
.Nm restore
@@ -69,6 +73,7 @@
.Op Fl chkmuvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
+.Op Fl P Ar rshcmd
.Op Fl s Ar fileno
.Op file ...
.Pp
@@ -311,6 +316,13 @@
This is useful if only a few files are being extracted,
and one wants to avoid regenerating the complete pathname
to the file.
+.It Fl P Ar rshcmd
+Program to provide
+.Xr rsh 1 -like Ns
+transport to the remote tape server.
+It must provide a binary-transparent path to the remote host
+and must have a command argument syntax that is compatible with
+.Xr rsh 1 .
.It Fl s Ar fileno
Read from the specified
.Ar fileno
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200001020159.CAA88226>
