Chromium Code Reviews| 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_ARRAY_BUFFER) { | |
| 173 LOG_ERROR("ProcessInput: expected ArrayBuffer 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 VarArrayBufferInterface* buffer_iface = ppapi->GetVarArrayBufferInterface(); | |
| 184 if (!buffer_iface) { | |
| 185 LOG_ERROR("ProcessInput: ArrayBuffer interface pointer is NULL."); | |
| 186 return EINVAL; | |
| 187 } | |
|
Sam Clegg
2014/06/17 22:29:28
I hate to do this to you now, but I think the actu
binji
2014/06/17 22:55:22
Done.
| |
| 188 | |
| 189 uint32_t num_bytes; | |
| 190 if (buffer_iface->ByteLength(message, &num_bytes) != PP_TRUE) { | |
| 191 LOG_ERROR("ProcessInput: unable to get ArrayBuffer length."); | |
| 192 return EINVAL; | |
| 193 } | |
| 194 | |
| 195 const char* buffer = static_cast<const char*>(buffer_iface->Map(message)); | |
| 196 Error error = ProcessInput(buffer, num_bytes); | |
| 197 buffer_iface->Unmap(message); | |
| 198 return error; | |
| 199 } | |
| 200 | |
| 201 Error TtyNode::ProcessInput(const char* buffer, size_t num_bytes) { | |
| 171 AUTO_LOCK(emitter_->GetLock()) | 202 AUTO_LOCK(emitter_->GetLock()) |
| 172 | 203 |
| 173 const char* buffer = message->buffer; | |
| 174 size_t num_bytes = message->length; | |
| 175 | |
| 176 for (size_t i = 0; i < num_bytes; i++) { | 204 for (size_t i = 0; i < num_bytes; i++) { |
| 177 char c = buffer[i]; | 205 char c = buffer[i]; |
| 178 // Transform characters according to input flags. | 206 // Transform characters according to input flags. |
| 179 if (c == '\r') { | 207 if (c == '\r') { |
| 180 if (termios_.c_iflag & IGNCR) | 208 if (termios_.c_iflag & IGNCR) |
| 181 continue; | 209 continue; |
| 182 if (termios_.c_iflag & ICRNL) | 210 if (termios_.c_iflag & ICRNL) |
| 183 c = '\n'; | 211 c = '\n'; |
| 184 } else if (c == '\n') { | 212 } else if (c == '\n') { |
| 185 if (termios_.c_iflag & INLCR) | 213 if (termios_.c_iflag & INLCR) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 AUTO_LOCK(output_lock_); | 269 AUTO_LOCK(output_lock_); |
| 242 if (arg == NULL) { | 270 if (arg == NULL) { |
| 243 output_handler_.handler = NULL; | 271 output_handler_.handler = NULL; |
| 244 return 0; | 272 return 0; |
| 245 } | 273 } |
| 246 if (output_handler_.handler != NULL) | 274 if (output_handler_.handler != NULL) |
| 247 return EALREADY; | 275 return EALREADY; |
| 248 output_handler_ = *arg; | 276 output_handler_ = *arg; |
| 249 return 0; | 277 return 0; |
| 250 } | 278 } |
| 251 case TIOCNACLINPUT: { | 279 case NACL_IOC_HANDLEMESSAGE: { |
| 252 // This ioctl is used to deliver data from the user to this tty node's | 280 struct PP_Var* message = va_arg(args, struct PP_Var*); |
| 253 // input buffer. | 281 return ProcessInput(*message); |
| 254 struct tioc_nacl_input_string* message = | |
| 255 va_arg(args, struct tioc_nacl_input_string*); | |
| 256 return ProcessInput(message); | |
| 257 } | 282 } |
| 258 case TIOCSWINSZ: { | 283 case TIOCSWINSZ: { |
| 259 struct winsize* size = va_arg(args, struct winsize*); | 284 struct winsize* size = va_arg(args, struct winsize*); |
| 260 { | 285 { |
| 261 AUTO_LOCK(node_lock_); | 286 AUTO_LOCK(node_lock_); |
| 262 if (rows_ == size->ws_row && cols_ == size->ws_col) | 287 if (rows_ == size->ws_row && cols_ == size->ws_col) |
| 263 return 0; | 288 return 0; |
| 264 rows_ = size->ws_row; | 289 rows_ = size->ws_row; |
| 265 cols_ = size->ws_col; | 290 cols_ = size->ws_col; |
| 266 } | 291 } |
| 267 ki_kill(getpid(), SIGWINCH); | 292 ki_kill(getpid(), SIGWINCH); |
| 268 { | 293 { |
| 269 // Wake up any thread waiting on Read with POLLERR then immediate | 294 // Wake up any thread waiting on Read with POLLERR then immediate |
| 270 // clear it to signal EINTR. | 295 // clear it to signal EINTR. |
| 271 AUTO_LOCK(emitter_->GetLock()) | 296 AUTO_LOCK(emitter_->GetLock()) |
| 272 emitter_->RaiseEvents_Locked(POLLERR); | 297 emitter_->RaiseEvents_Locked(POLLERR); |
| 273 emitter_->ClearEvents_Locked(POLLERR); | 298 emitter_->ClearEvents_Locked(POLLERR); |
| 274 } | 299 } |
| 275 return 0; | 300 return 0; |
| 276 } | 301 } |
| 277 case TIOCGWINSZ: { | 302 case TIOCGWINSZ: { |
| 278 struct winsize* size = va_arg(args, struct winsize*); | 303 struct winsize* size = va_arg(args, struct winsize*); |
| 279 size->ws_row = rows_; | 304 size->ws_row = rows_; |
| 280 size->ws_col = cols_; | 305 size->ws_col = cols_; |
| 281 return 0; | 306 return 0; |
| 282 } | 307 } |
| 308 default: { | |
| 309 LOG_ERROR("TtyNode:VIoctl: Unknown request: %#x", request); | |
| 310 } | |
| 283 } | 311 } |
| 284 | 312 |
| 285 return EINVAL; | 313 return EINVAL; |
| 286 } | 314 } |
| 287 | 315 |
| 288 Error TtyNode::Tcgetattr(struct termios* termios_p) { | 316 Error TtyNode::Tcgetattr(struct termios* termios_p) { |
| 289 AUTO_LOCK(node_lock_); | 317 AUTO_LOCK(node_lock_); |
| 290 *termios_p = termios_; | 318 *termios_p = termios_; |
| 291 return 0; | 319 return 0; |
| 292 } | 320 } |
| 293 | 321 |
| 294 Error TtyNode::Tcsetattr(int optional_actions, | 322 Error TtyNode::Tcsetattr(int optional_actions, |
| 295 const struct termios* termios_p) { | 323 const struct termios* termios_p) { |
| 296 AUTO_LOCK(node_lock_); | 324 AUTO_LOCK(node_lock_); |
| 297 termios_ = *termios_p; | 325 termios_ = *termios_p; |
| 298 return 0; | 326 return 0; |
| 299 } | 327 } |
| 300 | 328 |
| 301 } // namespace nacl_io | 329 } // namespace nacl_io |
| OLD | NEW |