Merge remote-tracking branch 'origin/v0.6'
[platform/upstream/nodejs.git] / src / tty_wrap.cc
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #include <node.h>
23 #include <node_buffer.h>
24 #include <node_vars.h>
25 #include <req_wrap.h>
26 #include <handle_wrap.h>
27 #include <stream_wrap.h>
28
29 namespace node {
30
31 using v8::Object;
32 using v8::Handle;
33 using v8::Local;
34 using v8::Persistent;
35 using v8::Value;
36 using v8::HandleScope;
37 using v8::FunctionTemplate;
38 using v8::String;
39 using v8::Function;
40 using v8::TryCatch;
41 using v8::Context;
42 using v8::Arguments;
43 using v8::Integer;
44 using v8::Undefined;
45
46 #define UNWRAP \
47   assert(!args.Holder().IsEmpty()); \
48   assert(args.Holder()->InternalFieldCount() > 0); \
49   TTYWrap* wrap =  \
50       static_cast<TTYWrap*>(args.Holder()->GetPointerFromInternalField(0)); \
51   if (!wrap) { \
52     uv_err_t err; \
53     err.code = UV_EBADF; \
54     SetErrno(err); \
55     return scope.Close(Integer::New(-1)); \
56   }
57
58
59 class TTYWrap : StreamWrap {
60  public:
61   static void Initialize(Handle<Object> target) {
62     StreamWrap::Initialize(target);
63
64     HandleScope scope;
65
66     Local<FunctionTemplate> t = FunctionTemplate::New(New);
67     t->SetClassName(String::NewSymbol("TTY"));
68
69     t->InstanceTemplate()->SetInternalFieldCount(1);
70
71     NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close);
72     NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);
73     NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref);
74
75     NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart);
76     NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
77     NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
78
79     NODE_SET_PROTOTYPE_METHOD(t, "getWindowSize", TTYWrap::GetWindowSize);
80     NODE_SET_PROTOTYPE_METHOD(t, "setRawMode", SetRawMode);
81
82     NODE_SET_METHOD(target, "isTTY", IsTTY);
83     NODE_SET_METHOD(target, "guessHandleType", GuessHandleType);
84
85     target->Set(String::NewSymbol("TTY"), t->GetFunction());
86   }
87
88  private:
89   static Handle<Value> GuessHandleType(const Arguments& args) {
90     HandleScope scope;
91     int fd = args[0]->Int32Value();
92     assert(fd >= 0);
93
94     uv_handle_type t = uv_guess_handle(fd);
95
96     switch (t) {
97       case UV_TTY:
98         return scope.Close(String::New("TTY"));
99
100       case UV_NAMED_PIPE:
101         return scope.Close(String::New("PIPE"));
102
103       case UV_FILE:
104         return scope.Close(String::New("FILE"));
105
106       default:
107         assert(0);
108         return v8::Undefined();
109     }
110   }
111
112   static Handle<Value> IsTTY(const Arguments& args) {
113     HandleScope scope;
114     int fd = args[0]->Int32Value();
115     assert(fd >= 0);
116     return uv_guess_handle(fd) == UV_TTY ? v8::True() : v8::False();
117   }
118
119   static Handle<Value> GetWindowSize(const Arguments& args) {
120     HandleScope scope;
121
122     UNWRAP
123
124     int width, height;
125     int r = uv_tty_get_winsize(&wrap->handle_, &width, &height);
126
127     if (r) {
128       SetErrno(uv_last_error(Loop()));
129       return v8::Undefined();
130     }
131
132     Local<v8::Array> a = v8::Array::New(2);
133     a->Set(0, Integer::New(width));
134     a->Set(1, Integer::New(height));
135
136     return scope.Close(a);
137   }
138
139   static Handle<Value> SetRawMode(const Arguments& args) {
140     HandleScope scope;
141
142     UNWRAP
143
144     int r = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue());
145
146     if (r) {
147       SetErrno(uv_last_error(Loop()));
148     }
149
150     return scope.Close(Integer::New(r));
151   }
152
153   static Handle<Value> New(const Arguments& args) {
154     HandleScope scope;
155
156     // This constructor should not be exposed to public javascript.
157     // Therefore we assert that we are not trying to call this as a
158     // normal function.
159     assert(args.IsConstructCall());
160
161     int fd = args[0]->Int32Value();
162     assert(fd >= 0);
163
164     TTYWrap* wrap = new TTYWrap(args.This(), fd, args[1]->IsTrue());
165     assert(wrap);
166     wrap->UpdateWriteQueueSize();
167
168     return scope.Close(args.This());
169   }
170
171   TTYWrap(Handle<Object> object, int fd, bool readable)
172       : StreamWrap(object, (uv_stream_t*)&handle_) {
173     uv_tty_init(Loop(), &handle_, fd, readable);
174   }
175
176   uv_tty_t handle_;
177 };
178
179 }  // namespace node
180
181 NODE_MODULE(node_tty_wrap, node::TTYWrap::Initialize)