xref: /openbsd-src/usr.bin/cu/command.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /* $OpenBSD: command.c,v 1.11 2012/07/11 16:45:12 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 
40 void
41 pipe_command(void)
42 {
43 	const char	*cmd;
44 	pid_t		 pid;
45 	int		 fd;
46 
47 	cmd = get_input("Local command?");
48 	if (cmd == NULL || *cmd == '\0')
49 		return;
50 
51 	restore_termios();
52 
53 	switch (pid = fork()) {
54 	case -1:
55 		cu_err(1, "fork");
56 	case 0:
57 		fd = open(_PATH_DEVNULL, O_RDWR);
58 		if (fd < 0 || dup2(fd, STDIN_FILENO) == -1)
59 			_exit(1);
60 		close(fd);
61 
62 		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
63 			_exit(1);
64 		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
65 			_exit(1);
66 
67 		/* attach stdout to line */
68 		if (dup2(line_fd, STDOUT_FILENO) == -1)
69 			_exit(1);
70 
71 		if (closefrom(STDERR_FILENO + 1) != 0)
72 			_exit(1);
73 
74 		execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL);
75 		_exit(1);
76 	default:
77 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
78 			/* nothing */;
79 		break;
80 	}
81 
82 	set_termios();
83 }
84 
85 void
86 connect_command(void)
87 {
88 	const char	*cmd;
89 	pid_t		 pid;
90 
91 	/*
92 	 * Fork a program with:
93 	 *  0 <-> remote tty in
94 	 *  1 <-> remote tty out
95 	 *  2 <-> local tty stderr
96 	 */
97 
98 	cmd = get_input("Local command?");
99 	if (cmd == NULL || *cmd == '\0')
100 		return;
101 
102 	restore_termios();
103 
104 	switch (pid = fork()) {
105 	case -1:
106 		cu_err(1, "fork");
107 	case 0:
108 		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
109 			_exit(1);
110 		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
111 			_exit(1);
112 
113 		/* attach stdout and stdin to line */
114 		if (dup2(line_fd, STDOUT_FILENO) == -1)
115 			_exit(1);
116 		if (dup2(line_fd, STDIN_FILENO) == -1)
117 			_exit(1);
118 
119 		if (closefrom(STDERR_FILENO + 1) != 0)
120 			_exit(1);
121 
122 		execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL);
123 		_exit(1);
124 	default:
125 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
126 			/* nothing */;
127 		break;
128 	}
129 
130 	set_termios();
131 }
132 
133 void
134 send_file(void)
135 {
136 	const char	*file;
137 	FILE		*f;
138 	char		 buf[BUFSIZ], *expanded;
139 	size_t		 len;
140 
141 	file = get_input("Local file?");
142 	if (file == NULL || *file == '\0')
143 		return;
144 
145 	expanded = tilde_expand(file);
146 	f = fopen(expanded, "r");
147 	if (f == NULL) {
148 		cu_warn("%s", file);
149 		return;
150 	}
151 
152 	while (!feof(f) && !ferror(f)) {
153 		len = fread(buf, 1, sizeof(buf), f);
154 		if (len != 0)
155 			bufferevent_write(line_ev, buf, len);
156 	}
157 
158 	fclose(f);
159 	free(expanded);
160 }
161 
162 void
163 send_xmodem(void)
164 {
165 	const char	*file;
166 	char		*expanded;
167 
168 	file = get_input("Local file?");
169 	if (file == NULL || *file == '\0')
170 		return;
171 
172 	expanded = tilde_expand(file);
173 	xmodem_send(expanded);
174 	free(expanded);
175 }
176 
177 void
178 set_speed(void)
179 {
180 	const char	*s, *errstr;
181 	int		 speed;
182 
183 	s = get_input("New speed?");
184 	if (s == NULL || *s == '\0')
185 		return;
186 
187 	speed = strtonum(s, 0, UINT_MAX, &errstr);
188 	if (errstr != NULL) {
189 		cu_warnx("speed is %s: %s", errstr, s);
190 		return;
191 	}
192 
193 	if (set_line(speed) != 0)
194 		cu_warn("tcsetattr");
195 }
196 
197 void
198 start_record(void)
199 {
200 	const char	*file;
201 
202 	if (record_file != NULL) {
203 		fclose(record_file);
204 		record_file = NULL;
205 	}
206 
207 	file = get_input("Record file?");
208 	if (file == NULL || *file == '\0')
209 		return;
210 
211 	record_file = fopen(file, "a");
212 	if (record_file == NULL)
213 		cu_warnx("%s", file);
214 }
215 
216 void
217 do_command(char c)
218 {
219 	switch (c) {
220 	case '.':
221 	case '\004': /* ^D */
222 		event_loopexit(NULL);
223 		break;
224 	case '\032': /* ^Z */
225 		restore_termios();
226 		kill(getpid(), SIGTSTP);
227 		set_termios();
228 		break;
229 	case 'C':
230 		connect_command();
231 		break;
232 	case 'R':
233 		start_record();
234 		break;
235 	case 'S':
236 		set_speed();
237 		break;
238 	case 'X':
239 		send_xmodem();
240 		break;
241 	case '$':
242 		pipe_command();
243 		break;
244 	case '>':
245 		send_file();
246 		break;
247 	case '#':
248 		ioctl(line_fd, TIOCSBRK, NULL);
249 		sleep(1);
250 		ioctl(line_fd, TIOCCBRK, NULL);
251 		break;
252 	case '~':
253 		bufferevent_write(line_ev, "~", 1);
254 		break;
255 	case '?':
256 		printf("\r\n"
257 		    "~#      send break\r\n"
258 		    "~$      pipe local command to remote host\r\n"
259 		    "~>      send file to remote host\r\n"
260 		    "~C      connect program to remote host\r\n"
261 		    "~R      start recording to file\r\n"
262 		    "~S      set speed\r\n"
263 		    "~X      send file with XMODEM\r\n"
264 		    "~?      get this summary\r\n"
265 		);
266 		break;
267 	}
268 }
269