GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/mt/mtrmt.c Lines: 0 95 0.0 %
Date: 2017-11-07 Branches: 0 54 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mtrmt.c,v 1.21 2013/11/21 15:54:45 deraadt Exp $	*/
2
/*	$NetBSD: mtrmt.c,v 1.2 1996/03/06 06:22:07 scottr Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/mtio.h>
35
#include <sys/ioctl.h>
36
#include <sys/socket.h>
37
#include <sys/time.h>
38
#include <ufs/ufs/dinode.h>
39
40
#include <netinet/in.h>
41
#include <netinet/tcp.h>
42
43
#include <protocols/dumprestore.h>
44
45
#include <ctype.h>
46
#include <err.h>
47
#include <netdb.h>
48
#include <pwd.h>
49
#include <signal.h>
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <string.h>
53
#include <unistd.h>
54
55
#include "pathnames.h"
56
#include "mt.h"
57
58
#define	TS_CLOSED	0
59
#define	TS_OPEN		1
60
61
static	int rmtstate = TS_CLOSED;
62
static	int rmtape;
63
static	char *rmtpeer;
64
65
static	int okname(char *);
66
static	int rmtcall(char *, char *);
67
static	void rmtconnaborted(void);
68
static	void sigrmtconnaborted(int);
69
static	int rmtgetb(void);
70
static	void rmtgetconn(void);
71
static	void rmtgets(char *, int);
72
static	int rmtreply(char *);
73
74
int
75
rmthost(char *host)
76
{
77
	if ((rmtpeer = strdup(host)) == NULL)
78
		err(1, "strdup");
79
	signal(SIGPIPE, sigrmtconnaborted);
80
	rmtgetconn();
81
	if (rmtape < 0)
82
		return (0);
83
	return (1);
84
}
85
86
/* ARGSUSED */
87
static void
88
sigrmtconnaborted(int signo)
89
{
90
91
	warnx("Lost connection to remote host.");
92
	_exit(1);
93
}
94
95
static void
96
rmtconnaborted(void)
97
{
98
99
	errx(1, "Lost connection to remote host.");
100
}
101
102
void
103
rmtgetconn(void)
104
{
105
	char *cp;
106
	static struct servent *sp = NULL;
107
	static struct passwd *pwd = NULL;
108
#ifdef notdef
109
	static int on = 1;
110
#endif
111
	char *tuser;
112
	int size;
113
	int maxseg;
114
115
	if (sp == NULL) {
116
		sp = getservbyname("shell", "tcp");
117
		if (sp == NULL)
118
			errx(1, "shell/tcp: unknown service");
119
		pwd = getpwuid(getuid());
120
		if (pwd == NULL)
121
			errx(1, "who are you?");
122
	}
123
	if ((cp = strchr(rmtpeer, '@')) != NULL) {
124
		tuser = rmtpeer;
125
		*cp = '\0';
126
		if (!okname(tuser))
127
			exit(1);
128
		rmtpeer = ++cp;
129
	} else
130
		tuser = pwd->pw_name;
131
132
	rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
133
	    _PATH_RMT, NULL);
134
	if (rmtape == -1)
135
		exit(1);		/* rcmd already printed error message */
136
137
	size = TP_BSIZE;
138
	if (size > 60 * 1024)		/* XXX */
139
		size = 60 * 1024;
140
	/* Leave some space for rmt request/response protocol */
141
	size += 2 * 1024;
142
143
	while (size > TP_BSIZE &&
144
	    setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
145
		    size -= TP_BSIZE;
146
	(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
147
148
	maxseg = 1024;
149
	(void)setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG, &maxseg,
150
		sizeof (maxseg));
151
152
#ifdef notdef
153
	if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
154
		perror("TCP_NODELAY setsockopt");
155
#endif
156
}
157
158
static int
159
okname(char *cp0)
160
{
161
	unsigned char *cp;
162
	int c;
163
164
	for (cp = cp0; *cp; cp++) {
165
		c = (unsigned char)*cp;
166
		if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
167
			warnx("invalid user name: %s", cp0);
168
			return (0);
169
		}
170
	}
171
	return (1);
172
}
173
174
int
175
rmtopen(char *tape, int mode)
176
{
177
	char buf[256];
178
179
	(void)snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode);
180
	rmtstate = TS_OPEN;
181
	return (rmtcall(tape, buf));
182
}
183
184
void
185
rmtclose(void)
186
{
187
188
	if (rmtstate != TS_OPEN)
189
		return;
190
	rmtcall("close", "C\n");
191
	rmtstate = TS_CLOSED;
192
}
193
194
struct	mtget mts;
195
196
struct mtget *
197
rmtstatus(void)
198
{
199
	int i;
200
	char *cp;
201
202
	if (rmtstate != TS_OPEN)
203
		return (NULL);
204
	rmtcall("status", "S\n");
205
	for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
206
		*cp++ = rmtgetb();
207
	return (&mts);
208
}
209
210
int
211
rmtioctl(int cmd, int count)
212
{
213
	char buf[256];
214
215
	if (count < 0)
216
		return (-1);
217
	(void)snprintf(buf, sizeof (buf), "I%d\n%d\n", cmd, count);
218
	return (rmtcall("ioctl", buf));
219
}
220
221
static int
222
rmtcall(char *cmd, char *buf)
223
{
224
225
	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
226
		rmtconnaborted();
227
	return (rmtreply(cmd));
228
}
229
230
static int
231
rmtreply(char *cmd)
232
{
233
	char *cp;
234
	char code[30], emsg[BUFSIZ];
235
236
	rmtgets(code, sizeof (code));
237
	if (*code == 'E' || *code == 'F') {
238
		rmtgets(emsg, sizeof (emsg));
239
		warnx("%s: %s", cmd, emsg);
240
		if (*code == 'F') {
241
			rmtstate = TS_CLOSED;
242
			return (-1);
243
		}
244
		return (-1);
245
	}
246
	if (*code != 'A') {
247
		/* Kill trailing newline */
248
		cp = code + strlen(code);
249
		if (cp > code && *--cp == '\n')
250
			*cp = '\0';
251
252
		warnx("Protocol to remote tape server botched (code \"%s\").",
253
		    code);
254
		rmtconnaborted();
255
	}
256
	return (atoi(code + 1));
257
}
258
259
int
260
rmtgetb(void)
261
{
262
	char c;
263
264
	if (read(rmtape, &c, 1) != 1)
265
		rmtconnaborted();
266
	return (c);
267
}
268
269
/* Get a line (guaranteed to have a trailing newline). */
270
void
271
rmtgets(char *line, int len)
272
{
273
	char *cp = line;
274
275
	while (len > 1) {
276
		*cp = rmtgetb();
277
		if (*cp == '\n') {
278
			cp[1] = '\0';
279
			return;
280
		}
281
		cp++;
282
		len--;
283
	}
284
	*cp = '\0';
285
	warnx("Protocol to remote tape server botched.");
286
	warnx("(rmtgets got \"%s\").", line);
287
	rmtconnaborted();
288
}