1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use std::rt::io::IoError;
13 use std::rt::local::Local;
14 use std::rt::rtio::RtioTTY;
15 use std::rt::sched::{Scheduler, SchedHandle};
17 use stream::StreamWatcher;
18 use super::{Loop, UvError, UvHandle, uv_error_to_io_error};
22 pub struct TtyWatcher{
24 stream: StreamWatcher,
30 pub fn new(loop_: &Loop, fd: libc::c_int, readable: bool)
31 -> Result<TtyWatcher, UvError>
33 // libuv may succeed in giving us a handle (via uv_tty_init), but if the
34 // handle isn't actually connected to a terminal there are frequently
35 // many problems in using it with libuv. To get around this, always
36 // return a failure if the specified file descriptor isn't actually a
40 // - https://github.com/joyent/libuv/issues/982
41 // - https://github.com/joyent/libuv/issues/988
42 if unsafe { uvll::guess_handle(fd) != uvll::UV_TTY as libc::c_int } {
43 return Err(UvError(uvll::EBADF));
46 // If this file descriptor is indeed guessed to be a tty, then go ahead
47 // with attempting to open it as a tty.
48 let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
50 uvll::uv_tty_init(loop_.handle, handle, fd as libc::c_int,
51 readable as libc::c_int)
56 stream: StreamWatcher::new(handle),
57 home: get_handle_to_current_scheduler!(),
62 unsafe { uvll::free_handle(handle) }
69 impl RtioTTY for TtyWatcher {
70 fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
71 let _m = self.fire_homing_missile();
72 self.stream.read(buf).map_err(uv_error_to_io_error)
75 fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
76 let _m = self.fire_homing_missile();
77 self.stream.write(buf).map_err(uv_error_to_io_error)
80 fn set_raw(&mut self, raw: bool) -> Result<(), IoError> {
81 let raw = raw as libc::c_int;
82 let _m = self.fire_homing_missile();
83 match unsafe { uvll::uv_tty_set_mode(self.tty, raw) } {
85 n => Err(uv_error_to_io_error(UvError(n)))
90 fn get_winsize(&mut self) -> Result<(int, int), IoError> {
91 let mut width: libc::c_int = 0;
92 let mut height: libc::c_int = 0;
93 let widthptr: *libc::c_int = &width;
94 let heightptr: *libc::c_int = &width;
96 let _m = self.fire_homing_missile();
97 match unsafe { uvll::uv_tty_get_winsize(self.tty,
98 widthptr, heightptr) } {
99 0 => Ok((width as int, height as int)),
100 n => Err(uv_error_to_io_error(UvError(n)))
105 impl UvHandle<uvll::uv_tty_t> for TtyWatcher {
106 fn uv_handle(&self) -> *uvll::uv_tty_t { self.tty }
109 impl HomingIO for TtyWatcher {
110 fn home<'a>(&'a mut self) -> &'a mut SchedHandle { &mut self.home }
113 impl Drop for TtyWatcher {
115 let _m = self.fire_homing_missile();