OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "nacl_io/devfs/tty_node.h" | 5 #include "nacl_io/devfs/tty_node.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <signal.h> | 9 #include <signal.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <string.h> | 11 #include <string.h> |
12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
13 #include <unistd.h> | 13 #include <unistd.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 | 16 |
17 #include "nacl_io/filesystem.h" | 17 #include "nacl_io/filesystem.h" |
18 #include "nacl_io/ioctl.h" | 18 #include "nacl_io/ioctl.h" |
19 #include "nacl_io/kernel_handle.h" | 19 #include "nacl_io/kernel_handle.h" |
20 #include "nacl_io/kernel_intercept.h" | 20 #include "nacl_io/kernel_intercept.h" |
| 21 #include "nacl_io/log.h" |
21 #include "nacl_io/pepper_interface.h" | 22 #include "nacl_io/pepper_interface.h" |
22 #include "sdk_util/auto_lock.h" | 23 #include "sdk_util/auto_lock.h" |
23 | 24 |
24 #define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS.c_lflag& FLAG) | 25 #define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS.c_lflag& FLAG) |
25 | 26 |
26 #define IS_ECHO CHECK_LFLAG(termios_, ECHO) | 27 #define IS_ECHO CHECK_LFLAG(termios_, ECHO) |
27 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE) | 28 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE) |
28 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL) | 29 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL) |
29 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL) | 30 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL) |
30 #define IS_ICANON CHECK_LFLAG(termios_, ICANON) | 31 #define IS_ICANON CHECK_LFLAG(termios_, ICANON) |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 Error error = Write(data, string, count, &wrote); | 161 Error error = Write(data, string, count, &wrote); |
161 if (error != 0 || wrote != count) { | 162 if (error != 0 || wrote != count) { |
162 // TOOD(sbc): Do something more useful in response to a | 163 // TOOD(sbc): Do something more useful in response to a |
163 // failure to echo. | 164 // failure to echo. |
164 return error; | 165 return error; |
165 } | 166 } |
166 | 167 |
167 return 0; | 168 return 0; |
168 } | 169 } |
169 | 170 |
170 Error TtyNode::ProcessInput(struct tioc_nacl_input_string* message) { | 171 Error TtyNode::ProcessInput(PP_Var message) { |
| 172 if (message.type != PP_VARTYPE_STRING) { |
| 173 LOG_ERROR("ProcessInput: expected VarString but got %d.", message.type); |
| 174 return EINVAL; |
| 175 } |
| 176 |
| 177 PepperInterface* ppapi = filesystem_->ppapi(); |
| 178 if (!ppapi) { |
| 179 LOG_ERROR("ProcessInput: ppapi is NULL."); |
| 180 return EINVAL; |
| 181 } |
| 182 |
| 183 VarInterface* var_iface = ppapi->GetVarInterface(); |
| 184 if (!var_iface) { |
| 185 LOG_ERROR("ProcessInput: Var interface pointer is NULL."); |
| 186 return EINVAL; |
| 187 } |
| 188 |
| 189 uint32_t num_bytes; |
| 190 const char* buffer = var_iface->VarToUtf8(message, &num_bytes); |
| 191 Error error = ProcessInput(buffer, num_bytes); |
| 192 return error; |
| 193 } |
| 194 |
| 195 Error TtyNode::ProcessInput(const char* buffer, size_t num_bytes) { |
171 AUTO_LOCK(emitter_->GetLock()) | 196 AUTO_LOCK(emitter_->GetLock()) |
172 | 197 |
173 const char* buffer = message->buffer; | |
174 size_t num_bytes = message->length; | |
175 | |
176 for (size_t i = 0; i < num_bytes; i++) { | 198 for (size_t i = 0; i < num_bytes; i++) { |
177 char c = buffer[i]; | 199 char c = buffer[i]; |
178 // Transform characters according to input flags. | 200 // Transform characters according to input flags. |
179 if (c == '\r') { | 201 if (c == '\r') { |
180 if (termios_.c_iflag & IGNCR) | 202 if (termios_.c_iflag & IGNCR) |
181 continue; | 203 continue; |
182 if (termios_.c_iflag & ICRNL) | 204 if (termios_.c_iflag & ICRNL) |
183 c = '\n'; | 205 c = '\n'; |
184 } else if (c == '\n') { | 206 } else if (c == '\n') { |
185 if (termios_.c_iflag & INLCR) | 207 if (termios_.c_iflag & INLCR) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 AUTO_LOCK(output_lock_); | 263 AUTO_LOCK(output_lock_); |
242 if (arg == NULL) { | 264 if (arg == NULL) { |
243 output_handler_.handler = NULL; | 265 output_handler_.handler = NULL; |
244 return 0; | 266 return 0; |
245 } | 267 } |
246 if (output_handler_.handler != NULL) | 268 if (output_handler_.handler != NULL) |
247 return EALREADY; | 269 return EALREADY; |
248 output_handler_ = *arg; | 270 output_handler_ = *arg; |
249 return 0; | 271 return 0; |
250 } | 272 } |
251 case TIOCNACLINPUT: { | 273 case NACL_IOC_HANDLEMESSAGE: { |
252 // This ioctl is used to deliver data from the user to this tty node's | 274 struct PP_Var* message = va_arg(args, struct PP_Var*); |
253 // input buffer. | 275 return ProcessInput(*message); |
254 struct tioc_nacl_input_string* message = | |
255 va_arg(args, struct tioc_nacl_input_string*); | |
256 return ProcessInput(message); | |
257 } | 276 } |
258 case TIOCSWINSZ: { | 277 case TIOCSWINSZ: { |
259 struct winsize* size = va_arg(args, struct winsize*); | 278 struct winsize* size = va_arg(args, struct winsize*); |
260 { | 279 { |
261 AUTO_LOCK(node_lock_); | 280 AUTO_LOCK(node_lock_); |
262 if (rows_ == size->ws_row && cols_ == size->ws_col) | 281 if (rows_ == size->ws_row && cols_ == size->ws_col) |
263 return 0; | 282 return 0; |
264 rows_ = size->ws_row; | 283 rows_ = size->ws_row; |
265 cols_ = size->ws_col; | 284 cols_ = size->ws_col; |
266 } | 285 } |
267 ki_kill(getpid(), SIGWINCH); | 286 ki_kill(getpid(), SIGWINCH); |
268 { | 287 { |
269 // Wake up any thread waiting on Read with POLLERR then immediate | 288 // Wake up any thread waiting on Read with POLLERR then immediate |
270 // clear it to signal EINTR. | 289 // clear it to signal EINTR. |
271 AUTO_LOCK(emitter_->GetLock()) | 290 AUTO_LOCK(emitter_->GetLock()) |
272 emitter_->RaiseEvents_Locked(POLLERR); | 291 emitter_->RaiseEvents_Locked(POLLERR); |
273 emitter_->ClearEvents_Locked(POLLERR); | 292 emitter_->ClearEvents_Locked(POLLERR); |
274 } | 293 } |
275 return 0; | 294 return 0; |
276 } | 295 } |
277 case TIOCGWINSZ: { | 296 case TIOCGWINSZ: { |
278 struct winsize* size = va_arg(args, struct winsize*); | 297 struct winsize* size = va_arg(args, struct winsize*); |
279 size->ws_row = rows_; | 298 size->ws_row = rows_; |
280 size->ws_col = cols_; | 299 size->ws_col = cols_; |
281 return 0; | 300 return 0; |
282 } | 301 } |
| 302 default: { |
| 303 LOG_ERROR("TtyNode:VIoctl: Unknown request: %#x", request); |
| 304 } |
283 } | 305 } |
284 | 306 |
285 return EINVAL; | 307 return EINVAL; |
286 } | 308 } |
287 | 309 |
288 Error TtyNode::Tcgetattr(struct termios* termios_p) { | 310 Error TtyNode::Tcgetattr(struct termios* termios_p) { |
289 AUTO_LOCK(node_lock_); | 311 AUTO_LOCK(node_lock_); |
290 *termios_p = termios_; | 312 *termios_p = termios_; |
291 return 0; | 313 return 0; |
292 } | 314 } |
293 | 315 |
294 Error TtyNode::Tcsetattr(int optional_actions, | 316 Error TtyNode::Tcsetattr(int optional_actions, |
295 const struct termios* termios_p) { | 317 const struct termios* termios_p) { |
296 AUTO_LOCK(node_lock_); | 318 AUTO_LOCK(node_lock_); |
297 termios_ = *termios_p; | 319 termios_ = *termios_p; |
298 return 0; | 320 return 0; |
299 } | 321 } |
300 | 322 |
301 } // namespace nacl_io | 323 } // namespace nacl_io |
OLD | NEW |