xref: /csrg-svn/sbin/dump/dumprmt.c (revision 68991)
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*68991Sbostic static char sccsid[] = "@(#)dumprmt.c	8.3 (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>
3168986Sbostic #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
rmthost(host)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
rmtconnaborted()806645Ssam rmtconnaborted()
816645Ssam {
826645Ssam 
8368986Sbostic 	errx(1, "Lost connection to remote host.");
846645Ssam }
856645Ssam 
8646587Storek void
rmtgetconn()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");
10168986Sbostic 		if (sp == NULL)
10268986Sbostic 			errx(1, "shell/tcp: unknown service");
10357724Smckusick 		pwd = getpwuid(getuid());
10468986Sbostic 		if (pwd == NULL)
10568986Sbostic 			errx(1, "who are you?");
1069306Ssam 	}
107*68991Sbostic 	if ((cp = strchr(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
okname(cp0)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 == '-')) {
14768986Sbostic 			warnx("invalid user name: %s", cp0);
14857724Smckusick 			return (0);
14957724Smckusick 		}
15057724Smckusick 	}
15157724Smckusick 	return (1);
15257724Smckusick }
15357724Smckusick 
15446587Storek int
rmtopen(tape,mode)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
rmtclose()1676645Ssam rmtclose()
1686645Ssam {
1696645Ssam 
1706645Ssam 	if (rmtstate != TS_OPEN)
1716645Ssam 		return;
1726645Ssam 	rmtcall("close", "C\n");
1736645Ssam 	rmtstate = TS_CLOSED;
1746645Ssam }
1756645Ssam 
17646587Storek int
rmtread(buf,count)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
rmtwrite(buf,count)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
rmtwrite0(count)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
rmtwrite1(buf,count)2246645Ssam rmtwrite1(buf, count)
2256645Ssam 	char *buf;
2266645Ssam 	int count;
2276645Ssam {
2286645Ssam 
2296645Ssam 	write(rmtape, buf, count);
2306645Ssam }
2316645Ssam 
23246587Storek int
rmtwrite2()2336645Ssam rmtwrite2()
2346645Ssam {
2356645Ssam 
2366645Ssam 	return (rmtreply("write"));
2376645Ssam }
2386645Ssam 
23946587Storek int
rmtseek(offset,pos)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 *
rmtstatus()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
rmtioctl(cmd,count)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
rmtcall(cmd,buf)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
rmtreply(cmd)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
rmtgetb()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
rmtgets(line,len)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