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