054d8535 |
1 | #define _XOPEN_SOURCE |
2 | #include <features.h> |
3 | |
1709795f |
4 | #include <stdio.h> |
5 | #include <stdlib.h> |
054d8535 |
6 | #include <string.h> |
7 | #include <unistd.h> |
8 | #include <fcntl.h> |
1709795f |
9 | |
10 | #include "putty.h" |
11 | |
12 | #ifndef FALSE |
13 | #define FALSE 0 |
14 | #endif |
15 | #ifndef TRUE |
16 | #define TRUE 1 |
17 | #endif |
18 | |
054d8535 |
19 | int pty_master_fd; |
20 | |
1709795f |
21 | static void pty_size(void); |
22 | |
23 | static void c_write(char *buf, int len) |
24 | { |
25 | from_backend(0, buf, len); |
26 | } |
27 | |
28 | /* |
29 | * Called to set up the pty. |
30 | * |
31 | * Returns an error message, or NULL on success. |
32 | * |
33 | * Also places the canonical host name into `realhost'. It must be |
34 | * freed by the caller. |
35 | */ |
36 | static char *pty_init(char *host, int port, char **realhost, int nodelay) |
37 | { |
054d8535 |
38 | int slavefd; |
39 | char name[FILENAME_MAX]; |
40 | pid_t pid; |
41 | |
42 | pty_master_fd = open("/dev/ptmx", O_RDWR); |
43 | |
44 | if (pty_master_fd < 0) { |
45 | perror("/dev/ptmx: open"); |
46 | exit(1); |
47 | } |
48 | |
49 | if (grantpt(pty_master_fd) < 0) { |
50 | perror("grantpt"); |
51 | exit(1); |
52 | } |
53 | |
54 | if (unlockpt(pty_master_fd) < 0) { |
55 | perror("unlockpt"); |
56 | exit(1); |
57 | } |
58 | |
59 | name[FILENAME_MAX-1] = '\0'; |
60 | strncpy(name, ptsname(pty_master_fd), FILENAME_MAX-1); |
61 | |
62 | slavefd = open(name, O_RDWR); |
63 | if (slavefd < 0) { |
64 | perror("slave pty: open"); |
65 | return 1; |
66 | } |
67 | |
68 | /* |
69 | * Fork and execute the command. |
70 | */ |
71 | pid = fork(); |
72 | if (pid < 0) { |
73 | perror("fork"); |
74 | return 1; |
75 | } |
76 | |
77 | if (pid == 0) { |
78 | int i; |
79 | /* |
80 | * We are the child. |
81 | */ |
82 | close(pty_master_fd); |
83 | close(0); |
84 | close(1); |
85 | close(2); |
86 | fcntl(slavefd, F_SETFD, 0); /* don't close on exec */ |
87 | dup2(slavefd, 0); |
88 | dup2(slavefd, 1); |
89 | dup2(slavefd, 2); |
90 | setsid(); |
91 | setpgrp(); |
92 | tcsetpgrp(0, getpgrp()); |
93 | /* Close everything _else_, for tidiness. */ |
94 | for (i = 3; i < 1024; i++) |
95 | close(i); |
96 | execl(getenv("SHELL"), getenv("SHELL"), NULL); |
97 | /* |
98 | * If we're here, exec has gone badly foom. |
99 | */ |
100 | perror("exec"); |
101 | exit(127); |
102 | } else { |
103 | close(slavefd); |
104 | } |
105 | |
1709795f |
106 | return NULL; |
107 | } |
108 | |
109 | /* |
110 | * Called to send data down the pty. |
111 | */ |
112 | static int pty_send(char *buf, int len) |
113 | { |
054d8535 |
114 | while (len > 0) { |
115 | int ret = write(pty_master_fd, buf, len); |
116 | if (ret < 0) { |
117 | perror("write pty master"); |
118 | exit(1); |
119 | } |
120 | buf += ret; |
121 | len -= ret; |
122 | } |
1709795f |
123 | return 0; |
124 | } |
125 | |
126 | /* |
127 | * Called to query the current socket sendability status. |
128 | */ |
129 | static int pty_sendbuffer(void) |
130 | { |
131 | return 0; |
132 | } |
133 | |
134 | /* |
135 | * Called to set the size of the window |
136 | */ |
137 | static void pty_size(void) |
138 | { |
139 | /* FIXME: will need to do TIOCSWINSZ or whatever. */ |
140 | return; |
141 | } |
142 | |
143 | /* |
144 | * Send special codes. |
145 | */ |
146 | static void pty_special(Telnet_Special code) |
147 | { |
148 | /* Do nothing! */ |
149 | return; |
150 | } |
151 | |
152 | static Socket pty_socket(void) |
153 | { |
154 | return NULL; /* shouldn't ever be needed */ |
155 | } |
156 | |
157 | static int pty_sendok(void) |
158 | { |
159 | return 1; |
160 | } |
161 | |
162 | static void pty_unthrottle(int backlog) |
163 | { |
164 | /* do nothing */ |
165 | } |
166 | |
167 | static int pty_ldisc(int option) |
168 | { |
169 | return 0; /* neither editing nor echoing */ |
170 | } |
171 | |
172 | static int pty_exitcode(void) |
173 | { |
174 | /* Shouldn't ever be required */ |
175 | return 0; |
176 | } |
177 | |
178 | Backend pty_backend = { |
179 | pty_init, |
180 | pty_send, |
181 | pty_sendbuffer, |
182 | pty_size, |
183 | pty_special, |
184 | pty_socket, |
185 | pty_exitcode, |
186 | pty_sendok, |
187 | pty_ldisc, |
188 | pty_unthrottle, |
189 | 1 |
190 | }; |