xref: /original-bsd/sbin/dump/dumprmt.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)dumprmt.c	8.1 (Berkeley) 06/05/93";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 #include <sys/mtio.h>
14 #include <sys/ioctl.h>
15 #include <sys/socket.h>
16 #include <sys/time.h>
17 #ifdef sunos
18 #include <sys/vnode.h>
19 
20 #include <ufs/inode.h>
21 #else
22 #include <ufs/ufs/dinode.h>
23 #endif
24 
25 #include <netinet/in.h>
26 #include <netinet/tcp.h>
27 
28 #include <protocols/dumprestore.h>
29 
30 #include <ctype.h>
31 #include <netdb.h>
32 #include <pwd.h>
33 #include <signal.h>
34 #include <stdio.h>
35 #ifdef __STDC__
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #endif
40 
41 #include "pathnames.h"
42 #include "dump.h"
43 
44 #define	TS_CLOSED	0
45 #define	TS_OPEN		1
46 
47 static	int rmtstate = TS_CLOSED;
48 static	int rmtape;
49 static	char *rmtpeer;
50 
51 static	int okname __P((char *));
52 static	int rmtcall __P((char *, char *));
53 static	void rmtconnaborted __P((/* int, int */));
54 static	int rmtgetb __P((void));
55 static	void rmtgetconn __P((void));
56 static	void rmtgets __P((char *, int));
57 static	int rmtreply __P((char *));
58 
59 extern	int ntrec;		/* blocking factor on tape */
60 
61 int
62 rmthost(host)
63 	char *host;
64 {
65 
66 	rmtpeer = malloc(strlen(host) + 1);
67 	if (rmtpeer)
68 		strcpy(rmtpeer, host);
69 	else
70 		rmtpeer = host;
71 	signal(SIGPIPE, rmtconnaborted);
72 	rmtgetconn();
73 	if (rmtape < 0)
74 		return (0);
75 	return (1);
76 }
77 
78 static void
79 rmtconnaborted()
80 {
81 
82 	(void) fprintf(stderr, "rdump: Lost connection to remote host.\n");
83 	exit(1);
84 }
85 
86 void
87 rmtgetconn()
88 {
89 	register char *cp;
90 	static struct servent *sp = NULL;
91 	static struct passwd *pwd = NULL;
92 #ifdef notdef
93 	static int on = 1;
94 #endif
95 	char *tuser;
96 	int size;
97 	int maxseg;
98 
99 	if (sp == NULL) {
100 		sp = getservbyname("shell", "tcp");
101 		if (sp == NULL) {
102 			(void) fprintf(stderr,
103 			    "rdump: shell/tcp: unknown service\n");
104 			exit(1);
105 		}
106 		pwd = getpwuid(getuid());
107 		if (pwd == NULL) {
108 			(void) fprintf(stderr, "rdump: who are you?\n");
109 			exit(1);
110 		}
111 	}
112 	if ((cp = index(rmtpeer, '@')) != NULL) {
113 		tuser = rmtpeer;
114 		*cp = '\0';
115 		if (!okname(tuser))
116 			exit(1);
117 		rmtpeer = ++cp;
118 	} else
119 		tuser = pwd->pw_name;
120 	rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
121 	    _PATH_RMT, (int *)0);
122 	size = ntrec * TP_BSIZE;
123 	if (size > 60 * 1024)		/* XXX */
124 		size = 60 * 1024;
125 	/* Leave some space for rmt request/response protocol */
126 	size += 2 * 1024;
127 	while (size > TP_BSIZE &&
128 	    setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
129 		    size -= TP_BSIZE;
130 	(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
131 	maxseg = 1024;
132 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
133 	    &maxseg, sizeof (maxseg)) < 0)
134 		perror("TCP_MAXSEG setsockopt");
135 
136 #ifdef notdef
137 	if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
138 		perror("TCP_NODELAY setsockopt");
139 #endif
140 }
141 
142 static int
143 okname(cp0)
144 	char *cp0;
145 {
146 	register char *cp;
147 	register int c;
148 
149 	for (cp = cp0; *cp; cp++) {
150 		c = *cp;
151 		if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
152 			(void) fprintf(stderr, "rdump: invalid user name %s\n",
153 			    cp0);
154 			return (0);
155 		}
156 	}
157 	return (1);
158 }
159 
160 int
161 rmtopen(tape, mode)
162 	char *tape;
163 	int mode;
164 {
165 	char buf[256];
166 
167 	(void)sprintf(buf, "O%s\n%d\n", tape, mode);
168 	rmtstate = TS_OPEN;
169 	return (rmtcall(tape, buf));
170 }
171 
172 void
173 rmtclose()
174 {
175 
176 	if (rmtstate != TS_OPEN)
177 		return;
178 	rmtcall("close", "C\n");
179 	rmtstate = TS_CLOSED;
180 }
181 
182 int
183 rmtread(buf, count)
184 	char *buf;
185 	int count;
186 {
187 	char line[30];
188 	int n, i, cc;
189 	extern errno;
190 
191 	(void)sprintf(line, "R%d\n", count);
192 	n = rmtcall("read", line);
193 	if (n < 0) {
194 		errno = n;
195 		return (-1);
196 	}
197 	for (i = 0; i < n; i += cc) {
198 		cc = read(rmtape, buf+i, n - i);
199 		if (cc <= 0) {
200 			rmtconnaborted();
201 		}
202 	}
203 	return (n);
204 }
205 
206 int
207 rmtwrite(buf, count)
208 	char *buf;
209 	int count;
210 {
211 	char line[30];
212 
213 	(void)sprintf(line, "W%d\n", count);
214 	write(rmtape, line, strlen(line));
215 	write(rmtape, buf, count);
216 	return (rmtreply("write"));
217 }
218 
219 void
220 rmtwrite0(count)
221 	int count;
222 {
223 	char line[30];
224 
225 	(void)sprintf(line, "W%d\n", count);
226 	write(rmtape, line, strlen(line));
227 }
228 
229 void
230 rmtwrite1(buf, count)
231 	char *buf;
232 	int count;
233 {
234 
235 	write(rmtape, buf, count);
236 }
237 
238 int
239 rmtwrite2()
240 {
241 
242 	return (rmtreply("write"));
243 }
244 
245 int
246 rmtseek(offset, pos)
247 	int offset, pos;
248 {
249 	char line[80];
250 
251 	(void)sprintf(line, "L%d\n%d\n", offset, pos);
252 	return (rmtcall("seek", line));
253 }
254 
255 struct	mtget mts;
256 
257 struct mtget *
258 rmtstatus()
259 {
260 	register int i;
261 	register char *cp;
262 
263 	if (rmtstate != TS_OPEN)
264 		return (NULL);
265 	rmtcall("status", "S\n");
266 	for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
267 		*cp++ = rmtgetb();
268 	return (&mts);
269 }
270 
271 int
272 rmtioctl(cmd, count)
273 	int cmd, count;
274 {
275 	char buf[256];
276 
277 	if (count < 0)
278 		return (-1);
279 	(void)sprintf(buf, "I%d\n%d\n", cmd, count);
280 	return (rmtcall("ioctl", buf));
281 }
282 
283 static int
284 rmtcall(cmd, buf)
285 	char *cmd, *buf;
286 {
287 
288 	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
289 		rmtconnaborted();
290 	return (rmtreply(cmd));
291 }
292 
293 static int
294 rmtreply(cmd)
295 	char *cmd;
296 {
297 	register char *cp;
298 	char code[30], emsg[BUFSIZ];
299 
300 	rmtgets(code, sizeof (code));
301 	if (*code == 'E' || *code == 'F') {
302 		rmtgets(emsg, sizeof (emsg));
303 		msg("%s: %s", cmd, emsg);
304 		if (*code == 'F') {
305 			rmtstate = TS_CLOSED;
306 			return (-1);
307 		}
308 		return (-1);
309 	}
310 	if (*code != 'A') {
311 		/* Kill trailing newline */
312 		cp = code + strlen(code);
313 		if (cp > code && *--cp == '\n')
314 			*cp = '\0';
315 
316 		msg("Protocol to remote tape server botched (code \"%s\").\n",
317 		    code);
318 		rmtconnaborted();
319 	}
320 	return (atoi(code + 1));
321 }
322 
323 int
324 rmtgetb()
325 {
326 	char c;
327 
328 	if (read(rmtape, &c, 1) != 1)
329 		rmtconnaborted();
330 	return (c);
331 }
332 
333 /* Get a line (guaranteed to have a trailing newline). */
334 void
335 rmtgets(line, len)
336 	char *line;
337 	int len;
338 {
339 	register char *cp = line;
340 
341 	while (len > 1) {
342 		*cp = rmtgetb();
343 		if (*cp == '\n') {
344 			cp[1] = '\0';
345 			return;
346 		}
347 		cp++;
348 		len--;
349 	}
350 	*cp = '\0';
351 	msg("Protocol to remote tape server botched.\n");
352 	msg("(rmtgets got \"%s\").\n", line);
353 	rmtconnaborted();
354 }
355