1 /*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * 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[] = "@(#)dumprmt.c 5.11 (Berkeley) 3/7/91";
36 #endif /* not lint */
37
38 #include <sys/param.h>
39 #include <sys/mtio.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <ufs/dinode.h>
43 #include <signal.h>
44
45 #include <netinet/in.h>
46
47 #include <netdb.h>
48 #include <protocols/dumprestore.h>
49 #include <pwd.h>
50 #include <stdio.h>
51 #ifdef __STDC__
52 #include <unistd.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #endif
56 #include "pathnames.h"
57
58 #define TS_CLOSED 0
59 #define TS_OPEN 1
60
61 static int rmtstate = TS_CLOSED;
62 int rmtape;
63 void rmtgetconn();
64 void rmtconnaborted();
65 int rmtreply();
66 int rmtgetb();
67 void rmtgets();
68 int rmtcall();
69 char *rmtpeer;
70
71 extern int ntrec; /* blocking factor on tape */
72 extern void msg();
73
74 int
rmthost(host)75 rmthost(host)
76 char *host;
77 {
78
79 rmtpeer = host;
80 signal(SIGPIPE, rmtconnaborted);
81 rmtgetconn();
82 if (rmtape < 0)
83 return (0);
84 return (1);
85 }
86
87 void
rmtconnaborted()88 rmtconnaborted()
89 {
90
91 fprintf(stderr, "rdump: Lost connection to remote host.\n");
92 exit(1);
93 }
94
95 void
rmtgetconn()96 rmtgetconn()
97 {
98 static struct servent *sp = 0;
99 struct passwd *pw;
100 char *name = "root";
101 int size;
102
103 if (sp == 0) {
104 sp = getservbyname("shell", "tcp");
105 if (sp == 0) {
106 fprintf(stderr, "rdump: shell/tcp: unknown service\n");
107 exit(1);
108 }
109 }
110 pw = getpwuid(getuid());
111 if (pw && pw->pw_name)
112 name = pw->pw_name;
113 rmtape = rcmd(&rmtpeer, sp->s_port, name, name, _PATH_RMT, 0);
114 size = ntrec * TP_BSIZE;
115 while (size > TP_BSIZE &&
116 setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
117 size -= TP_BSIZE;
118 }
119
120 int
rmtopen(tape,mode)121 rmtopen(tape, mode)
122 char *tape;
123 int mode;
124 {
125 char buf[256];
126
127 (void)sprintf(buf, "O%s\n%d\n", tape, mode);
128 rmtstate = TS_OPEN;
129 return (rmtcall(tape, buf));
130 }
131
132 void
rmtclose()133 rmtclose()
134 {
135
136 if (rmtstate != TS_OPEN)
137 return;
138 rmtcall("close", "C\n");
139 rmtstate = TS_CLOSED;
140 }
141
142 int
rmtread(buf,count)143 rmtread(buf, count)
144 char *buf;
145 int count;
146 {
147 char line[30];
148 int n, i, cc;
149 extern errno;
150
151 (void)sprintf(line, "R%d\n", count);
152 n = rmtcall("read", line);
153 if (n < 0) {
154 errno = n;
155 return (-1);
156 }
157 for (i = 0; i < n; i += cc) {
158 cc = read(rmtape, buf+i, n - i);
159 if (cc <= 0) {
160 rmtconnaborted();
161 }
162 }
163 return (n);
164 }
165
166 int
rmtwrite(buf,count)167 rmtwrite(buf, count)
168 char *buf;
169 int count;
170 {
171 char line[30];
172
173 (void)sprintf(line, "W%d\n", count);
174 write(rmtape, line, strlen(line));
175 write(rmtape, buf, count);
176 return (rmtreply("write"));
177 }
178
179 void
rmtwrite0(count)180 rmtwrite0(count)
181 int count;
182 {
183 char line[30];
184
185 (void)sprintf(line, "W%d\n", count);
186 write(rmtape, line, strlen(line));
187 }
188
189 void
rmtwrite1(buf,count)190 rmtwrite1(buf, count)
191 char *buf;
192 int count;
193 {
194
195 write(rmtape, buf, count);
196 }
197
198 int
rmtwrite2()199 rmtwrite2()
200 {
201
202 return (rmtreply("write"));
203 }
204
205 int
rmtseek(offset,pos)206 rmtseek(offset, pos)
207 int offset, pos;
208 {
209 char line[80];
210
211 (void)sprintf(line, "L%d\n%d\n", offset, pos);
212 return (rmtcall("seek", line));
213 }
214
215 struct mtget mts;
216
217 struct mtget *
rmtstatus()218 rmtstatus()
219 {
220 register int i;
221 register char *cp;
222
223 if (rmtstate != TS_OPEN)
224 return (0);
225 rmtcall("status", "S\n");
226 for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
227 *cp++ = rmtgetb();
228 return (&mts);
229 }
230
231 int
rmtioctl(cmd,count)232 rmtioctl(cmd, count)
233 int cmd, count;
234 {
235 char buf[256];
236
237 if (count < 0)
238 return (-1);
239 (void)sprintf(buf, "I%d\n%d\n", cmd, count);
240 return (rmtcall("ioctl", buf));
241 }
242
243 int
rmtcall(cmd,buf)244 rmtcall(cmd, buf)
245 char *cmd, *buf;
246 {
247
248 if (write(rmtape, buf, strlen(buf)) != strlen(buf))
249 rmtconnaborted();
250 return (rmtreply(cmd));
251 }
252
253 int
rmtreply(cmd)254 rmtreply(cmd)
255 char *cmd;
256 {
257 char code[30], emsg[BUFSIZ];
258
259 rmtgets(code, sizeof (code));
260 if (*code == 'E' || *code == 'F') {
261 rmtgets(emsg, sizeof (emsg));
262 msg("%s: %s\n", cmd, emsg, code + 1);
263 if (*code == 'F') {
264 rmtstate = TS_CLOSED;
265 return (-1);
266 }
267 return (-1);
268 }
269 if (*code != 'A') {
270 msg("Protocol to remote tape server botched (code %s?).\n",
271 code);
272 rmtconnaborted();
273 }
274 return (atoi(code + 1));
275 }
276
277 int
rmtgetb()278 rmtgetb()
279 {
280 char c;
281
282 if (read(rmtape, &c, 1) != 1)
283 rmtconnaborted();
284 return (c);
285 }
286
287 void
rmtgets(cp,len)288 rmtgets(cp, len)
289 char *cp;
290 int len;
291 {
292
293 while (len > 1) {
294 *cp = rmtgetb();
295 if (*cp == '\n') {
296 cp[1] = 0;
297 return;
298 }
299 cp++;
300 len--;
301 }
302 msg("Protocol to remote tape server botched (in rmtgets).\n");
303 rmtconnaborted();
304 }
305