* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
* Remy Card <card@Linux.EU.Org>, 1994-1997
- * Stelian Pop <pop@cybercable.fr>, 1999
- *
+ * Stelian Pop <pop@noos.fr>, 1999-2000
+ * Stelian Pop <pop@noos.fr> - AlcĂ´ve <www.alcove.fr>, 2000
*/
/*-
*/
#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dumprmt.c 8.3 (Berkeley) 4/28/95";
-#endif
static const char rcsid[] =
- "$Id: dumprmt.c,v 1.2 1999/10/11 12:53:20 stelian Exp $";
+ "$Id: dumprmt.c,v 1.18 2001/08/13 16:17:52 stelian Exp $";
#endif /* not lint */
-#ifdef __linux__
-#include <sys/types.h>
-#include <linux/types.h>
-#endif
+#include <config.h>
#include <sys/param.h>
#include <sys/mtio.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifdef __linux__
+#include <sys/types.h>
+#ifdef HAVE_EXT2FS_EXT2_FS_H
+#include <ext2fs/ext2_fs.h>
+#else
#include <linux/ext2_fs.h>
+#endif
#include <bsdcompat.h>
#include <signal.h>
-#else
-#ifdef sunos
+#elif defined sunos
#include <sys/vnode.h>
#include <ufs/inode.h>
#else
#include <ufs/ufs/dinode.h>
#endif
-#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <protocols/dumprestore.h>
#include <ctype.h>
+#include <errno.h>
+#include <compaterr.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <ext2fs/ext2fs.h>
#endif
-#include "pathnames.h"
-#include "dump.h"
+#include <pathnames.h>
+#include "dump.h" /* for X_STARTUP, X_ABORT etc */
#define TS_CLOSED 0
#define TS_OPEN 1
static int rmtstate = TS_CLOSED;
-static int rmtape;
-static char *rmtpeer;
-
-static int okname __P((char *));
-static int rmtcall __P((char *, char *));
-static void rmtconnaborted __P((/* int, int */));
+static int tormtape = -1;
+static int fromrmtape = -1;
+int rshpid = -1;
+static const char *rmtpeer = 0;
+
+static int okname __P((const char *));
+static int rmtcall __P((const char *, const char *));
+static void rmtconnaborted __P((int));
static int rmtgetb __P((void));
-static void rmtgetconn __P((void));
-static void rmtgets __P((char *, int));
-static int rmtreply __P((char *));
+static int rmtgetconn __P((void));
+static void rmtgets __P((char *, size_t));
+static int rmtreply __P((const char *));
+static int piped_child __P((const char **command));
#ifdef KERBEROS
int krcmd __P((char **, int /*u_short*/, char *, char *, int *, char *));
#endif
static int errfd = -1;
extern int dokerberos;
extern int ntrec; /* blocking factor on tape */
+#ifndef errno
+extern int errno;
+#endif
int
-rmthost(host)
- char *host;
+rmthost(const char *host)
{
-
- rmtpeer = malloc(strlen(host) + 1);
if (rmtpeer)
- strcpy(rmtpeer, host);
- else
+ free((void *)rmtpeer);
+ if ((rmtpeer = strdup(host)) == NULL)
rmtpeer = host;
signal(SIGPIPE, rmtconnaborted);
- rmtgetconn();
- if (rmtape < 0)
- return (0);
- return (1);
+ return rmtgetconn();
}
static void
-rmtconnaborted()
+rmtconnaborted(int signo)
{
msg("Lost connection to remote host.\n");
if (errfd != -1) {
exit(X_ABORT);
}
-void
-rmtgetconn()
+static int
+rmtgetconn(void)
{
register char *cp;
register const char *rmt;
static struct servent *sp = NULL;
static struct passwd *pwd = NULL;
- char *tuser;
+ const char *tuser;
+ const char *rsh;
int size;
int throughput;
int on;
+ char *rmtpeercopy;
- if (sp == NULL) {
+ rsh = getenv("RSH");
+
+ if (!rsh && sp == NULL) {
sp = getservbyname(dokerberos ? "kshell" : "shell", "tcp");
- if (sp == NULL) {
- msg("%s/tcp: unknown service\n",
+ if (sp == NULL)
+ errx(1, "%s/tcp: unknown service",
dokerberos ? "kshell" : "shell");
- exit(X_STARTUP);
- }
+ }
+ if (pwd == NULL) {
pwd = getpwuid(getuid());
- if (pwd == NULL) {
- msg("who are you?\n");
- exit(X_STARTUP);
- }
+ if (pwd == NULL)
+ errx(1, "who are you?");
}
if ((cp = strchr(rmtpeer, '@')) != NULL) {
tuser = rmtpeer;
if ((rmt = getenv("RMT")) == NULL)
rmt = _PATH_RMT;
msg("");
+
+ if (rsh) {
+ const char *rshcmd[6];
+ rshcmd[0] = rsh;
+ rshcmd[1] = rmtpeer;
+ rshcmd[2] = "-l";
+ rshcmd[3] = tuser;
+ rshcmd[4] = rmt;
+ rshcmd[5] = NULL;
+
+ /* Restore the uid and gid. We really don't want
+ * to execute whatever is put into RSH variable with
+ * more priviledges than needed... */
+ setuid(getuid());
+ setgid(getgid());
+
+ if ((rshpid = piped_child(rshcmd)) < 0) {
+ msg("cannot open connection\n");
+ return 0;
+ }
+ }
+ else {
+ /* Copy rmtpeer to rmtpeercopy to ignore the
+ return value from rcmd. I cannot figure if
+ this is this a bug in rcmd or in my code... */
+ rmtpeercopy = (char *)rmtpeer;
#ifdef KERBEROS
- if (dokerberos)
- rmtape = krcmd(&rmtpeer, sp->s_port, tuser, rmt, &errfd,
- (char *)0);
- else
+ if (dokerberos)
+ tormtape = krcmd(&rmtpeercopy, sp->s_port, tuser, rmt, &errfd,
+ (char *)0);
+ else
#endif
- rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name,
- tuser, rmt, &errfd);
- if (rmtape < 0) {
- msg("login to %s as %s failed.\n", rmtpeer, tuser);
- return;
+ tormtape = rcmd(&rmtpeercopy, (u_short)sp->s_port, pwd->pw_name,
+ tuser, rmt, &errfd);
+ if (tormtape < 0) {
+ msg("login to %s as %s failed.\n", rmtpeer, tuser);
+ return 0;
+ }
+ size = ntrec * TP_BSIZE;
+ if (size > 60 * 1024) /* XXX */
+ size = 60 * 1024;
+ /* Leave some space for rmt request/response protocol */
+ size += 2 * 1024;
+ while (size > TP_BSIZE &&
+ setsockopt(tormtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
+ size -= TP_BSIZE;
+ (void)setsockopt(tormtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
+ throughput = IPTOS_THROUGHPUT;
+ if (setsockopt(tormtape, IPPROTO_IP, IP_TOS,
+ &throughput, sizeof(throughput)) < 0)
+ perror("IP_TOS:IPTOS_THROUGHPUT setsockopt");
+ on = 1;
+ if (setsockopt(tormtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
+ perror("TCP_NODELAY setsockopt");
+ fromrmtape = tormtape;
}
(void)fprintf(stderr, "Connection to %s established.\n", rmtpeer);
- size = ntrec * TP_BSIZE;
- if (size > 60 * 1024) /* XXX */
- size = 60 * 1024;
- /* Leave some space for rmt request/response protocol */
- size += 2 * 1024;
- while (size > TP_BSIZE &&
- setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
- size -= TP_BSIZE;
- (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
- throughput = IPTOS_THROUGHPUT;
- if (setsockopt(rmtape, IPPROTO_IP, IP_TOS,
- &throughput, sizeof(throughput)) < 0)
- perror("IP_TOS:IPTOS_THROUGHPUT setsockopt");
- on = 1;
- if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
- perror("TCP_NODELAY setsockopt");
+ return 1;
}
static int
-okname(cp0)
- char *cp0;
+okname(const char *cp0)
{
- register char *cp;
+ register const char *cp;
register int c;
for (cp = cp0; *cp; cp++) {
c = *cp;
if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
- msg("invalid user name %s\n", cp0);
+ warnx("invalid user name %s\n", cp0);
return (0);
}
}
}
int
-rmtopen(tape, mode)
- char *tape;
- int mode;
+rmtopen(const char *tape, int mode)
{
- char buf[256];
+ char buf[MAXPATHLEN];
- (void)snprintf(buf, sizeof (buf), "O%.226s\n%d\n", tape, mode);
+ (void)snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode);
rmtstate = TS_OPEN;
return (rmtcall(tape, buf));
}
void
-rmtclose()
+rmtclose(void)
{
if (rmtstate != TS_OPEN)
}
int
-rmtread(buf, count)
- char *buf;
- int count;
+rmtread(char *buf, size_t count)
{
char line[30];
- int n, i, cc;
+ int n, i;
+ ssize_t cc;
- (void)snprintf(line, sizeof (line), "R%d\n", count);
+ (void)snprintf(line, sizeof (line), "R%u\n", (unsigned)count);
n = rmtcall("read", line);
if (n < 0)
/* rmtcall() properly sets errno for us on errors. */
return (n);
for (i = 0; i < n; i += cc) {
- cc = read(rmtape, buf+i, n - i);
+ cc = read(fromrmtape, buf+i, n - i);
if (cc <= 0)
- rmtconnaborted();
+ rmtconnaborted(0);
}
return (n);
}
int
-rmtwrite(buf, count)
- char *buf;
- int count;
+rmtwrite(const char *buf, size_t count)
{
char line[30];
- (void)snprintf(line, sizeof (line), "W%d\n", count);
- write(rmtape, line, strlen(line));
- write(rmtape, buf, count);
+ (void)snprintf(line, sizeof (line), "W%ld\n", (long)count);
+ write(tormtape, line, strlen(line));
+ write(tormtape, buf, count);
return (rmtreply("write"));
}
-void
-rmtwrite0(count)
- int count;
-{
- char line[30];
-
- (void)snprintf(line, sizeof (line), "W%d\n", count);
- write(rmtape, line, strlen(line));
-}
-
-void
-rmtwrite1(buf, count)
- char *buf;
- int count;
-{
-
- write(rmtape, buf, count);
-}
-
int
-rmtwrite2()
-{
-
- return (rmtreply("write"));
-}
-
-int
-rmtseek(offset, pos)
- int offset, pos;
+rmtseek(int offset, int pos)
{
char line[80];
struct mtget mts;
struct mtget *
-rmtstatus()
+rmtstatus(void)
{
register int i;
register char *cp;
}
int
-rmtioctl(cmd, count)
- int cmd, count;
+rmtioctl(int cmd, int count)
{
char buf[256];
}
static int
-rmtcall(cmd, buf)
- char *cmd, *buf;
+rmtcall(const char *cmd, const char *buf)
{
- if (write(rmtape, buf, strlen(buf)) != strlen(buf))
- rmtconnaborted();
+ if (write(tormtape, buf, strlen(buf)) != strlen(buf))
+ rmtconnaborted(0);
return (rmtreply(cmd));
}
static int
-rmtreply(cmd)
- char *cmd;
+rmtreply(const char *cmd)
{
register char *cp;
char code[30], emsg[BUFSIZ];
- extern int errno;
rmtgets(code, sizeof (code));
if (*code == 'E' || *code == 'F') {
msg("Protocol to remote tape server botched (code \"%s\").\n",
code);
- rmtconnaborted();
+ rmtconnaborted(0);
}
return (atoi(code + 1));
}
-int
-rmtgetb()
+static int
+rmtgetb(void)
{
char c;
- if (read(rmtape, &c, 1) != 1)
- rmtconnaborted();
+ if (read(fromrmtape, &c, 1) != 1)
+ rmtconnaborted(0);
return (c);
}
/* Get a line (guaranteed to have a trailing newline). */
-void
-rmtgets(line, len)
- char *line;
- int len;
+static void
+rmtgets(char *line, size_t len)
{
register char *cp = line;
*cp = '\0';
msg("Protocol to remote tape server botched.\n");
msg("(rmtgets got \"%s\").\n", line);
- rmtconnaborted();
+ rmtconnaborted(0);
+}
+
+int piped_child(const char **command) {
+ int pid;
+ int to_child_pipe[2];
+ int from_child_pipe[2];
+
+ if (pipe (to_child_pipe) < 0) {
+ msg ("cannot create pipe: %s\n", strerror(errno));
+ return -1;
+ }
+ if (pipe (from_child_pipe) < 0) {
+ msg ("cannot create pipe: %s\n", strerror(errno));
+ return -1;
+ }
+ pid = fork ();
+ if (pid < 0) {
+ msg ("cannot fork: %s\n", strerror(errno));
+ return -1;
+ }
+ if (pid == 0) {
+ if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) {
+ msg ("cannot dup2 pipe: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (close (to_child_pipe[1]) < 0) {
+ msg ("cannot close pipe: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (close (from_child_pipe[0]) < 0) {
+ msg ("cannot close pipe: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) {
+ msg ("cannot dup2 pipe: %s\n", strerror(errno));
+ exit(1);
+ }
+ setpgid(0, getpid());
+ execvp (command[0], (char *const *) command);
+ msg("cannot exec %s: %s\n", command[0], strerror(errno));
+ exit(1);
+ }
+ if (close (to_child_pipe[0]) < 0) {
+ msg ("cannot close pipe: %s\n", strerror(errno));
+ return -1;
+ }
+ if (close (from_child_pipe[1]) < 0) {
+ msg ("cannot close pipe: %s\n", strerror(errno));
+ return -1;
+ }
+ tormtape = to_child_pipe[1];
+ fromrmtape = from_child_pipe[0];
+ return pid;
}