Skip to content
Newer
Older
100644 166 lines (147 sloc) 3.66 KB
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/select.h>
5 #include <sys/ioctl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <termios.h>
12 #include <signal.h>
13
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored Jan 17, 2011
14 int attach_child(pid_t pid, const char *pty);
15
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
16 void die(const char *msg, ...) {
17 char buf[8192];
18 va_list ap;
19 va_start(ap, msg);
20 vsnprintf(buf, sizeof buf, msg, ap);
21 va_end(ap);
22
23 fprintf(stderr, "%s\n", buf);
24 exit(1);
25 }
26
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored Jan 18, 2011
27 void debug(const char *msg, ...) {
28 char buf[8192];
29 va_list ap;
30 va_start(ap, msg);
31 vsnprintf(buf, sizeof buf, msg, ap);
32 va_end(ap);
33
34 fprintf(stderr, "[+] %s\n", buf);
35 }
36
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
37 void setup_raw(struct termios *save) {
38 struct termios set;
39 if (tcgetattr(0, save) < 0)
40 die("Unable to read terminal attributes: %m");
41 set = *save;
42 set.c_iflag = 0;
43 set.c_oflag = 0;
44 set.c_cflag = 0;
45 set.c_lflag = 0;
46 if (tcsetattr(0, TCSANOW, &set) < 0)
47 die("Unable to set terminal attributes: %m");
48 }
49
50 void resize_pty(int pty) {
51 struct winsize sz;
52 if (ioctl(0, TIOCGWINSZ, &sz) < 0)
53 return;
54 ioctl(pty, TIOCSWINSZ, &sz);
55 }
56
57 int writeall(int fd, const void *buf, ssize_t count) {
58 ssize_t rv;
59 while (count > 0) {
60 rv = write(fd, buf, count);
61 if (rv < 0)
62 return rv;
63 count -= rv;
64 buf += rv;
65 }
66 return 0;
67 }
68
69 int winch_happened = 0;
70
71 void do_winch(int signal) {
72 winch_happened = 1;
73 }
74
75 void do_proxy(int pty) {
76 char buf[4096];
77 ssize_t count;
78 fd_set set;
79 while (1) {
80 if (winch_happened) {
81 resize_pty(pty);
82 /* FIXME: racy against a second resize */
83 winch_happened = 0;
84 }
85 FD_ZERO(&set);
86 FD_SET(0, &set);
87 FD_SET(pty, &set);
88 if (select(pty+1, &set, NULL, NULL, NULL) < 0) {
89 if (errno == EINTR)
90 continue;
91 fprintf(stderr, "select: %m");
92 return;
93 }
94 if (FD_ISSET(0, &set)) {
95 count = read(0, buf, sizeof buf);
96 if (count < 0)
97 return;
98 writeall(pty, buf, count);
99 }
100 if (FD_ISSET(pty, &set)) {
101 count = read(pty, buf, sizeof buf);
102 if (count < 0)
103 return;
104 writeall(1, buf, count);
105 }
106 }
107 }
108
e2d8d67 @nelhage Add a minimal usage message.
authored Jan 19, 2011
109 void usage(char *me) {
110 fprintf(stderr, "Usage: %s [-l | PID]\n", me);
111 }
112
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
113 int main(int argc, char **argv) {
114 struct termios saved_termios;
115 struct sigaction act;
116 int pty;
e2d8d67 @nelhage Add a minimal usage message.
authored Jan 20, 2011
117 int do_attach = 1;
118
119 if (argc < 2) {
120 usage(argv[0]);
121 return 2;
122 }
123 if(argv[1][0] == '-') {
124 switch(argv[1][1]) {
125 case 'h':
126 usage(argv[0]);
127 return 0;
128 case 'l':
129 do_attach = 0;
130 break;
131 default:
132 usage(argv[0]);
133 return 1;
134 }
135 }
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
136
137 if ((pty = open("/dev/ptmx", O_RDWR|O_NOCTTY)) < 0)
138 die("Unable to open /dev/ptmx: %m");
139 if (unlockpt(pty) < 0)
140 die("Unable to unlockpt: %m");
141 if (grantpt(pty) < 0)
142 die("Unable to unlockpt: %m");
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored Jan 18, 2011
143
e2d8d67 @nelhage Add a minimal usage message.
authored Jan 20, 2011
144 if (do_attach) {
9e91662 @nelhage Checkpoint working version.
authored Jan 17, 2011
145 pid_t child = atoi(argv[1]);
b3eb80f @nelhage Improve error-reporting on attach failures somewhat.
authored Jan 18, 2011
146 int err;
147 if ((err = attach_child(child, ptsname(pty)))) {
61ea2b9 @nelhage Better error reporting if attaching to a child fails.
authored Jan 21, 2011
148 fprintf(stderr, "Unable to attach to pid %d: %s\n", child, strerror(err));
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored Jan 18, 2011
149 return 1;
150 }
151 } else {
152 printf("Opened a new pty: %s\n", ptsname(pty));
153 }
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored Jan 11, 2011
154
155 setup_raw(&saved_termios);
156 resize_pty(pty);
157 memset(&act, 0, sizeof act);
158 act.sa_handler = do_winch;
159 act.sa_flags = 0;
160 sigaction(SIGWINCH, &act, NULL);
161 do_proxy(pty);
162 tcsetattr(0, TCSANOW, &saved_termios);
163
164 return 0;
165 }
Something went wrong with that request. Please try again.