147082Smckusick /*- 247082Smckusick * Copyright (c) 1980 The Regents of the University of California. 347082Smckusick * All rights reserved. 447082Smckusick * 547082Smckusick * %sccs.include.redist.c% 622039Sdist */ 76645Ssam 822039Sdist #ifndef lint 9*57724Smckusick static char sccsid[] = "@(#)dumprmt.c 5.16 (Berkeley) 01/25/93"; 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> 16*57724Smckusick #include <sys/time.h> 17*57724Smckusick #ifdef sunos 18*57724Smckusick #include <sys/vnode.h> 19*57724Smckusick 20*57724Smckusick #include <ufs/inode.h> 2150498Smckusick #else 22*57724Smckusick #include <ufs/ufs/dinode.h> 2350498Smckusick #endif 246645Ssam 259306Ssam #include <netinet/in.h> 26*57724Smckusick #include <netinet/tcp.h> 279306Ssam 28*57724Smckusick #include <protocols/dumprestore.h> 29*57724Smckusick 30*57724Smckusick #include <ctype.h> 319306Ssam #include <netdb.h> 3237946Sbostic #include <pwd.h> 33*57724Smckusick #include <signal.h> 34*57724Smckusick #include <stdio.h> 3546795Sbostic #ifdef __STDC__ 3646587Storek #include <stdlib.h> 3746587Storek #include <string.h> 38*57724Smckusick #include <unistd.h> 3946795Sbostic #endif 40*57724Smckusick 4137946Sbostic #include "pathnames.h" 42*57724Smckusick #include "dump.h" 439306Ssam 446645Ssam #define TS_CLOSED 0 456645Ssam #define TS_OPEN 1 466645Ssam 476645Ssam static int rmtstate = TS_CLOSED; 48*57724Smckusick static int rmtape; 49*57724Smckusick static char *rmtpeer; 506645Ssam 51*57724Smckusick static int okname __P((char *)); 52*57724Smckusick static int rmtcall __P((char *, char *)); 53*57724Smckusick static void rmtconnaborted __P((/* int, int */)); 54*57724Smckusick static int rmtgetb __P((void)); 55*57724Smckusick static void rmtgetconn __P((void)); 56*57724Smckusick static void rmtgets __P((char *, int)); 57*57724Smckusick static int rmtreply __P((char *)); 5817538Sralph 59*57724Smckusick extern int ntrec; /* blocking factor on tape */ 6054044Smckusick 6146587Storek int 626645Ssam rmthost(host) 636645Ssam char *host; 646645Ssam { 656645Ssam 66*57724Smckusick rmtpeer = malloc(strlen(host) + 1); 67*57724Smckusick if (rmtpeer) 68*57724Smckusick strcpy(rmtpeer, host); 69*57724Smckusick else 70*57724Smckusick rmtpeer = host; 7113032Ssam signal(SIGPIPE, rmtconnaborted); 726645Ssam rmtgetconn(); 736645Ssam if (rmtape < 0) 7417538Sralph return (0); 7517538Sralph return (1); 766645Ssam } 776645Ssam 78*57724Smckusick static void 796645Ssam rmtconnaborted() 806645Ssam { 816645Ssam 8254044Smckusick (void) fprintf(stderr, "rdump: Lost connection to remote host.\n"); 83*57724Smckusick exit(1); 846645Ssam } 856645Ssam 8646587Storek void 876645Ssam rmtgetconn() 886645Ssam { 89*57724Smckusick register char *cp; 909306Ssam static struct servent *sp = 0; 91*57724Smckusick static struct passwd *pwd = 0; 92*57724Smckusick #ifdef notdef 93*57724Smckusick static int on = 1; 94*57724Smckusick #endif 95*57724Smckusick char *tuser; 9617538Sralph int size; 97*57724Smckusick int maxseg; 986645Ssam 999306Ssam if (sp == 0) { 1009306Ssam sp = getservbyname("shell", "tcp"); 1019306Ssam if (sp == 0) { 10254044Smckusick (void) fprintf(stderr, 10354044Smckusick "rdump: shell/tcp: unknown service\n"); 104*57724Smckusick exit(1); 1059306Ssam } 106*57724Smckusick pwd = getpwuid(getuid()); 107*57724Smckusick if (pwd == 0) { 108*57724Smckusick (void) fprintf(stderr, "rdump: who are you?\n"); 109*57724Smckusick exit(1); 110*57724Smckusick } 1119306Ssam } 112*57724Smckusick if (cp = index(rmtpeer, '@')) { 113*57724Smckusick tuser = rmtpeer; 114*57724Smckusick *cp = '\0'; 115*57724Smckusick if (!okname(tuser)) 116*57724Smckusick exit(1); 117*57724Smckusick rmtpeer = ++cp; 118*57724Smckusick } else 119*57724Smckusick tuser = pwd->pw_name; 120*57724Smckusick rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser, 121*57724Smckusick _PATH_RMT, (int *)0); 12217538Sralph size = ntrec * TP_BSIZE; 123*57724Smckusick if (size > 60 * 1024) /* XXX */ 124*57724Smckusick size = 60 * 1024; 125*57724Smckusick /* Leave some space for rmt request/response protocol */ 126*57724Smckusick size += 2 * 1024; 12718493Smckusick while (size > TP_BSIZE && 12818493Smckusick setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0) 129*57724Smckusick size -= TP_BSIZE; 130*57724Smckusick (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)); 131*57724Smckusick maxseg = 1024; 132*57724Smckusick if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG, 133*57724Smckusick &maxseg, sizeof (maxseg)) < 0) 134*57724Smckusick perror("TCP_MAXSEG setsockopt"); 135*57724Smckusick 136*57724Smckusick #ifdef notdef 137*57724Smckusick if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) 138*57724Smckusick perror("TCP_NODELAY setsockopt"); 139*57724Smckusick #endif 1406645Ssam } 1416645Ssam 142*57724Smckusick static int 143*57724Smckusick okname(cp0) 144*57724Smckusick char *cp0; 145*57724Smckusick { 146*57724Smckusick register char *cp; 147*57724Smckusick register int c; 148*57724Smckusick 149*57724Smckusick for (cp = cp0; *cp; cp++) { 150*57724Smckusick c = *cp; 151*57724Smckusick if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) { 152*57724Smckusick (void) fprintf(stderr, "rdump: invalid user name %s\n", 153*57724Smckusick cp0); 154*57724Smckusick return (0); 155*57724Smckusick } 156*57724Smckusick } 157*57724Smckusick return (1); 158*57724Smckusick } 159*57724Smckusick 16046587Storek int 1616645Ssam rmtopen(tape, mode) 1626645Ssam char *tape; 1636645Ssam int mode; 1646645Ssam { 1656645Ssam char buf[256]; 1666645Ssam 16732455Sbostic (void)sprintf(buf, "O%s\n%d\n", tape, mode); 1686645Ssam rmtstate = TS_OPEN; 16924836Smckusick return (rmtcall(tape, buf)); 1706645Ssam } 1716645Ssam 17246587Storek void 1736645Ssam rmtclose() 1746645Ssam { 1756645Ssam 1766645Ssam if (rmtstate != TS_OPEN) 1776645Ssam return; 1786645Ssam rmtcall("close", "C\n"); 1796645Ssam rmtstate = TS_CLOSED; 1806645Ssam } 1816645Ssam 18246587Storek int 1836645Ssam rmtread(buf, count) 1846645Ssam char *buf; 1856645Ssam int count; 1866645Ssam { 1876645Ssam char line[30]; 1886645Ssam int n, i, cc; 1896884Ssam extern errno; 1906645Ssam 19132455Sbostic (void)sprintf(line, "R%d\n", count); 1926645Ssam n = rmtcall("read", line); 1936884Ssam if (n < 0) { 1946884Ssam errno = n; 1956645Ssam return (-1); 1966884Ssam } 1976645Ssam for (i = 0; i < n; i += cc) { 1986645Ssam cc = read(rmtape, buf+i, n - i); 1996884Ssam if (cc <= 0) { 2006645Ssam rmtconnaborted(); 2016884Ssam } 2026645Ssam } 2036645Ssam return (n); 2046645Ssam } 2056645Ssam 20646587Storek int 2076645Ssam rmtwrite(buf, count) 2086645Ssam char *buf; 2096645Ssam int count; 2106645Ssam { 2116645Ssam char line[30]; 2126645Ssam 21332455Sbostic (void)sprintf(line, "W%d\n", count); 2146645Ssam write(rmtape, line, strlen(line)); 2156645Ssam write(rmtape, buf, count); 2166645Ssam return (rmtreply("write")); 2176645Ssam } 2186645Ssam 21946587Storek void 2206645Ssam rmtwrite0(count) 2216645Ssam int count; 2226645Ssam { 2236645Ssam char line[30]; 2246645Ssam 22532455Sbostic (void)sprintf(line, "W%d\n", count); 2266645Ssam write(rmtape, line, strlen(line)); 2276645Ssam } 2286645Ssam 22946587Storek void 2306645Ssam rmtwrite1(buf, count) 2316645Ssam char *buf; 2326645Ssam int count; 2336645Ssam { 2346645Ssam 2356645Ssam write(rmtape, buf, count); 2366645Ssam } 2376645Ssam 23846587Storek int 2396645Ssam rmtwrite2() 2406645Ssam { 2416645Ssam 2426645Ssam return (rmtreply("write")); 2436645Ssam } 2446645Ssam 24546587Storek int 2466645Ssam rmtseek(offset, pos) 2476645Ssam int offset, pos; 2486645Ssam { 2496645Ssam char line[80]; 2506645Ssam 25132455Sbostic (void)sprintf(line, "L%d\n%d\n", offset, pos); 2526645Ssam return (rmtcall("seek", line)); 2536645Ssam } 2546645Ssam 2556645Ssam struct mtget mts; 2566645Ssam 2576645Ssam struct mtget * 2586645Ssam rmtstatus() 2596645Ssam { 2606645Ssam register int i; 2616645Ssam register char *cp; 2626645Ssam 2636645Ssam if (rmtstate != TS_OPEN) 2646645Ssam return (0); 2656645Ssam rmtcall("status", "S\n"); 2666645Ssam for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++) 2676645Ssam *cp++ = rmtgetb(); 2686645Ssam return (&mts); 2696645Ssam } 2706645Ssam 271*57724Smckusick static int 2726645Ssam rmtcall(cmd, buf) 2736645Ssam char *cmd, *buf; 2746645Ssam { 2756645Ssam 2766645Ssam if (write(rmtape, buf, strlen(buf)) != strlen(buf)) 2776645Ssam rmtconnaborted(); 2786645Ssam return (rmtreply(cmd)); 2796645Ssam } 2806645Ssam 281*57724Smckusick static int 2826645Ssam rmtreply(cmd) 2836645Ssam char *cmd; 2846645Ssam { 2856645Ssam char code[30], emsg[BUFSIZ]; 2866645Ssam 2876645Ssam rmtgets(code, sizeof (code)); 2886645Ssam if (*code == 'E' || *code == 'F') { 2896645Ssam rmtgets(emsg, sizeof (emsg)); 2906645Ssam msg("%s: %s\n", cmd, emsg, code + 1); 2916645Ssam if (*code == 'F') { 2926645Ssam rmtstate = TS_CLOSED; 2936645Ssam return (-1); 2946645Ssam } 2956645Ssam return (-1); 2966645Ssam } 2976645Ssam if (*code != 'A') { 2986645Ssam msg("Protocol to remote tape server botched (code %s?).\n", 2996645Ssam code); 3006645Ssam rmtconnaborted(); 3016645Ssam } 3026645Ssam return (atoi(code + 1)); 3036645Ssam } 3046645Ssam 30546587Storek int 3066645Ssam rmtgetb() 3076645Ssam { 3086645Ssam char c; 3096645Ssam 3106645Ssam if (read(rmtape, &c, 1) != 1) 3116645Ssam rmtconnaborted(); 3126645Ssam return (c); 3136645Ssam } 3146645Ssam 31546587Storek void 316*57724Smckusick rmtgets(line, len) 317*57724Smckusick char *line; 3186645Ssam int len; 3196645Ssam { 320*57724Smckusick register char *cp = line; 3216645Ssam 3226645Ssam while (len > 1) { 3236645Ssam *cp = rmtgetb(); 3246645Ssam if (*cp == '\n') { 3256645Ssam cp[1] = 0; 3266645Ssam return; 3276645Ssam } 3286645Ssam cp++; 3296645Ssam len--; 3306645Ssam } 331*57724Smckusick *cp = 0; 332*57724Smckusick msg("Protocol to remote tape server botched.\n"); 333*57724Smckusick msg("(rmtgets got \"%s\").\n", line); 3346645Ssam rmtconnaborted(); 3356645Ssam } 336