xref: /third_party/node/src/tty_wrap.cc (revision 1cb0ef41)
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 "tty_wrap.h"
23
24#include "env-inl.h"
25#include "handle_wrap.h"
26#include "node_buffer.h"
27#include "node_external_reference.h"
28#include "stream_base-inl.h"
29#include "stream_wrap.h"
30#include "util-inl.h"
31
32namespace node {
33
34using v8::Array;
35using v8::Context;
36using v8::FunctionCallbackInfo;
37using v8::FunctionTemplate;
38using v8::Integer;
39using v8::Isolate;
40using v8::Local;
41using v8::Object;
42using v8::String;
43using v8::Value;
44
45void TTYWrap::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
46  registry->Register(New);
47  registry->Register(GetWindowSize);
48  registry->Register(SetRawMode);
49  registry->Register(IsTTY);
50}
51
52void TTYWrap::Initialize(Local<Object> target,
53                         Local<Value> unused,
54                         Local<Context> context,
55                         void* priv) {
56  Environment* env = Environment::GetCurrent(context);
57  Isolate* isolate = env->isolate();
58
59  Local<String> ttyString = FIXED_ONE_BYTE_STRING(env->isolate(), "TTY");
60
61  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
62  t->SetClassName(ttyString);
63  t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount);
64  t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env));
65
66  SetProtoMethodNoSideEffect(
67      isolate, t, "getWindowSize", TTYWrap::GetWindowSize);
68  SetProtoMethod(isolate, t, "setRawMode", SetRawMode);
69
70  SetMethodNoSideEffect(context, target, "isTTY", IsTTY);
71
72  Local<Value> func;
73  if (t->GetFunction(context).ToLocal(&func) &&
74      target->Set(context, ttyString, func).IsJust()) {
75    env->set_tty_constructor_template(t);
76  }
77}
78
79
80void TTYWrap::IsTTY(const FunctionCallbackInfo<Value>& args) {
81  Environment* env = Environment::GetCurrent(args);
82  int fd;
83  if (!args[0]->Int32Value(env->context()).To(&fd)) return;
84  CHECK_GE(fd, 0);
85  bool rc = uv_guess_handle(fd) == UV_TTY;
86  args.GetReturnValue().Set(rc);
87}
88
89
90void TTYWrap::GetWindowSize(const FunctionCallbackInfo<Value>& args) {
91  Environment* env = Environment::GetCurrent(args);
92
93  TTYWrap* wrap;
94  ASSIGN_OR_RETURN_UNWRAP(&wrap,
95                          args.Holder(),
96                          args.GetReturnValue().Set(UV_EBADF));
97  CHECK(args[0]->IsArray());
98
99  int width, height;
100  int err = uv_tty_get_winsize(&wrap->handle_, &width, &height);
101
102  if (err == 0) {
103    Local<Array> a = args[0].As<Array>();
104    a->Set(env->context(), 0, Integer::New(env->isolate(), width)).Check();
105    a->Set(env->context(), 1, Integer::New(env->isolate(), height)).Check();
106  }
107
108  args.GetReturnValue().Set(err);
109}
110
111
112void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) {
113  TTYWrap* wrap;
114  ASSIGN_OR_RETURN_UNWRAP(&wrap,
115                          args.Holder(),
116                          args.GetReturnValue().Set(UV_EBADF));
117  int err = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue());
118  args.GetReturnValue().Set(err);
119}
120
121
122void TTYWrap::New(const FunctionCallbackInfo<Value>& args) {
123  Environment* env = Environment::GetCurrent(args);
124
125  // This constructor should not be exposed to public javascript.
126  // Therefore we assert that we are not trying to call this as a
127  // normal function.
128  CHECK(args.IsConstructCall());
129
130  int fd;
131  if (!args[0]->Int32Value(env->context()).To(&fd)) return;
132  CHECK_GE(fd, 0);
133
134  int err = 0;
135  new TTYWrap(env, args.This(), fd, &err);
136  if (err != 0) {
137    env->CollectUVExceptionInfo(args[1], err, "uv_tty_init");
138    args.GetReturnValue().SetUndefined();
139  }
140}
141
142
143TTYWrap::TTYWrap(Environment* env,
144                 Local<Object> object,
145                 int fd,
146                 int* init_err)
147    : LibuvStreamWrap(env,
148                      object,
149                      reinterpret_cast<uv_stream_t*>(&handle_),
150                      AsyncWrap::PROVIDER_TTYWRAP) {
151  *init_err = uv_tty_init(env->event_loop(), &handle_, fd, 0);
152  set_fd(fd);
153  if (*init_err != 0)
154    MarkAsUninitialized();
155}
156
157}  // namespace node
158
159NODE_BINDING_CONTEXT_AWARE_INTERNAL(tty_wrap, node::TTYWrap::Initialize)
160NODE_BINDING_EXTERNAL_REFERENCE(tty_wrap,
161                                node::TTYWrap::RegisterExternalReferences)
162