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>