dumprmt.c revision 1.6 1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 /*static char sccsid[] = "from: @(#)dumprmt.c 8.1 (Berkeley) 6/5/93";*/
36 static char *rcsid = "$Id: dumprmt.c,v 1.6 1994/06/08 18:57:34 mycroft Exp $";
37 #endif /* not lint */
38
39 #include <sys/param.h>
40 #include <sys/mtio.h>
41 #include <sys/ioctl.h>
42 #include <sys/socket.h>
43 #include <sys/time.h>
44 #ifdef sunos
45 #include <sys/vnode.h>
46
47 #include <ufs/inode.h>
48 #else
49 #include <ufs/ufs/dinode.h>
50 #endif
51
52 #include <netinet/in.h>
53 #include <netinet/tcp.h>
54
55 #include <protocols/dumprestore.h>
56
57 #include <ctype.h>
58 #include <netdb.h>
59 #include <pwd.h>
60 #include <signal.h>
61 #include <stdio.h>
62 #ifdef __STDC__
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66 #endif
67
68 #include "pathnames.h"
69 #include "dump.h"
70
71 #define TS_CLOSED 0
72 #define TS_OPEN 1
73
74 static int rmtstate = TS_CLOSED;
75 static int rmtape;
76 static char *rmtpeer;
77
78 static int okname __P((char *));
79 static int rmtcall __P((char *, char *));
80 static void rmtconnaborted __P((/* int, int */));
81 static int rmtgetb __P((void));
82 static void rmtgetconn __P((void));
83 static void rmtgets __P((char *, int));
84 static int rmtreply __P((char *));
85
86 extern int ntrec; /* blocking factor on tape */
87
88 int
89 rmthost(host)
90 char *host;
91 {
92
93 rmtpeer = malloc(strlen(host) + 1);
94 if (rmtpeer)
95 strcpy(rmtpeer, host);
96 else
97 rmtpeer = host;
98 signal(SIGPIPE, rmtconnaborted);
99 rmtgetconn();
100 if (rmtape < 0)
101 return (0);
102 return (1);
103 }
104
105 static void
106 rmtconnaborted()
107 {
108
109 (void) fprintf(stderr, "rdump: Lost connection to remote host.\n");
110 exit(1);
111 }
112
113 void
114 rmtgetconn()
115 {
116 register char *cp;
117 static struct servent *sp = NULL;
118 static struct passwd *pwd = NULL;
119 #ifdef notdef
120 static int on = 1;
121 #endif
122 char *tuser;
123 int size;
124 int maxseg;
125
126 if (sp == NULL) {
127 sp = getservbyname("shell", "tcp");
128 if (sp == NULL) {
129 (void) fprintf(stderr,
130 "rdump: shell/tcp: unknown service\n");
131 exit(1);
132 }
133 pwd = getpwuid(getuid());
134 if (pwd == NULL) {
135 (void) fprintf(stderr, "rdump: who are you?\n");
136 exit(1);
137 }
138 }
139 if ((cp = index(rmtpeer, '@')) != NULL) {
140 tuser = rmtpeer;
141 *cp = '\0';
142 if (!okname(tuser))
143 exit(1);
144 rmtpeer = ++cp;
145 } else
146 tuser = pwd->pw_name;
147 rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
148 _PATH_RMT, (int *)0);
149 size = ntrec * TP_BSIZE;
150 if (size > 60 * 1024) /* XXX */
151 size = 60 * 1024;
152 /* Leave some space for rmt request/response protocol */
153 size += 2 * 1024;
154 while (size > TP_BSIZE &&
155 setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
156 size -= TP_BSIZE;
157 (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
158 maxseg = 1024;
159 if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
160 &maxseg, sizeof (maxseg)) < 0)
161 perror("TCP_MAXSEG setsockopt");
162
163 #ifdef notdef
164 if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
165 perror("TCP_NODELAY setsockopt");
166 #endif
167 }
168
169 static int
170 okname(cp0)
171 char *cp0;
172 {
173 register char *cp;
174 register int c;
175
176 for (cp = cp0; *cp; cp++) {
177 c = *cp;
178 if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
179 (void) fprintf(stderr, "rdump: invalid user name %s\n",
180 cp0);
181 return (0);
182 }
183 }
184 return (1);
185 }
186
187 int
188 rmtopen(tape, mode)
189 char *tape;
190 int mode;
191 {
192 char buf[256];
193
194 (void)sprintf(buf, "O%s\n%d\n", tape, mode);
195 rmtstate = TS_OPEN;
196 return (rmtcall(tape, buf));
197 }
198
199 void
200 rmtclose()
201 {
202
203 if (rmtstate != TS_OPEN)
204 return;
205 rmtcall("close", "C\n");
206 rmtstate = TS_CLOSED;
207 }
208
209 int
210 rmtread(buf, count)
211 char *buf;
212 int count;
213 {
214 char line[30];
215 int n, i, cc;
216 extern errno;
217
218 (void)sprintf(line, "R%d\n", count);
219 n = rmtcall("read", line);
220 if (n < 0) {
221 errno = n;
222 return (-1);
223 }
224 for (i = 0; i < n; i += cc) {
225 cc = read(rmtape, buf+i, n - i);
226 if (cc <= 0) {
227 rmtconnaborted();
228 }
229 }
230 return (n);
231 }
232
233 int
234 rmtwrite(buf, count)
235 char *buf;
236 int count;
237 {
238 char line[30];
239
240 (void)sprintf(line, "W%d\n", count);
241 write(rmtape, line, strlen(line));
242 write(rmtape, buf, count);
243 return (rmtreply("write"));
244 }
245
246 void
247 rmtwrite0(count)
248 int count;
249 {
250 char line[30];
251
252 (void)sprintf(line, "W%d\n", count);
253 write(rmtape, line, strlen(line));
254 }
255
256 void
257 rmtwrite1(buf, count)
258 char *buf;
259 int count;
260 {
261
262 write(rmtape, buf, count);
263 }
264
265 int
266 rmtwrite2()
267 {
268
269 return (rmtreply("write"));
270 }
271
272 int
273 rmtseek(offset, pos)
274 int offset, pos;
275 {
276 char line[80];
277
278 (void)sprintf(line, "L%d\n%d\n", offset, pos);
279 return (rmtcall("seek", line));
280 }
281
282 struct mtget mts;
283
284 struct mtget *
285 rmtstatus()
286 {
287 register int i;
288 register char *cp;
289
290 if (rmtstate != TS_OPEN)
291 return (NULL);
292 rmtcall("status", "S\n");
293 for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
294 *cp++ = rmtgetb();
295 return (&mts);
296 }
297
298 int
299 rmtioctl(cmd, count)
300 int cmd, count;
301 {
302 char buf[256];
303
304 if (count < 0)
305 return (-1);
306 (void)sprintf(buf, "I%d\n%d\n", cmd, count);
307 return (rmtcall("ioctl", buf));
308 }
309
310 static int
311 rmtcall(cmd, buf)
312 char *cmd, *buf;
313 {
314
315 if (write(rmtape, buf, strlen(buf)) != strlen(buf))
316 rmtconnaborted();
317 return (rmtreply(cmd));
318 }
319
320 static int
321 rmtreply(cmd)
322 char *cmd;
323 {
324 register char *cp;
325 char code[30], emsg[BUFSIZ];
326
327 rmtgets(code, sizeof (code));
328 if (*code == 'E' || *code == 'F') {
329 rmtgets(emsg, sizeof (emsg));
330 msg("%s: %s", cmd, emsg);
331 if (*code == 'F') {
332 rmtstate = TS_CLOSED;
333 return (-1);
334 }
335 return (-1);
336 }
337 if (*code != 'A') {
338 /* Kill trailing newline */
339 cp = code + strlen(code);
340 if (cp > code && *--cp == '\n')
341 *cp = '\0';
342
343 msg("Protocol to remote tape server botched (code \"%s\").\n",
344 code);
345 rmtconnaborted();
346 }
347 return (atoi(code + 1));
348 }
349
350 int
351 rmtgetb()
352 {
353 char c;
354
355 if (read(rmtape, &c, 1) != 1)
356 rmtconnaborted();
357 return (c);
358 }
359
360 /* Get a line (guaranteed to have a trailing newline). */
361 void
362 rmtgets(line, len)
363 char *line;
364 int len;
365 {
366 register char *cp = line;
367
368 while (len > 1) {
369 *cp = rmtgetb();
370 if (*cp == '\n') {
371 cp[1] = '\0';
372 return;
373 }
374 cp++;
375 len--;
376 }
377 *cp = '\0';
378 msg("Protocol to remote tape server botched.\n");
379 msg("(rmtgets got \"%s\").\n", line);
380 rmtconnaborted();
381 }
382