xref: /csrg-svn/sbin/dump/dumprmt.c (revision 57724)
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*57724Smckusick static char sccsid[] = "@(#)dumprmt.c	5.16 (Berkeley) 01/25/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>
16*57724Smckusick #include <sys/time.h>
17*57724Smckusick #ifdef sunos
18*57724Smckusick #include <sys/vnode.h>
19*57724Smckusick 
20*57724Smckusick #include <ufs/inode.h>
2150498Smckusick #else
22*57724Smckusick #include <ufs/ufs/dinode.h>
2350498Smckusick #endif
246645Ssam 
259306Ssam #include <netinet/in.h>
26*57724Smckusick #include <netinet/tcp.h>
279306Ssam 
28*57724Smckusick #include <protocols/dumprestore.h>
29*57724Smckusick 
30*57724Smckusick #include <ctype.h>
319306Ssam #include <netdb.h>
3237946Sbostic #include <pwd.h>
33*57724Smckusick #include <signal.h>
34*57724Smckusick #include <stdio.h>
3546795Sbostic #ifdef __STDC__
3646587Storek #include <stdlib.h>
3746587Storek #include <string.h>
38*57724Smckusick #include <unistd.h>
3946795Sbostic #endif
40*57724Smckusick 
4137946Sbostic #include "pathnames.h"
42*57724Smckusick #include "dump.h"
439306Ssam 
446645Ssam #define	TS_CLOSED	0
456645Ssam #define	TS_OPEN		1
466645Ssam 
476645Ssam static	int rmtstate = TS_CLOSED;
48*57724Smckusick static	int rmtape;
49*57724Smckusick static	char *rmtpeer;
506645Ssam 
51*57724Smckusick static	int okname __P((char *));
52*57724Smckusick static	int rmtcall __P((char *, char *));
53*57724Smckusick static	void rmtconnaborted __P((/* int, int */));
54*57724Smckusick static	int rmtgetb __P((void));
55*57724Smckusick static	void rmtgetconn __P((void));
56*57724Smckusick static	void rmtgets __P((char *, int));
57*57724Smckusick static	int rmtreply __P((char *));
5817538Sralph 
59*57724Smckusick extern	int ntrec;		/* blocking factor on tape */
6054044Smckusick 
6146587Storek int
626645Ssam rmthost(host)
636645Ssam 	char *host;
646645Ssam {
656645Ssam 
66*57724Smckusick 	rmtpeer = malloc(strlen(host) + 1);
67*57724Smckusick 	if (rmtpeer)
68*57724Smckusick 		strcpy(rmtpeer, host);
69*57724Smckusick 	else
70*57724Smckusick 		rmtpeer = host;
7113032Ssam 	signal(SIGPIPE, rmtconnaborted);
726645Ssam 	rmtgetconn();
736645Ssam 	if (rmtape < 0)
7417538Sralph 		return (0);
7517538Sralph 	return (1);
766645Ssam }
776645Ssam 
78*57724Smckusick static void
796645Ssam rmtconnaborted()
806645Ssam {
816645Ssam 
8254044Smckusick 	(void) fprintf(stderr, "rdump: Lost connection to remote host.\n");
83*57724Smckusick 	exit(1);
846645Ssam }
856645Ssam 
8646587Storek void
876645Ssam rmtgetconn()
886645Ssam {
89*57724Smckusick 	register char *cp;
909306Ssam 	static struct servent *sp = 0;
91*57724Smckusick 	static struct passwd *pwd = 0;
92*57724Smckusick #ifdef notdef
93*57724Smckusick 	static int on = 1;
94*57724Smckusick #endif
95*57724Smckusick 	char *tuser;
9617538Sralph 	int size;
97*57724Smckusick 	int maxseg;
986645Ssam 
999306Ssam 	if (sp == 0) {
1009306Ssam 		sp = getservbyname("shell", "tcp");
1019306Ssam 		if (sp == 0) {
10254044Smckusick 			(void) fprintf(stderr,
10354044Smckusick 			    "rdump: shell/tcp: unknown service\n");
104*57724Smckusick 			exit(1);
1059306Ssam 		}
106*57724Smckusick 		pwd = getpwuid(getuid());
107*57724Smckusick 		if (pwd == 0) {
108*57724Smckusick 			(void) fprintf(stderr, "rdump: who are you?\n");
109*57724Smckusick 			exit(1);
110*57724Smckusick 		}
1119306Ssam 	}
112*57724Smckusick 	if (cp = index(rmtpeer, '@')) {
113*57724Smckusick 		tuser = rmtpeer;
114*57724Smckusick 		*cp = '\0';
115*57724Smckusick 		if (!okname(tuser))
116*57724Smckusick 			exit(1);
117*57724Smckusick 		rmtpeer = ++cp;
118*57724Smckusick 	} else
119*57724Smckusick 		tuser = pwd->pw_name;
120*57724Smckusick 	rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
121*57724Smckusick 	    _PATH_RMT, (int *)0);
12217538Sralph 	size = ntrec * TP_BSIZE;
123*57724Smckusick 	if (size > 60 * 1024)		/* XXX */
124*57724Smckusick 		size = 60 * 1024;
125*57724Smckusick 	/* Leave some space for rmt request/response protocol */
126*57724Smckusick 	size += 2 * 1024;
12718493Smckusick 	while (size > TP_BSIZE &&
12818493Smckusick 	    setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
129*57724Smckusick 		    size -= TP_BSIZE;
130*57724Smckusick 	(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
131*57724Smckusick 	maxseg = 1024;
132*57724Smckusick 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
133*57724Smckusick 	    &maxseg, sizeof (maxseg)) < 0)
134*57724Smckusick 		perror("TCP_MAXSEG setsockopt");
135*57724Smckusick 
136*57724Smckusick #ifdef notdef
137*57724Smckusick 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
138*57724Smckusick 		perror("TCP_NODELAY setsockopt");
139*57724Smckusick #endif
1406645Ssam }
1416645Ssam 
142*57724Smckusick static int
143*57724Smckusick okname(cp0)
144*57724Smckusick 	char *cp0;
145*57724Smckusick {
146*57724Smckusick 	register char *cp;
147*57724Smckusick 	register int c;
148*57724Smckusick 
149*57724Smckusick 	for (cp = cp0; *cp; cp++) {
150*57724Smckusick 		c = *cp;
151*57724Smckusick 		if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
152*57724Smckusick 			(void) fprintf(stderr, "rdump: invalid user name %s\n",
153*57724Smckusick 			    cp0);
154*57724Smckusick 			return (0);
155*57724Smckusick 		}
156*57724Smckusick 	}
157*57724Smckusick 	return (1);
158*57724Smckusick }
159*57724Smckusick 
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)
2646645Ssam 		return (0);
2656645Ssam 	rmtcall("status", "S\n");
2666645Ssam 	for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
2676645Ssam 		*cp++ = rmtgetb();
2686645Ssam 	return (&mts);
2696645Ssam }
2706645Ssam 
271*57724Smckusick static int
2726645Ssam rmtcall(cmd, buf)
2736645Ssam 	char *cmd, *buf;
2746645Ssam {
2756645Ssam 
2766645Ssam 	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
2776645Ssam 		rmtconnaborted();
2786645Ssam 	return (rmtreply(cmd));
2796645Ssam }
2806645Ssam 
281*57724Smckusick static int
2826645Ssam rmtreply(cmd)
2836645Ssam 	char *cmd;
2846645Ssam {
2856645Ssam 	char code[30], emsg[BUFSIZ];
2866645Ssam 
2876645Ssam 	rmtgets(code, sizeof (code));
2886645Ssam 	if (*code == 'E' || *code == 'F') {
2896645Ssam 		rmtgets(emsg, sizeof (emsg));
2906645Ssam 		msg("%s: %s\n", cmd, emsg, code + 1);
2916645Ssam 		if (*code == 'F') {
2926645Ssam 			rmtstate = TS_CLOSED;
2936645Ssam 			return (-1);
2946645Ssam 		}
2956645Ssam 		return (-1);
2966645Ssam 	}
2976645Ssam 	if (*code != 'A') {
2986645Ssam 		msg("Protocol to remote tape server botched (code %s?).\n",
2996645Ssam 		    code);
3006645Ssam 		rmtconnaborted();
3016645Ssam 	}
3026645Ssam 	return (atoi(code + 1));
3036645Ssam }
3046645Ssam 
30546587Storek int
3066645Ssam rmtgetb()
3076645Ssam {
3086645Ssam 	char c;
3096645Ssam 
3106645Ssam 	if (read(rmtape, &c, 1) != 1)
3116645Ssam 		rmtconnaborted();
3126645Ssam 	return (c);
3136645Ssam }
3146645Ssam 
31546587Storek void
316*57724Smckusick rmtgets(line, len)
317*57724Smckusick 	char *line;
3186645Ssam 	int len;
3196645Ssam {
320*57724Smckusick 	register char *cp = line;
3216645Ssam 
3226645Ssam 	while (len > 1) {
3236645Ssam 		*cp = rmtgetb();
3246645Ssam 		if (*cp == '\n') {
3256645Ssam 			cp[1] = 0;
3266645Ssam 			return;
3276645Ssam 		}
3286645Ssam 		cp++;
3296645Ssam 		len--;
3306645Ssam 	}
331*57724Smckusick 	*cp = 0;
332*57724Smckusick 	msg("Protocol to remote tape server botched.\n");
333*57724Smckusick 	msg("(rmtgets got \"%s\").\n", line);
3346645Ssam 	rmtconnaborted();
3356645Ssam }
336