Display sys_errno when UV_UNKNOWN is returned
[platform/upstream/nodejs.git] / src / tty_wrap.cc
1 #include <node.h>
2 #include <node_buffer.h>
3 #include <req_wrap.h>
4 #include <handle_wrap.h>
5 #include <stream_wrap.h>
6
7 namespace node {
8
9 using v8::Object;
10 using v8::Handle;
11 using v8::Local;
12 using v8::Persistent;
13 using v8::Value;
14 using v8::HandleScope;
15 using v8::FunctionTemplate;
16 using v8::String;
17 using v8::Function;
18 using v8::TryCatch;
19 using v8::Context;
20 using v8::Arguments;
21 using v8::Integer;
22 using v8::Undefined;
23
24 #define UNWRAP \
25   assert(!args.Holder().IsEmpty()); \
26   assert(args.Holder()->InternalFieldCount() > 0); \
27   TTYWrap* wrap =  \
28       static_cast<TTYWrap*>(args.Holder()->GetPointerFromInternalField(0)); \
29   if (!wrap) { \
30     uv_err_t err; \
31     err.code = UV_EBADF; \
32     SetErrno(err); \
33     return scope.Close(Integer::New(-1)); \
34   }
35
36
37 class TTYWrap : StreamWrap {
38  public:
39   static void Initialize(Handle<Object> target) {
40     StreamWrap::Initialize(target);
41
42     HandleScope scope;
43
44     Local<FunctionTemplate> t = FunctionTemplate::New(New);
45     t->SetClassName(String::NewSymbol("TTY"));
46
47     t->InstanceTemplate()->SetInternalFieldCount(1);
48
49     NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close);
50     NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);
51
52     NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart);
53     NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
54     NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
55
56     NODE_SET_PROTOTYPE_METHOD(t, "getWindowSize", TTYWrap::GetWindowSize);
57     NODE_SET_PROTOTYPE_METHOD(t, "setRawMode", SetRawMode);
58
59     NODE_SET_METHOD(target, "isTTY", IsTTY);
60     NODE_SET_METHOD(target, "guessHandleType", GuessHandleType);
61
62     target->Set(String::NewSymbol("TTY"), t->GetFunction());
63   }
64
65  private:
66   static Handle<Value> GuessHandleType(const Arguments& args) {
67     HandleScope scope;
68     int fd = args[0]->Int32Value();
69     assert(fd >= 0);
70
71     uv_handle_type t = uv_guess_handle(fd);
72
73     switch (t) {
74       case UV_TTY:
75         return scope.Close(String::New("TTY"));
76
77       case UV_NAMED_PIPE:
78         return scope.Close(String::New("PIPE"));
79
80       case UV_FILE:
81         return scope.Close(String::New("FILE"));
82
83       default:
84         assert(0);
85         return v8::Undefined();
86     }
87   }
88
89   static Handle<Value> IsTTY(const Arguments& args) {
90     HandleScope scope;
91     int fd = args[0]->Int32Value();
92     assert(fd >= 0);
93     return uv_guess_handle(fd) == UV_TTY ? v8::True() : v8::False();
94   }
95
96   static Handle<Value> GetWindowSize(const Arguments& args) {
97     HandleScope scope;
98     
99     UNWRAP
100
101     int width, height;
102     int r = uv_tty_get_winsize(&wrap->handle_, &width, &height);
103
104     if (r) {
105       SetErrno(uv_last_error(uv_default_loop()));
106       return v8::Undefined();
107     }
108
109     Local<v8::Array> a = v8::Array::New(2);
110     a->Set(0, Integer::New(width));
111     a->Set(1, Integer::New(height));
112
113     return scope.Close(a);
114   }
115
116   static Handle<Value> SetRawMode(const Arguments& args) {
117     HandleScope scope;
118
119     UNWRAP
120
121     int r = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue());
122
123     if (r) {
124       SetErrno(uv_last_error(uv_default_loop()));
125     }
126
127     return scope.Close(Integer::New(r));
128   }
129
130   static Handle<Value> New(const Arguments& args) {
131     HandleScope scope;
132
133     // This constructor should not be exposed to public javascript.
134     // Therefore we assert that we are not trying to call this as a
135     // normal function.
136     assert(args.IsConstructCall());
137
138     int fd = args[0]->Int32Value();
139     assert(fd >= 0);
140
141     TTYWrap* wrap = new TTYWrap(args.This(), fd, args[1]->IsTrue());
142     assert(wrap);
143     wrap->UpdateWriteQueueSize();
144
145     return scope.Close(args.This());
146   }
147
148   TTYWrap(Handle<Object> object, int fd, bool readable)
149       : StreamWrap(object, (uv_stream_t*)&handle_) {
150     uv_tty_init(uv_default_loop(), &handle_, fd, readable);
151   }
152
153   uv_tty_t handle_;
154 };
155
156 }  // namespace node
157
158 NODE_MODULE(node_tty_wrap, node::TTYWrap::Initialize);