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.18 (Berkeley) 05/11/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