xref: /csrg-svn/sbin/dump/dumprmt.c (revision 59924)
147082Smckusick /*-
247082Smckusick  * Copyright (c) 1980 The Regents of the University of California.
347082Smckusick  * All rights reserved.
447082Smckusick  *
547082Smckusick  * %sccs.include.redist.c%
622039Sdist  */
76645Ssam 
822039Sdist #ifndef lint
9*59924Storek static char sccsid[] = "@(#)dumprmt.c	5.18 (Berkeley) 05/11/93";
1046587Storek #endif /* not lint */
1122039Sdist 
126884Ssam #include <sys/param.h>
136645Ssam #include <sys/mtio.h>
146645Ssam #include <sys/ioctl.h>
1517538Sralph #include <sys/socket.h>
1657724Smckusick #include <sys/time.h>
1757724Smckusick #ifdef sunos
1857724Smckusick #include <sys/vnode.h>
1957724Smckusick 
2057724Smckusick #include <ufs/inode.h>
2150498Smckusick #else
2257724Smckusick #include <ufs/ufs/dinode.h>
2350498Smckusick #endif
246645Ssam 
259306Ssam #include <netinet/in.h>
2657724Smckusick #include <netinet/tcp.h>
279306Ssam 
2857724Smckusick #include <protocols/dumprestore.h>
2957724Smckusick 
3057724Smckusick #include <ctype.h>
319306Ssam #include <netdb.h>
3237946Sbostic #include <pwd.h>
3357724Smckusick #include <signal.h>
3457724Smckusick #include <stdio.h>
3546795Sbostic #ifdef __STDC__
3646587Storek #include <stdlib.h>
3746587Storek #include <string.h>
3857724Smckusick #include <unistd.h>
3946795Sbostic #endif
4057724Smckusick 
4137946Sbostic #include "pathnames.h"
4257724Smckusick #include "dump.h"
439306Ssam 
446645Ssam #define	TS_CLOSED	0
456645Ssam #define	TS_OPEN		1
466645Ssam 
476645Ssam static	int rmtstate = TS_CLOSED;
4857724Smckusick static	int rmtape;
4957724Smckusick static	char *rmtpeer;
506645Ssam 
5157724Smckusick static	int okname __P((char *));
5257724Smckusick static	int rmtcall __P((char *, char *));
5357724Smckusick static	void rmtconnaborted __P((/* int, int */));
5457724Smckusick static	int rmtgetb __P((void));
5557724Smckusick static	void rmtgetconn __P((void));
5657724Smckusick static	void rmtgets __P((char *, int));
5757724Smckusick static	int rmtreply __P((char *));
5817538Sralph 
5957724Smckusick extern	int ntrec;		/* blocking factor on tape */
6054044Smckusick 
6146587Storek int
626645Ssam rmthost(host)
636645Ssam 	char *host;
646645Ssam {
656645Ssam 
6657724Smckusick 	rmtpeer = malloc(strlen(host) + 1);
6757724Smckusick 	if (rmtpeer)
6857724Smckusick 		strcpy(rmtpeer, host);
6957724Smckusick 	else
7057724Smckusick 		rmtpeer = host;
7113032Ssam 	signal(SIGPIPE, rmtconnaborted);
726645Ssam 	rmtgetconn();
736645Ssam 	if (rmtape < 0)
7417538Sralph 		return (0);
7517538Sralph 	return (1);
766645Ssam }
776645Ssam 
7857724Smckusick static void
796645Ssam rmtconnaborted()
806645Ssam {
816645Ssam 
8254044Smckusick 	(void) fprintf(stderr, "rdump: Lost connection to remote host.\n");
8357724Smckusick 	exit(1);
846645Ssam }
856645Ssam 
8646587Storek void
876645Ssam rmtgetconn()
886645Ssam {
8957724Smckusick 	register char *cp;
90*59924Storek 	static struct servent *sp = NULL;
91*59924Storek 	static struct passwd *pwd = NULL;
9257724Smckusick #ifdef notdef
9357724Smckusick 	static int on = 1;
9457724Smckusick #endif
9557724Smckusick 	char *tuser;
9617538Sralph 	int size;
9757724Smckusick 	int maxseg;
986645Ssam 
99*59924Storek 	if (sp == NULL) {
1009306Ssam 		sp = getservbyname("shell", "tcp");
101*59924Storek 		if (sp == NULL) {
10254044Smckusick 			(void) fprintf(stderr,
10354044Smckusick 			    "rdump: shell/tcp: unknown service\n");
10457724Smckusick 			exit(1);
1059306Ssam 		}
10657724Smckusick 		pwd = getpwuid(getuid());
107*59924Storek 		if (pwd == NULL) {
10857724Smckusick 			(void) fprintf(stderr, "rdump: who are you?\n");
10957724Smckusick 			exit(1);
11057724Smckusick 		}
1119306Ssam 	}
112*59924Storek 	if ((cp = index(rmtpeer, '@')) != NULL) {
11357724Smckusick 		tuser = rmtpeer;
11457724Smckusick 		*cp = '\0';
11557724Smckusick 		if (!okname(tuser))
11657724Smckusick 			exit(1);
11757724Smckusick 		rmtpeer = ++cp;
11857724Smckusick 	} else
11957724Smckusick 		tuser = pwd->pw_name;
12057724Smckusick 	rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
12157724Smckusick 	    _PATH_RMT, (int *)0);
12217538Sralph 	size = ntrec * TP_BSIZE;
12357724Smckusick 	if (size > 60 * 1024)		/* XXX */
12457724Smckusick 		size = 60 * 1024;
12557724Smckusick 	/* Leave some space for rmt request/response protocol */
12657724Smckusick 	size += 2 * 1024;
12718493Smckusick 	while (size > TP_BSIZE &&
12818493Smckusick 	    setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
12957724Smckusick 		    size -= TP_BSIZE;
13057724Smckusick 	(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
13157724Smckusick 	maxseg = 1024;
13257724Smckusick 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
13357724Smckusick 	    &maxseg, sizeof (maxseg)) < 0)
13457724Smckusick 		perror("TCP_MAXSEG setsockopt");
13557724Smckusick 
13657724Smckusick #ifdef notdef
13757724Smckusick 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
13857724Smckusick 		perror("TCP_NODELAY setsockopt");
13957724Smckusick #endif
1406645Ssam }
1416645Ssam 
14257724Smckusick static int
14357724Smckusick okname(cp0)
14457724Smckusick 	char *cp0;
14557724Smckusick {
14657724Smckusick 	register char *cp;
14757724Smckusick 	register int c;
14857724Smckusick 
14957724Smckusick 	for (cp = cp0; *cp; cp++) {
15057724Smckusick 		c = *cp;
15157724Smckusick 		if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
15257724Smckusick 			(void) fprintf(stderr, "rdump: invalid user name %s\n",
15357724Smckusick 			    cp0);
15457724Smckusick 			return (0);
15557724Smckusick 		}
15657724Smckusick 	}
15757724Smckusick 	return (1);
15857724Smckusick }
15957724Smckusick 
16046587Storek int
1616645Ssam rmtopen(tape, mode)
1626645Ssam 	char *tape;
1636645Ssam 	int mode;
1646645Ssam {
1656645Ssam 	char buf[256];
1666645Ssam 
16732455Sbostic 	(void)sprintf(buf, "O%s\n%d\n", tape, mode);
1686645Ssam 	rmtstate = TS_OPEN;
16924836Smckusick 	return (rmtcall(tape, buf));
1706645Ssam }
1716645Ssam 
17246587Storek void
1736645Ssam rmtclose()
1746645Ssam {
1756645Ssam 
1766645Ssam 	if (rmtstate != TS_OPEN)
1776645Ssam 		return;
1786645Ssam 	rmtcall("close", "C\n");
1796645Ssam 	rmtstate = TS_CLOSED;
1806645Ssam }
1816645Ssam 
18246587Storek int
1836645Ssam rmtread(buf, count)
1846645Ssam 	char *buf;
1856645Ssam 	int count;
1866645Ssam {
1876645Ssam 	char line[30];
1886645Ssam 	int n, i, cc;
1896884Ssam 	extern errno;
1906645Ssam 
19132455Sbostic 	(void)sprintf(line, "R%d\n", count);
1926645Ssam 	n = rmtcall("read", line);
1936884Ssam 	if (n < 0) {
1946884Ssam 		errno = n;
1956645Ssam 		return (-1);
1966884Ssam 	}
1976645Ssam 	for (i = 0; i < n; i += cc) {
1986645Ssam 		cc = read(rmtape, buf+i, n - i);
1996884Ssam 		if (cc <= 0) {
2006645Ssam 			rmtconnaborted();
2016884Ssam 		}
2026645Ssam 	}
2036645Ssam 	return (n);
2046645Ssam }
2056645Ssam 
20646587Storek int
2076645Ssam rmtwrite(buf, count)
2086645Ssam 	char *buf;
2096645Ssam 	int count;
2106645Ssam {
2116645Ssam 	char line[30];
2126645Ssam 
21332455Sbostic 	(void)sprintf(line, "W%d\n", count);
2146645Ssam 	write(rmtape, line, strlen(line));
2156645Ssam 	write(rmtape, buf, count);
2166645Ssam 	return (rmtreply("write"));
2176645Ssam }
2186645Ssam 
21946587Storek void
2206645Ssam rmtwrite0(count)
2216645Ssam 	int count;
2226645Ssam {
2236645Ssam 	char line[30];
2246645Ssam 
22532455Sbostic 	(void)sprintf(line, "W%d\n", count);
2266645Ssam 	write(rmtape, line, strlen(line));
2276645Ssam }
2286645Ssam 
22946587Storek void
2306645Ssam rmtwrite1(buf, count)
2316645Ssam 	char *buf;
2326645Ssam 	int count;
2336645Ssam {
2346645Ssam 
2356645Ssam 	write(rmtape, buf, count);
2366645Ssam }
2376645Ssam 
23846587Storek int
2396645Ssam rmtwrite2()
2406645Ssam {
2416645Ssam 
2426645Ssam 	return (rmtreply("write"));
2436645Ssam }
2446645Ssam 
24546587Storek int
2466645Ssam rmtseek(offset, pos)
2476645Ssam 	int offset, pos;
2486645Ssam {
2496645Ssam 	char line[80];
2506645Ssam 
25132455Sbostic 	(void)sprintf(line, "L%d\n%d\n", offset, pos);
2526645Ssam 	return (rmtcall("seek", line));
2536645Ssam }
2546645Ssam 
2556645Ssam struct	mtget mts;
2566645Ssam 
2576645Ssam struct mtget *
2586645Ssam rmtstatus()
2596645Ssam {
2606645Ssam 	register int i;
2616645Ssam 	register char *cp;
2626645Ssam 
2636645Ssam 	if (rmtstate != TS_OPEN)
264*59924Storek 		return (NULL);
2656645Ssam 	rmtcall("status", "S\n");
2666645Ssam 	for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
2676645Ssam 		*cp++ = rmtgetb();
2686645Ssam 	return (&mts);
2696645Ssam }
2706645Ssam 
27157727Smckusick int
27257727Smckusick rmtioctl(cmd, count)
27357727Smckusick 	int cmd, count;
27457727Smckusick {
27557727Smckusick 	char buf[256];
27657727Smckusick 
27757727Smckusick 	if (count < 0)
27857727Smckusick 		return (-1);
27957727Smckusick 	(void)sprintf(buf, "I%d\n%d\n", cmd, count);
28057727Smckusick 	return (rmtcall("ioctl", buf));
28157727Smckusick }
28257727Smckusick 
28357724Smckusick static int
2846645Ssam rmtcall(cmd, buf)
2856645Ssam 	char *cmd, *buf;
2866645Ssam {
2876645Ssam 
2886645Ssam 	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
2896645Ssam 		rmtconnaborted();
2906645Ssam 	return (rmtreply(cmd));
2916645Ssam }
2926645Ssam 
29357724Smckusick static int
2946645Ssam rmtreply(cmd)
2956645Ssam 	char *cmd;
2966645Ssam {
297*59924Storek 	register char *cp;
2986645Ssam 	char code[30], emsg[BUFSIZ];
2996645Ssam 
3006645Ssam 	rmtgets(code, sizeof (code));
3016645Ssam 	if (*code == 'E' || *code == 'F') {
3026645Ssam 		rmtgets(emsg, sizeof (emsg));
303*59924Storek 		msg("%s: %s", cmd, emsg);
3046645Ssam 		if (*code == 'F') {
3056645Ssam 			rmtstate = TS_CLOSED;
3066645Ssam 			return (-1);
3076645Ssam 		}
3086645Ssam 		return (-1);
3096645Ssam 	}
3106645Ssam 	if (*code != 'A') {
311*59924Storek 		/* Kill trailing newline */
312*59924Storek 		cp = code + strlen(code);
313*59924Storek 		if (cp > code && *--cp == '\n')
314*59924Storek 			*cp = '\0';
315*59924Storek 
316*59924Storek 		msg("Protocol to remote tape server botched (code \"%s\").\n",
3176645Ssam 		    code);
3186645Ssam 		rmtconnaborted();
3196645Ssam 	}
3206645Ssam 	return (atoi(code + 1));
3216645Ssam }
3226645Ssam 
32346587Storek int
3246645Ssam rmtgetb()
3256645Ssam {
3266645Ssam 	char c;
3276645Ssam 
3286645Ssam 	if (read(rmtape, &c, 1) != 1)
3296645Ssam 		rmtconnaborted();
3306645Ssam 	return (c);
3316645Ssam }
3326645Ssam 
333*59924Storek /* Get a line (guaranteed to have a trailing newline). */
33446587Storek void
33557724Smckusick rmtgets(line, len)
33657724Smckusick 	char *line;
3376645Ssam 	int len;
3386645Ssam {
33957724Smckusick 	register char *cp = line;
3406645Ssam 
3416645Ssam 	while (len > 1) {
3426645Ssam 		*cp = rmtgetb();
3436645Ssam 		if (*cp == '\n') {
344*59924Storek 			cp[1] = '\0';
3456645Ssam 			return;
3466645Ssam 		}
3476645Ssam 		cp++;
3486645Ssam 		len--;
3496645Ssam 	}
350*59924Storek 	*cp = '\0';
35157724Smckusick 	msg("Protocol to remote tape server botched.\n");
35257724Smckusick 	msg("(rmtgets got \"%s\").\n", line);
3536645Ssam 	rmtconnaborted();
3546645Ssam }
355