+static char *sccsid = "@(#)dumprmt.c 1.1 (Berkeley) %G%";
+#include "dump.h"
+
+#include <sys/mtio.h>
+#include <sys/ioctl.h>
+#include <net/in.h>
+
+#define TS_CLOSED 0
+#define TS_OPEN 1
+
+static int rmtstate = TS_CLOSED;
+int rmtape;
+int rmtconnaborted();
+char *rmtpeer;
+
+rmthost(host)
+ char *host;
+{
+
+ rmtpeer = host;
+ sigset(SIGPIPE, rmtconnaborted);
+ rmtgetconn();
+ if (rmtape < 0)
+ rmtreconnect();
+}
+
+rmtconnaborted()
+{
+
+ msg("Lost connection to tape server.\n");
+ if (rmtape >= 0) {
+ close(rmtape);
+ rmtape = -1;
+ }
+ exit(X_REWRITE);
+}
+
+rmtreconnect()
+{
+
+ do {
+ if (query("Retry conection to remote host?") == 0)
+ exit(X_ABORT);
+ rmtgetconn();
+ } while (rmtape < 0);
+}
+
+rmtgetconn()
+{
+
+ rmtape = rcmd(&rmtpeer, IPPORT_CMDSERVER,
+ "root", "root", "/etc/rmt", 0);
+}
+
+rmtopen(tape, mode)
+ char *tape;
+ int mode;
+{
+ char buf[256];
+
+ sprintf(buf, "O%s\n%d\n", tape, mode);
+ rmtcall(tape, buf);
+ rmtstate = TS_OPEN;
+}
+
+rmtclose()
+{
+
+ if (rmtstate != TS_OPEN)
+ return;
+ rmtcall("close", "C\n");
+ rmtstate = TS_CLOSED;
+}
+
+rmtread(buf, count)
+ char *buf;
+ int count;
+{
+ char line[30];
+ int n, i, cc;
+
+ sprintf(line, "R%d\n", count);
+ n = rmtcall("read", line);
+ if (n < 0)
+ return (-1);
+ for (i = 0; i < n; i += cc) {
+ cc = read(rmtape, buf+i, n - i);
+ if (cc <= 0)
+ rmtconnaborted();
+ }
+ return (n);
+}
+
+rmtwrite(buf, count)
+ char *buf;
+ int count;
+{
+ char line[30];
+
+ sprintf(line, "W%d\n", count);
+ write(rmtape, line, strlen(line));
+ write(rmtape, buf, count);
+ return (rmtreply("write"));
+}
+
+rmtwrite0(count)
+ int count;
+{
+ char line[30];
+
+ sprintf(line, "W%d\n", count);
+ write(rmtape, line, strlen(line));
+}
+
+rmtwrite1(buf, count)
+ char *buf;
+ int count;
+{
+
+ write(rmtape, buf, count);
+}
+
+rmtwrite2()
+{
+ int i;
+
+ return (rmtreply("write"));
+}
+
+rmtseek(offset, pos)
+ int offset, pos;
+{
+ char line[80];
+
+ sprintf(line, "L%d\n%d\n", offset, pos);
+ return (rmtcall("seek", line));
+}
+
+struct mtget mts;
+
+struct mtget *
+rmtstatus()
+{
+ register int i;
+ register char *cp;
+
+ if (rmtstate != TS_OPEN)
+ return (0);
+ rmtcall("status", "S\n");
+ for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
+ *cp++ = rmtgetb();
+ return (&mts);
+}
+
+rmtioctl(cmd, count)
+ int cmd, count;
+{
+ char buf[256];
+
+ if (count < 0)
+ return (-1);
+ sprintf(buf, "I%d\n%d\n", cmd, count);
+ rmtcall("ioctl", buf);
+}
+
+rmtcall(cmd, buf)
+ char *cmd, *buf;
+{
+
+ if (write(rmtape, buf, strlen(buf)) != strlen(buf))
+ rmtconnaborted();
+ return (rmtreply(cmd));
+}
+
+rmtreply(cmd)
+ char *cmd;
+{
+ register int c;
+ char code[30], emsg[BUFSIZ];
+
+ rmtgets(code, sizeof (code));
+ if (*code == 'E' || *code == 'F') {
+ rmtgets(emsg, sizeof (emsg));
+ msg("%s: %s\n", cmd, emsg, code + 1);
+ if (*code == 'F') {
+ rmtstate = TS_CLOSED;
+ return (-1);
+ }
+ return (-1);
+ }
+ if (*code != 'A') {
+ msg("Protocol to remote tape server botched (code %s?).\n",
+ code);
+ rmtconnaborted();
+ }
+ return (atoi(code + 1));
+}
+
+rmtgetb()
+{
+ char c;
+
+ if (read(rmtape, &c, 1) != 1)
+ rmtconnaborted();
+ return (c);
+}
+
+rmtgets(cp, len)
+ char *cp;
+ int len;
+{
+
+ while (len > 1) {
+ *cp = rmtgetb();
+ if (*cp == '\n') {
+ cp[1] = 0;
+ return;
+ }
+ cp++;
+ len--;
+ }
+ msg("Protocol to remote tape server botched (in rmtgets).\n");
+ rmtconnaborted();
+}