Annotation of src/usr.bin/cu/command.c, Revision 1.12
1.12 ! nicm 1: /* $OpenBSD: command.c,v 1.11 2012/07/11 16:45:12 nicm Exp $ */
1.1 nicm 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>
1.7 nicm 26: #include <limits.h>
1.1 nicm 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);
1.4 nicm 36: void connect_command(void);
1.1 nicm 37: void send_file(void);
1.8 nicm 38: void send_xmodem(void);
1.1 nicm 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:
1.3 nicm 51: restore_termios();
52:
1.1 nicm 53: switch (pid = fork()) {
54: case -1:
1.6 nicm 55: cu_err(1, "fork");
1.1 nicm 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:
1.3 nicm 62: if (signal(SIGINT, SIG_DFL) == SIG_ERR)
63: _exit(1);
64: if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
65: _exit(1);
66:
1.1 nicm 67: /* attach stdout to line */
68: if (dup2(line_fd, STDOUT_FILENO) == -1)
69: _exit(1);
70:
1.5 nicm 71: if (closefrom(STDERR_FILENO + 1) != 0)
1.1 nicm 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: }
1.3 nicm 81:
82: set_termios();
1.1 nicm 83: }
84:
85: void
1.4 nicm 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:
1.6 nicm 106: cu_err(1, "fork");
1.4 nicm 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:
1.5 nicm 119: if (closefrom(STDERR_FILENO + 1) != 0)
1.4 nicm 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
1.1 nicm 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) {
1.6 nicm 148: cu_warn("%s", file);
1.1 nicm 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
1.8 nicm 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
1.2 nicm 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) {
1.6 nicm 189: cu_warnx("speed is %s: %s", errstr, s);
1.2 nicm 190: return;
191: }
192:
1.6 nicm 193: if (set_line(speed) != 0)
194: cu_warn("tcsetattr");
1.2 nicm 195: }
196:
197: void
1.10 nicm 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
1.1 nicm 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;
1.4 nicm 229: case 'C':
230: connect_command();
231: break;
1.12 ! nicm 232: case 'D':
! 233: ioctl(line_fd, TIOCCDTR, NULL);
! 234: sleep(1);
! 235: ioctl(line_fd, TIOCSDTR, NULL);
! 236: break;
1.10 nicm 237: case 'R':
238: start_record();
239: break;
1.2 nicm 240: case 'S':
241: set_speed();
1.8 nicm 242: break;
243: case 'X':
244: send_xmodem();
1.2 nicm 245: break;
1.1 nicm 246: case '$':
247: pipe_command();
248: break;
249: case '>':
250: send_file();
251: break;
252: case '#':
253: ioctl(line_fd, TIOCSBRK, NULL);
254: sleep(1);
255: ioctl(line_fd, TIOCCBRK, NULL);
1.11 nicm 256: break;
257: case '~':
258: bufferevent_write(line_ev, "~", 1);
1.1 nicm 259: break;
260: case '?':
261: printf("\r\n"
1.2 nicm 262: "~# send break\r\n"
263: "~$ pipe local command to remote host\r\n"
1.1 nicm 264: "~> send file to remote host\r\n"
1.4 nicm 265: "~C connect program to remote host\r\n"
1.12 ! nicm 266: "~D de-assert DTR line briefly\r\n"
1.10 nicm 267: "~R start recording to file\r\n"
1.2 nicm 268: "~S set speed\r\n"
1.9 nicm 269: "~X send file with XMODEM\r\n"
1.1 nicm 270: "~? get this summary\r\n"
1.2 nicm 271: );
1.1 nicm 272: break;
273: }
274: }