147082Smckusick /*- 261484Sbostic * Copyright (c) 1980, 1993 361484Sbostic * The Regents of the University of California. All rights reserved. 447082Smckusick * 547082Smckusick * %sccs.include.redist.c% 622039Sdist */ 76645Ssam 822039Sdist #ifndef lint 9*68986Sbostic static char sccsid[] = "@(#)dumprmt.c 8.2 (Berkeley) 04/28/95"; 1046587Storek #endif /* not lint */ 1122039Sdist 126884Ssam #include <sys/param.h> 136645Ssam #include <sys/mtio.h> 146645Ssam #include <sys/ioctl.h> 1517538Sralph #include <sys/socket.h> 1657724Smckusick #include <sys/time.h> 1757724Smckusick #ifdef sunos 1857724Smckusick #include <sys/vnode.h> 1957724Smckusick 2057724Smckusick #include <ufs/inode.h> 2150498Smckusick #else 2257724Smckusick #include <ufs/ufs/dinode.h> 2350498Smckusick #endif 246645Ssam 259306Ssam #include <netinet/in.h> 2657724Smckusick #include <netinet/tcp.h> 279306Ssam 2857724Smckusick #include <protocols/dumprestore.h> 2957724Smckusick 3057724Smckusick #include <ctype.h> 31*68986Sbostic #include <err.h> 329306Ssam #include <netdb.h> 3337946Sbostic #include <pwd.h> 3457724Smckusick #include <signal.h> 3557724Smckusick #include <stdio.h> 3646795Sbostic #ifdef __STDC__ 3746587Storek #include <stdlib.h> 3846587Storek #include <string.h> 3957724Smckusick #include <unistd.h> 4046795Sbostic #endif 4157724Smckusick 4237946Sbostic #include "pathnames.h" 4357724Smckusick #include "dump.h" 449306Ssam 456645Ssam #define TS_CLOSED 0 466645Ssam #define TS_OPEN 1 476645Ssam 486645Ssam static int rmtstate = TS_CLOSED; 4957724Smckusick static int rmtape; 5057724Smckusick static char *rmtpeer; 516645Ssam 5257724Smckusick static int okname __P((char *)); 5357724Smckusick static int rmtcall __P((char *, char *)); 5457724Smckusick static void rmtconnaborted __P((/* int, int */)); 5557724Smckusick static int rmtgetb __P((void)); 5657724Smckusick static void rmtgetconn __P((void)); 5757724Smckusick static void rmtgets __P((char *, int)); 5857724Smckusick static int rmtreply __P((char *)); 5917538Sralph 6057724Smckusick extern int ntrec; /* blocking factor on tape */ 6154044Smckusick 6246587Storek int 636645Ssam rmthost(host) 646645Ssam char *host; 656645Ssam { 666645Ssam 6757724Smckusick rmtpeer = malloc(strlen(host) + 1); 6857724Smckusick if (rmtpeer) 6957724Smckusick strcpy(rmtpeer, host); 7057724Smckusick else 7157724Smckusick rmtpeer = host; 7213032Ssam signal(SIGPIPE, rmtconnaborted); 736645Ssam rmtgetconn(); 746645Ssam if (rmtape < 0) 7517538Sralph return (0); 7617538Sralph return (1); 776645Ssam } 786645Ssam 7957724Smckusick static void 806645Ssam rmtconnaborted() 816645Ssam { 826645Ssam 83*68986Sbostic errx(1, "Lost connection to remote host."); 846645Ssam } 856645Ssam 8646587Storek void 876645Ssam rmtgetconn() 886645Ssam { 8957724Smckusick register char *cp; 9059924Storek static struct servent *sp = NULL; 9159924Storek static struct passwd *pwd = NULL; 9257724Smckusick #ifdef notdef 9357724Smckusick static int on = 1; 9457724Smckusick #endif 9557724Smckusick char *tuser; 9617538Sralph int size; 9757724Smckusick int maxseg; 986645Ssam 9959924Storek if (sp == NULL) { 1009306Ssam sp = getservbyname("shell", "tcp"); 101*68986Sbostic if (sp == NULL) 102*68986Sbostic errx(1, "shell/tcp: unknown service"); 10357724Smckusick pwd = getpwuid(getuid()); 104*68986Sbostic if (pwd == NULL) 105*68986Sbostic errx(1, "who are you?"); 1069306Ssam } 10759924Storek if ((cp = index(rmtpeer, '@')) != NULL) { 10857724Smckusick tuser = rmtpeer; 10957724Smckusick *cp = '\0'; 11057724Smckusick if (!okname(tuser)) 11157724Smckusick exit(1); 11257724Smckusick rmtpeer = ++cp; 11357724Smckusick } else 11457724Smckusick tuser = pwd->pw_name; 11557724Smckusick rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser, 11657724Smckusick _PATH_RMT, (int *)0); 11717538Sralph size = ntrec * TP_BSIZE; 11857724Smckusick if (size > 60 * 1024) /* XXX */ 11957724Smckusick size = 60 * 1024; 12057724Smckusick /* Leave some space for rmt request/response protocol */ 12157724Smckusick size += 2 * 1024; 12218493Smckusick while (size > TP_BSIZE && 12318493Smckusick setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0) 12457724Smckusick size -= TP_BSIZE; 12557724Smckusick (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)); 12657724Smckusick maxseg = 1024; 12757724Smckusick if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG, 12857724Smckusick &maxseg, sizeof (maxseg)) < 0) 12957724Smckusick perror("TCP_MAXSEG setsockopt"); 13057724Smckusick 13157724Smckusick #ifdef notdef 13257724Smckusick if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) 13357724Smckusick perror("TCP_NODELAY setsockopt"); 13457724Smckusick #endif 1356645Ssam } 1366645Ssam 13757724Smckusick static int 13857724Smckusick okname(cp0) 13957724Smckusick char *cp0; 14057724Smckusick { 14157724Smckusick register char *cp; 14257724Smckusick register int c; 14357724Smckusick 14457724Smckusick for (cp = cp0; *cp; cp++) { 14557724Smckusick c = *cp; 14657724Smckusick if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) { 147*68986Sbostic warnx("invalid user name: %s", cp0); 14857724Smckusick return (0); 14957724Smckusick } 15057724Smckusick } 15157724Smckusick return (1); 15257724Smckusick } 15357724Smckusick 15446587Storek int 1556645Ssam rmtopen(tape, mode) 1566645Ssam char *tape; 1576645Ssam int mode; 1586645Ssam { 1596645Ssam char buf[256]; 1606645Ssam 16132455Sbostic (void)sprintf(buf, "O%s\n%d\n", tape, mode); 1626645Ssam rmtstate = TS_OPEN; 16324836Smckusick return (rmtcall(tape, buf)); 1646645Ssam } 1656645Ssam 16646587Storek void 1676645Ssam rmtclose() 1686645Ssam { 1696645Ssam 1706645Ssam if (rmtstate != TS_OPEN) 1716645Ssam return; 1726645Ssam rmtcall("close", "C\n"); 1736645Ssam rmtstate = TS_CLOSED; 1746645Ssam } 1756645Ssam 17646587Storek int 1776645Ssam rmtread(buf, count) 1786645Ssam char *buf; 1796645Ssam int count; 1806645Ssam { 1816645Ssam char line[30]; 1826645Ssam int n, i, cc; 1836884Ssam extern errno; 1846645Ssam 18532455Sbostic (void)sprintf(line, "R%d\n", count); 1866645Ssam n = rmtcall("read", line); 1876884Ssam if (n < 0) { 1886884Ssam errno = n; 1896645Ssam return (-1); 1906884Ssam } 1916645Ssam for (i = 0; i < n; i += cc) { 1926645Ssam cc = read(rmtape, buf+i, n - i); 1936884Ssam if (cc <= 0) { 1946645Ssam rmtconnaborted(); 1956884Ssam } 1966645Ssam } 1976645Ssam return (n); 1986645Ssam } 1996645Ssam 20046587Storek int 2016645Ssam rmtwrite(buf, count) 2026645Ssam char *buf; 2036645Ssam int count; 2046645Ssam { 2056645Ssam char line[30]; 2066645Ssam 20732455Sbostic (void)sprintf(line, "W%d\n", count); 2086645Ssam write(rmtape, line, strlen(line)); 2096645Ssam write(rmtape, buf, count); 2106645Ssam return (rmtreply("write")); 2116645Ssam } 2126645Ssam 21346587Storek void 2146645Ssam rmtwrite0(count) 2156645Ssam int count; 2166645Ssam { 2176645Ssam char line[30]; 2186645Ssam 21932455Sbostic (void)sprintf(line, "W%d\n", count); 2206645Ssam write(rmtape, line, strlen(line)); 2216645Ssam } 2226645Ssam 22346587Storek void 2246645Ssam rmtwrite1(buf, count) 2256645Ssam char *buf; 2266645Ssam int count; 2276645Ssam { 2286645Ssam 2296645Ssam write(rmtape, buf, count); 2306645Ssam } 2316645Ssam 23246587Storek int 2336645Ssam rmtwrite2() 2346645Ssam { 2356645Ssam 2366645Ssam return (rmtreply("write")); 2376645Ssam } 2386645Ssam 23946587Storek int 2406645Ssam rmtseek(offset, pos) 2416645Ssam int offset, pos; 2426645Ssam { 2436645Ssam char line[80]; 2446645Ssam 24532455Sbostic (void)sprintf(line, "L%d\n%d\n", offset, pos); 2466645Ssam return (rmtcall("seek", line)); 2476645Ssam } 2486645Ssam 2496645Ssam struct mtget mts; 2506645Ssam 2516645Ssam struct mtget * 2526645Ssam rmtstatus() 2536645Ssam { 2546645Ssam register int i; 2556645Ssam register char *cp; 2566645Ssam 2576645Ssam if (rmtstate != TS_OPEN) 25859924Storek return (NULL); 2596645Ssam rmtcall("status", "S\n"); 2606645Ssam for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++) 2616645Ssam *cp++ = rmtgetb(); 2626645Ssam return (&mts); 2636645Ssam } 2646645Ssam 26557727Smckusick int 26657727Smckusick rmtioctl(cmd, count) 26757727Smckusick int cmd, count; 26857727Smckusick { 26957727Smckusick char buf[256]; 27057727Smckusick 27157727Smckusick if (count < 0) 27257727Smckusick return (-1); 27357727Smckusick (void)sprintf(buf, "I%d\n%d\n", cmd, count); 27457727Smckusick return (rmtcall("ioctl", buf)); 27557727Smckusick } 27657727Smckusick 27757724Smckusick static int 2786645Ssam rmtcall(cmd, buf) 2796645Ssam char *cmd, *buf; 2806645Ssam { 2816645Ssam 2826645Ssam if (write(rmtape, buf, strlen(buf)) != strlen(buf)) 2836645Ssam rmtconnaborted(); 2846645Ssam return (rmtreply(cmd)); 2856645Ssam } 2866645Ssam 28757724Smckusick static int 2886645Ssam rmtreply(cmd) 2896645Ssam char *cmd; 2906645Ssam { 29159924Storek register char *cp; 2926645Ssam char code[30], emsg[BUFSIZ]; 2936645Ssam 2946645Ssam rmtgets(code, sizeof (code)); 2956645Ssam if (*code == 'E' || *code == 'F') { 2966645Ssam rmtgets(emsg, sizeof (emsg)); 29759924Storek msg("%s: %s", cmd, emsg); 2986645Ssam if (*code == 'F') { 2996645Ssam rmtstate = TS_CLOSED; 3006645Ssam return (-1); 3016645Ssam } 3026645Ssam return (-1); 3036645Ssam } 3046645Ssam if (*code != 'A') { 30559924Storek /* Kill trailing newline */ 30659924Storek cp = code + strlen(code); 30759924Storek if (cp > code && *--cp == '\n') 30859924Storek *cp = '\0'; 30959924Storek 31059924Storek msg("Protocol to remote tape server botched (code \"%s\").\n", 3116645Ssam code); 3126645Ssam rmtconnaborted(); 3136645Ssam } 3146645Ssam return (atoi(code + 1)); 3156645Ssam } 3166645Ssam 31746587Storek int 3186645Ssam rmtgetb() 3196645Ssam { 3206645Ssam char c; 3216645Ssam 3226645Ssam if (read(rmtape, &c, 1) != 1) 3236645Ssam rmtconnaborted(); 3246645Ssam return (c); 3256645Ssam } 3266645Ssam 32759924Storek /* Get a line (guaranteed to have a trailing newline). */ 32846587Storek void 32957724Smckusick rmtgets(line, len) 33057724Smckusick char *line; 3316645Ssam int len; 3326645Ssam { 33357724Smckusick register char *cp = line; 3346645Ssam 3356645Ssam while (len > 1) { 3366645Ssam *cp = rmtgetb(); 3376645Ssam if (*cp == '\n') { 33859924Storek cp[1] = '\0'; 3396645Ssam return; 3406645Ssam } 3416645Ssam cp++; 3426645Ssam len--; 3436645Ssam } 34459924Storek *cp = '\0'; 34557724Smckusick msg("Protocol to remote tape server botched.\n"); 34657724Smckusick msg("(rmtgets got \"%s\").\n", line); 3476645Ssam rmtconnaborted(); 3486645Ssam } 349