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