Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 206 lines (183 sloc) 4.875 kb
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
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
18ebcd0 @nelhage Break out prototypes into a header file.
authored
14 #include "reptyr.h"
15
eeb8c68 @nelhage Check for Linux in an #ifdef for clarity.
authored
16 #ifndef __linux__
17 #error reptyr is currently Linux-only.
18 #endif
19
18ebcd0 @nelhage Break out prototypes into a header file.
authored
20 void _debug(const char *pfx, const char *msg, va_list ap) {
21
22 if (pfx)
23 fprintf(stderr, "%s", pfx);
24 vfprintf(stderr, msg, ap);
25 fprintf(stderr, "\n");
26 }
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
27
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
28 void die(const char *msg, ...) {
29 va_list ap;
30 va_start(ap, msg);
18ebcd0 @nelhage Break out prototypes into a header file.
authored
31 _debug("[!] ", msg, ap);
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
32 va_end(ap);
33
34 exit(1);
35 }
36
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
37 void debug(const char *msg, ...) {
38 va_list ap;
39 va_start(ap, msg);
18ebcd0 @nelhage Break out prototypes into a header file.
authored
40 _debug("[+] ", msg, ap);
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
41 va_end(ap);
18ebcd0 @nelhage Break out prototypes into a header file.
authored
42 }
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
43
18ebcd0 @nelhage Break out prototypes into a header file.
authored
44 void error(const char *msg, ...) {
45 va_list ap;
46 va_start(ap, msg);
47 _debug("[-] ", msg, ap);
48 va_end(ap);
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
49 }
50
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
51 void setup_raw(struct termios *save) {
52 struct termios set;
53 if (tcgetattr(0, save) < 0)
54 die("Unable to read terminal attributes: %m");
55 set = *save;
56 set.c_iflag = 0;
57 set.c_oflag = 0;
58 set.c_lflag = 0;
59 if (tcsetattr(0, TCSANOW, &set) < 0)
60 die("Unable to set terminal attributes: %m");
61 }
62
63 void resize_pty(int pty) {
64 struct winsize sz;
65 if (ioctl(0, TIOCGWINSZ, &sz) < 0)
66 return;
67 ioctl(pty, TIOCSWINSZ, &sz);
68 }
69
70 int writeall(int fd, const void *buf, ssize_t count) {
71 ssize_t rv;
72 while (count > 0) {
73 rv = write(fd, buf, count);
74 if (rv < 0)
75 return rv;
76 count -= rv;
77 buf += rv;
78 }
79 return 0;
80 }
81
82 int winch_happened = 0;
83
84 void do_winch(int signal) {
85 winch_happened = 1;
86 }
87
88 void do_proxy(int pty) {
89 char buf[4096];
90 ssize_t count;
91 fd_set set;
92 while (1) {
93 if (winch_happened) {
94 resize_pty(pty);
95 /* FIXME: racy against a second resize */
96 winch_happened = 0;
97 }
98 FD_ZERO(&set);
99 FD_SET(0, &set);
100 FD_SET(pty, &set);
101 if (select(pty+1, &set, NULL, NULL, NULL) < 0) {
102 if (errno == EINTR)
103 continue;
104 fprintf(stderr, "select: %m");
105 return;
106 }
107 if (FD_ISSET(0, &set)) {
108 count = read(0, buf, sizeof buf);
109 if (count < 0)
110 return;
111 writeall(pty, buf, count);
112 }
113 if (FD_ISSET(pty, &set)) {
114 count = read(pty, buf, sizeof buf);
115 if (count < 0)
116 return;
117 writeall(1, buf, count);
118 }
119 }
120 }
121
e2d8d67 @nelhage Add a minimal usage message.
authored
122 void usage(char *me) {
123 fprintf(stderr, "Usage: %s [-l | PID]\n", me);
124 }
125
ff11f6d @nelhage Try to diagnose errors due to Ubuntu's ptrace_scope sysctl.
authored
126 void check_yama_ptrace_scope(void) {
127 int fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY);
128 if (fd >= 0) {
129 char buf[256];
130 int n;
131 n = read(fd, buf, sizeof buf);
ce2f3eb @nelhage Don't leak an fd in check_yama_ptrace_scope.
authored
132 close(fd);
ff11f6d @nelhage Try to diagnose errors due to Ubuntu's ptrace_scope sysctl.
authored
133 if (n > 0) {
134 if (!atoi(buf)) {
135 return;
136 }
137 }
138 } else if(errno == ENOENT)
139 return;
140 fprintf(stderr, "The kernel denied permission while attaching. If your uid matches\n");
141 fprintf(stderr, "the target's, check the value of /proc/sys/kernel/yama/ptrace_scope.\n");
142 fprintf(stderr, "For more information, see /etc/sysctl.d/10-ptrace.conf\n");
143 }
144
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
145 int main(int argc, char **argv) {
146 struct termios saved_termios;
147 struct sigaction act;
148 int pty;
e2d8d67 @nelhage Add a minimal usage message.
authored
149 int do_attach = 1;
150
151 if (argc < 2) {
152 usage(argv[0]);
153 return 2;
154 }
155 if(argv[1][0] == '-') {
156 switch(argv[1][1]) {
157 case 'h':
158 usage(argv[0]);
159 return 0;
160 case 'l':
161 do_attach = 0;
162 break;
c5c9e51 @nelhage Add a version number.
authored
163 case 'v':
164 printf("This is reptyr version %s.\n", REPTYR_VERSION);
165 printf(" by Nelson Elhage <nelhage@nelhage.com>\n");
166 printf("http://github.com/nelhage/reptyr/\n");
167 return 0;
e2d8d67 @nelhage Add a minimal usage message.
authored
168 default:
169 usage(argv[0]);
170 return 1;
171 }
172 }
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
173
174 if ((pty = open("/dev/ptmx", O_RDWR|O_NOCTTY)) < 0)
175 die("Unable to open /dev/ptmx: %m");
176 if (unlockpt(pty) < 0)
177 die("Unable to unlockpt: %m");
178 if (grantpt(pty) < 0)
179 die("Unable to unlockpt: %m");
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
180
e2d8d67 @nelhage Add a minimal usage message.
authored
181 if (do_attach) {
9e91662 @nelhage Checkpoint working version.
authored
182 pid_t child = atoi(argv[1]);
b3eb80f @nelhage Improve error-reporting on attach failures somewhat.
authored
183 int err;
184 if ((err = attach_child(child, ptsname(pty)))) {
61ea2b9 @nelhage Better error reporting if attaching to a child fails.
authored
185 fprintf(stderr, "Unable to attach to pid %d: %s\n", child, strerror(err));
ff11f6d @nelhage Try to diagnose errors due to Ubuntu's ptrace_scope sysctl.
authored
186 if (err == EPERM) {
187 check_yama_ptrace_scope();
188 }
f5d1d89 @nelhage Checkpoint attach work-in-progress.
authored
189 return 1;
190 }
191 } else {
192 printf("Opened a new pty: %s\n", ptsname(pty));
193 }
e222527 @nelhage Initial import. Mostly able to run barnowl.
authored
194
195 setup_raw(&saved_termios);
196 resize_pty(pty);
197 memset(&act, 0, sizeof act);
198 act.sa_handler = do_winch;
199 act.sa_flags = 0;
200 sigaction(SIGWINCH, &act, NULL);
201 do_proxy(pty);
202 tcsetattr(0, TCSANOW, &saved_termios);
203
204 return 0;
205 }
Something went wrong with that request. Please try again.