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