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