GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/cu/command.c Lines: 0 108 0.0 %
Date: 2016-12-06 Branches: 0 97 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: command.c,v 1.15 2015/10/05 23:15:31 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2012 Nicholas Marriott <nicm@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/ioctl.h>
21
#include <sys/wait.h>
22
23
#include <event.h>
24
#include <errno.h>
25
#include <fcntl.h>
26
#include <limits.h>
27
#include <paths.h>
28
#include <signal.h>
29
#include <stdlib.h>
30
#include <stdio.h>
31
#include <unistd.h>
32
33
#include "cu.h"
34
35
void	pipe_command(void);
36
void	connect_command(void);
37
void	send_file(void);
38
void	send_xmodem(void);
39
void	set_speed(void);
40
void	start_record(void);
41
42
void
43
pipe_command(void)
44
{
45
	const char	*cmd;
46
	pid_t		 pid;
47
	int		 fd;
48
49
	cmd = get_input("Local command?");
50
	if (cmd == NULL || *cmd == '\0')
51
		return;
52
53
	restore_termios();
54
	set_blocking(line_fd, 1);
55
56
	switch (pid = fork()) {
57
	case -1:
58
		cu_err(1, "fork");
59
	case 0:
60
		fd = open(_PATH_DEVNULL, O_RDWR);
61
		if (fd < 0 || dup2(fd, STDIN_FILENO) == -1)
62
			_exit(1);
63
		close(fd);
64
65
		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
66
			_exit(1);
67
		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
68
			_exit(1);
69
70
		/* attach stdout to line */
71
		if (dup2(line_fd, STDOUT_FILENO) == -1)
72
			_exit(1);
73
74
		if (closefrom(STDERR_FILENO + 1) != 0)
75
			_exit(1);
76
77
		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
78
		_exit(1);
79
	default:
80
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
81
			/* nothing */;
82
		break;
83
	}
84
85
	set_blocking(line_fd, 0);
86
	set_termios();
87
}
88
89
void
90
connect_command(void)
91
{
92
	const char	*cmd;
93
	pid_t		 pid;
94
95
	/*
96
	 * Fork a program with:
97
	 *  0 <-> remote tty in
98
	 *  1 <-> remote tty out
99
	 *  2 <-> local tty stderr
100
	 */
101
102
	cmd = get_input("Local command?");
103
	if (cmd == NULL || *cmd == '\0')
104
		return;
105
106
	restore_termios();
107
	set_blocking(line_fd, 1);
108
109
	switch (pid = fork()) {
110
	case -1:
111
		cu_err(1, "fork");
112
	case 0:
113
		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
114
			_exit(1);
115
		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
116
			_exit(1);
117
118
		/* attach stdout and stdin to line */
119
		if (dup2(line_fd, STDOUT_FILENO) == -1)
120
			_exit(1);
121
		if (dup2(line_fd, STDIN_FILENO) == -1)
122
			_exit(1);
123
124
		if (closefrom(STDERR_FILENO + 1) != 0)
125
			_exit(1);
126
127
		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
128
		_exit(1);
129
	default:
130
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
131
			/* nothing */;
132
		break;
133
	}
134
135
	set_blocking(line_fd, 0);
136
	set_termios();
137
}
138
139
void
140
send_file(void)
141
{
142
	const char	*file;
143
	FILE		*f;
144
	char		 buf[BUFSIZ], *expanded;
145
	size_t		 len;
146
147
	file = get_input("Local file?");
148
	if (file == NULL || *file == '\0')
149
		return;
150
151
	expanded = tilde_expand(file);
152
	f = fopen(expanded, "r");
153
	if (f == NULL) {
154
		cu_warn("%s", file);
155
		return;
156
	}
157
158
	while (!feof(f) && !ferror(f)) {
159
		len = fread(buf, 1, sizeof(buf), f);
160
		if (len != 0)
161
			bufferevent_write(line_ev, buf, len);
162
	}
163
164
	fclose(f);
165
	free(expanded);
166
}
167
168
void
169
send_xmodem(void)
170
{
171
	const char	*file;
172
	char		*expanded;
173
174
	file = get_input("Local file?");
175
	if (file == NULL || *file == '\0')
176
		return;
177
178
	expanded = tilde_expand(file);
179
	xmodem_send(expanded);
180
	free(expanded);
181
}
182
183
void
184
set_speed(void)
185
{
186
	const char	*s, *errstr;
187
	int		 speed;
188
189
	s = get_input("New speed?");
190
	if (s == NULL || *s == '\0')
191
		return;
192
193
	speed = strtonum(s, 0, UINT_MAX, &errstr);
194
	if (errstr != NULL) {
195
		cu_warnx("speed is %s: %s", errstr, s);
196
		return;
197
	}
198
199
	if (set_line(speed) != 0)
200
		cu_warn("tcsetattr");
201
}
202
203
void
204
start_record(void)
205
{
206
	const char	*file;
207
208
	if (record_file != NULL) {
209
		fclose(record_file);
210
		record_file = NULL;
211
	}
212
213
	file = get_input("Record file?");
214
	if (file == NULL || *file == '\0')
215
		return;
216
217
	record_file = fopen(file, "a");
218
	if (record_file == NULL)
219
		cu_warnx("%s", file);
220
}
221
222
void
223
do_command(char c)
224
{
225
	switch (c) {
226
	case '.':
227
	case '\004': /* ^D */
228
		event_loopexit(NULL);
229
		break;
230
	case '\032': /* ^Z */
231
		restore_termios();
232
		kill(getpid(), SIGTSTP);
233
		set_termios();
234
		break;
235
	case 'C':
236
		connect_command();
237
		break;
238
	case 'D':
239
		ioctl(line_fd, TIOCCDTR, NULL);
240
		sleep(1);
241
		ioctl(line_fd, TIOCSDTR, NULL);
242
		break;
243
	case 'R':
244
		start_record();
245
		break;
246
	case 'S':
247
		set_speed();
248
		break;
249
	case 'X':
250
		send_xmodem();
251
		break;
252
	case '$':
253
		pipe_command();
254
		break;
255
	case '>':
256
		send_file();
257
		break;
258
	case '#':
259
		ioctl(line_fd, TIOCSBRK, NULL);
260
		sleep(1);
261
		ioctl(line_fd, TIOCCBRK, NULL);
262
		break;
263
	case '~':
264
		bufferevent_write(line_ev, "~", 1);
265
		break;
266
	case '?':
267
		printf("\r\n"
268
		    "~#      send break\r\n"
269
		    "~$      pipe local command to remote host\r\n"
270
		    "~>      send file to remote host\r\n"
271
		    "~C      connect program to remote host\r\n"
272
		    "~D      de-assert DTR line briefly\r\n"
273
		    "~R      start recording to file\r\n"
274
		    "~S      set speed\r\n"
275
		    "~X      send file with XMODEM\r\n"
276
		    "~?      get this summary\r\n"
277
		);
278
		break;
279
	}
280
}