Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc

Issue 23005005: [NaCl SDK] nacl_io: Add initial implementations of kill and signal (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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/mount_node_tty.h" 5 #include "nacl_io/mount_node_tty.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 <stdio.h> 10 #include <stdio.h>
10 #include <string.h> 11 #include <string.h>
12 #include <sys/ioctl.h>
13 #include <unistd.h>
11 14
12 #include <algorithm> 15 #include <algorithm>
13 16
17 #include "nacl_io/dbgprint.h"
14 #include "nacl_io/ioctl.h" 18 #include "nacl_io/ioctl.h"
15 #include "nacl_io/mount.h" 19 #include "nacl_io/mount.h"
16 #include "nacl_io/pepper_interface.h" 20 #include "nacl_io/pepper_interface.h"
17 #include "sdk_util/auto_lock.h" 21 #include "sdk_util/auto_lock.h"
18 22
19 #define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS .c_lflag & FLAG) 23 #define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS .c_lflag & FLAG)
20 24
21 #define IS_ECHO CHECK_LFLAG(termios_, ECHO) 25 #define IS_ECHO CHECK_LFLAG(termios_, ECHO)
22 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE) 26 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE)
23 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL) 27 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL)
24 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL) 28 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL)
25 #define IS_ICANON CHECK_LFLAG(termios_, ICANON) 29 #define IS_ICANON CHECK_LFLAG(termios_, ICANON)
26 30
27 namespace nacl_io { 31 namespace nacl_io {
28 32
29 MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount), 33 MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount),
30 is_readable_(false) { 34 is_readable_(false),
35 did_resize_(false),
36 rows_(10),
binji 2013/08/21 17:42:01 use consts. BTW, why 10?
Sam Clegg 2013/08/22 03:32:45 Done. Changed default rows to 30. Is there a mor
binji 2013/08/22 18:09:36 25 or 50, is what I remember, but I guess it proba
37 cols_(80) {
31 pthread_cond_init(&is_readable_cond_, NULL); 38 pthread_cond_init(&is_readable_cond_, NULL);
32 InitTermios(); 39 InitTermios();
33 } 40 }
34 41
35 void MountNodeTty::InitTermios() { 42 void MountNodeTty::InitTermios() {
36 // Some sane values that produce good result. 43 // Some sane values that produce good result.
37 termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8; 44 termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8;
38 termios_.c_oflag = OPOST | ONLCR; 45 termios_.c_oflag = OPOST | ONLCR;
39 termios_.c_cflag = CREAD | 077; 46 termios_.c_cflag = CREAD | 077;
40 termios_.c_lflag = 47 termios_.c_lflag =
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 uint32_t len = static_cast<uint32_t>(message.size()); 109 uint32_t len = static_cast<uint32_t>(message.size());
103 struct PP_Var val = var_intr->VarFromUtf8(message.data(), len); 110 struct PP_Var val = var_intr->VarFromUtf8(message.data(), len);
104 msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val); 111 msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
105 var_intr->Release(val); 112 var_intr->Release(val);
106 *out_bytes = count; 113 *out_bytes = count;
107 return 0; 114 return 0;
108 } 115 }
109 116
110 Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) { 117 Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
111 AUTO_LOCK(node_lock_); 118 AUTO_LOCK(node_lock_);
119 did_resize_ = false;
112 while (!is_readable_) { 120 while (!is_readable_) {
113 pthread_cond_wait(&is_readable_cond_, node_lock_.mutex()); 121 pthread_cond_wait(&is_readable_cond_, node_lock_.mutex());
122 if (!is_readable_ && did_resize_) {
123 // If an async resize event occured then return the failure and
124 // set EINTR.
125 *out_bytes = 0;
126 return EINTR;
127 }
114 } 128 }
115 129
116 size_t bytes_to_copy = std::min(count, input_buffer_.size()); 130 size_t bytes_to_copy = std::min(count, input_buffer_.size());
117 131
118 if (IS_ICANON) { 132 if (IS_ICANON) {
119 // Only read up to (and including) the first newline 133 // Only read up to (and including) the first newline
120 std::deque<char>::iterator nl = std::find(input_buffer_.begin(), 134 std::deque<char>::iterator nl = std::find(input_buffer_.begin(),
121 input_buffer_.end(), 135 input_buffer_.end(),
122 '\n'); 136 '\n');
123 137
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 if (error != 0 || wrote != count) { 169 if (error != 0 || wrote != count) {
156 // TOOD(sbc): Do something more useful in response to a 170 // TOOD(sbc): Do something more useful in response to a
157 // failure to echo. 171 // failure to echo.
158 return error; 172 return error;
159 } 173 }
160 174
161 return 0; 175 return 0;
162 } 176 }
163 177
164 Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) { 178 Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) {
165 AUTO_LOCK(node_lock_); 179 sdk_util::AutoLock lock(node_lock_);
166 if (message->length < prefix_.size() || 180 if (message->length < prefix_.size() ||
167 strncmp(message->buffer, prefix_.data(), prefix_.size()) != 0) { 181 strncmp(message->buffer, prefix_.data(), prefix_.size()) != 0) {
168 return ENOTTY; 182 return ENOTTY;
169 } 183 }
170 184
171 const char* buffer = message->buffer + prefix_.size(); 185 const char* buffer = message->buffer + prefix_.size();
172 int num_bytes = message->length - prefix_.size(); 186 int num_bytes = message->length - prefix_.size();
173 187
188 if (!strncmp(buffer, "resize:", 7)) {
189 num_bytes -= 7;
190 buffer += 7;
191
192 struct winsize size;
193 int rtn = sscanf(buffer, "%hdx%hd", &size.ws_col, &size.ws_row);
194 if (rtn != 2) {
195 dbgprintf("error parsing resize: '%s' %d\n", buffer, rtn);
196 return ENOTTY;
197 }
198 lock.Unlock();
199 //dbgprintf("got resize from JS\n");
200 this->Ioctl(TIOCSWINSZ, reinterpret_cast<char*>(&size));
201 return 0;
202 } else if (!strncmp(buffer, "input:", 6)) {
203 num_bytes -= 6;
204 buffer += 6;
205 } else {
206 dbgprintf("error parsing input: '%s'\n", message->buffer);
207 return ENOTTY;
208 }
209
174 for (int i = 0; i < num_bytes; i++) { 210 for (int i = 0; i < num_bytes; i++) {
175 char c = buffer[i]; 211 char c = buffer[i];
176 // Transform characters according to input flags. 212 // Transform characters according to input flags.
177 if (c == '\r') { 213 if (c == '\r') {
178 if (termios_.c_iflag & IGNCR) 214 if (termios_.c_iflag & IGNCR)
179 continue; 215 continue;
180 if (termios_.c_iflag & ICRNL) 216 if (termios_.c_iflag & ICRNL)
181 c = '\n'; 217 c = '\n';
182 } else if (c == '\n') { 218 } else if (c == '\n') {
183 if (termios_.c_iflag & INLCR) 219 if (termios_.c_iflag & INLCR)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 } 266 }
231 267
232 if (is_readable_) { 268 if (is_readable_) {
233 RaiseEvent(POLLIN); 269 RaiseEvent(POLLIN);
234 pthread_cond_broadcast(&is_readable_cond_); 270 pthread_cond_broadcast(&is_readable_cond_);
235 } 271 }
236 return 0; 272 return 0;
237 } 273 }
238 274
239 Error MountNodeTty::Ioctl(int request, char* arg) { 275 Error MountNodeTty::Ioctl(int request, char* arg) {
240 if (request == TIOCNACLPREFIX) { 276 switch (request) {
241 // This ioctl is used to change the prefix for this tty node. 277 case TIOCNACLPREFIX: {
242 // The prefix is used to distinguish messages intended for this 278 // This ioctl is used to change the prefix for this tty node.
243 // tty node from all the other messages cluttering up the 279 // The prefix is used to distinguish messages intended for this
244 // javascript postMessage() channel. 280 // tty node from all the other messages cluttering up the
245 AUTO_LOCK(node_lock_); 281 // javascript postMessage() channel.
246 prefix_ = arg; 282 AUTO_LOCK(node_lock_);
247 return 0; 283 prefix_ = arg;
248 } else if (request == TIOCNACLINPUT) { 284 return 0;
249 // This ioctl is used to deliver data from the user to this tty node's 285 }
250 // input buffer. We check if the prefix in the input data matches the 286 case TIOCNACLINPUT: {
251 // prefix for this node, and only deliver the data if so. 287 // This ioctl is used to deliver data from the user to this tty node's
252 struct tioc_nacl_input_string* message = 288 // input buffer. We check if the prefix in the input data matches the
253 reinterpret_cast<struct tioc_nacl_input_string*>(arg); 289 // prefix for this node, and only deliver the data if so.
254 return ProcessInput(message); 290 struct tioc_nacl_input_string* message =
255 } else { 291 reinterpret_cast<struct tioc_nacl_input_string*>(arg);
256 return EINVAL; 292 return ProcessInput(message);
293 }
294 case TIOCSWINSZ: {
295 struct winsize* size = reinterpret_cast<struct winsize*>(arg);
296 {
297 AUTO_LOCK(node_lock_);
298 rows_ = size->ws_row;
299 cols_ = size->ws_col;
300 }
301 //dbgprintf("tty TIOCSWINSZ: %d %d\n", cols_, rows_);
302 kill(getpid(), SIGWINCH);
303
304 // Wake up any thread waiting on Read
305 {
306 AUTO_LOCK(node_lock_);
307 did_resize_ = true;
308 pthread_cond_broadcast(&is_readable_cond_);
309 }
310 return 0;
311 }
312 case TIOCGWINSZ: {
313 struct winsize* size = reinterpret_cast<struct winsize*>(arg);
314 size->ws_row = rows_;
315 size->ws_col = cols_;
316 //dbgprintf("tty TIOCGWINSZ: %d %d\n", cols_, rows_);
317 return 0;
318 }
257 } 319 }
320 return EINVAL;
258 } 321 }
259 322
260 Error MountNodeTty::Tcgetattr(struct termios* termios_p) { 323 Error MountNodeTty::Tcgetattr(struct termios* termios_p) {
324 //dbgprintf("tcgetattr\n");
261 AUTO_LOCK(node_lock_); 325 AUTO_LOCK(node_lock_);
262 *termios_p = termios_; 326 *termios_p = termios_;
263 return 0; 327 return 0;
264 } 328 }
265 329
266 Error MountNodeTty::Tcsetattr(int optional_actions, 330 Error MountNodeTty::Tcsetattr(int optional_actions,
267 const struct termios *termios_p) { 331 const struct termios *termios_p) {
332 //dbgprintf("tcsetattr\n");
268 AUTO_LOCK(node_lock_); 333 AUTO_LOCK(node_lock_);
269 termios_ = *termios_p; 334 termios_ = *termios_p;
270 return 0; 335 return 0;
271 } 336 }
272 337
273 } 338 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698