1 /*- 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)dumprmt.c 5.17 (Berkeley) 01/25/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 = 0; 91 static struct passwd *pwd = 0; 92 #ifdef notdef 93 static int on = 1; 94 #endif 95 char *tuser; 96 int size; 97 int maxseg; 98 99 if (sp == 0) { 100 sp = getservbyname("shell", "tcp"); 101 if (sp == 0) { 102 (void) fprintf(stderr, 103 "rdump: shell/tcp: unknown service\n"); 104 exit(1); 105 } 106 pwd = getpwuid(getuid()); 107 if (pwd == 0) { 108 (void) fprintf(stderr, "rdump: who are you?\n"); 109 exit(1); 110 } 111 } 112 if (cp = index(rmtpeer, '@')) { 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 (0); 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 char code[30], emsg[BUFSIZ]; 298 299 rmtgets(code, sizeof (code)); 300 if (*code == 'E' || *code == 'F') { 301 rmtgets(emsg, sizeof (emsg)); 302 msg("%s: %s\n", cmd, emsg, code + 1); 303 if (*code == 'F') { 304 rmtstate = TS_CLOSED; 305 return (-1); 306 } 307 return (-1); 308 } 309 if (*code != 'A') { 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 void 328 rmtgets(line, len) 329 char *line; 330 int len; 331 { 332 register char *cp = line; 333 334 while (len > 1) { 335 *cp = rmtgetb(); 336 if (*cp == '\n') { 337 cp[1] = 0; 338 return; 339 } 340 cp++; 341 len--; 342 } 343 *cp = 0; 344 msg("Protocol to remote tape server botched.\n"); 345 msg("(rmtgets got \"%s\").\n", line); 346 rmtconnaborted(); 347 } 348