X-Git-Url: https://git.josue.xyz/?p=VSoRC%2F.git;a=blobdiff_plain;f=node_modules%2Fnode-pty%2Fsrc%2Funix%2Fpty.cc;fp=node_modules%2Fnode-pty%2Fsrc%2Funix%2Fpty.cc;h=0000000000000000000000000000000000000000;hp=d2f4c1131d7e91c714682e336848d764cc947620;hb=5e96dd57ddd883604e87f62bdddcb111c63a6e1a;hpb=acb5f682a2b75b972710cabd81658f63071324b0 diff --git a/node_modules/node-pty/src/unix/pty.cc b/node_modules/node-pty/src/unix/pty.cc deleted file mode 100644 index d2f4c11..0000000 --- a/node_modules/node-pty/src/unix/pty.cc +++ /dev/null @@ -1,708 +0,0 @@ -/** - * Copyright (c) 2012-2015, Christopher Jeffrey (MIT License) - * Copyright (c) 2017, Daniel Imms (MIT License) - * - * pty.cc: - * This file is responsible for starting processes - * with pseudo-terminal file descriptors. - * - * See: - * man pty - * man tty_ioctl - * man termios - * man forkpty - */ - -/** - * Includes - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* forkpty */ -/* http://www.gnu.org/software/gnulib/manual/html_node/forkpty.html */ -#if defined(__GLIBC__) || defined(__CYGWIN__) -#include -#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) -#include -#elif defined(__FreeBSD__) -#include -#elif defined(__sun) -#include /* for I_PUSH */ -#else -#include -#endif - -#include /* tcgetattr, tty_ioctl */ - -/* Some platforms name VWERASE and VDISCARD differently */ -#if !defined(VWERASE) && defined(VWERSE) -#define VWERASE VWERSE -#endif -#if !defined(VDISCARD) && defined(VDISCRD) -#define VDISCARD VDISCRD -#endif - -/* environ for execvpe */ -/* node/src/node_child_process.cc */ -#if defined(__APPLE__) && !TARGET_OS_IPHONE -#include -#define environ (*_NSGetEnviron()) -#else -extern char **environ; -#endif - -/* for pty_getproc */ -#if defined(__linux__) -#include -#include -#elif defined(__APPLE__) -#include -#include -#endif - -/** - * Structs - */ - -struct pty_baton { - Nan::Persistent cb; - int exit_code; - int signal_code; - pid_t pid; - uv_async_t async; - uv_thread_t tid; -}; - -/** - * Methods - */ - -NAN_METHOD(PtyFork); -NAN_METHOD(PtyOpen); -NAN_METHOD(PtyResize); -NAN_METHOD(PtyGetProc); - -/** - * Functions - */ - -static int -pty_execvpe(const char *, char **, char **); - -static int -pty_nonblock(int); - -static char * -pty_getproc(int, char *); - -static int -pty_openpty(int *, int *, char *, - const struct termios *, - const struct winsize *); - -static pid_t -pty_forkpty(int *, char *, - const struct termios *, - const struct winsize *); - -static void -pty_waitpid(void *); - -static void -pty_after_waitpid(uv_async_t *); - -static void -pty_after_close(uv_handle_t *); - -NAN_METHOD(PtyFork) { - Nan::HandleScope scope; - - if (info.Length() != 10 || - !info[0]->IsString() || - !info[1]->IsArray() || - !info[2]->IsArray() || - !info[3]->IsString() || - !info[4]->IsNumber() || - !info[5]->IsNumber() || - !info[6]->IsNumber() || - !info[7]->IsNumber() || - !info[8]->IsBoolean() || - !info[9]->IsFunction()) { - return Nan::ThrowError( - "Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, onexit)"); - } - - // Make sure the process still listens to SIGINT - signal(SIGINT, SIG_DFL); - - // file - Nan::Utf8String file(info[0]); - - // args - int i = 0; - v8::Local argv_ = v8::Local::Cast(info[1]); - int argc = argv_->Length(); - int argl = argc + 1 + 1; - char **argv = new char*[argl]; - argv[0] = strdup(*file); - argv[argl-1] = NULL; - for (; i < argc; i++) { - Nan::Utf8String arg(Nan::Get(argv_, i).ToLocalChecked()); - argv[i+1] = strdup(*arg); - } - - // env - i = 0; - v8::Local env_ = v8::Local::Cast(info[2]); - int envc = env_->Length(); - char **env = new char*[envc+1]; - env[envc] = NULL; - for (; i < envc; i++) { - Nan::Utf8String pair(Nan::Get(env_, i).ToLocalChecked()); - env[i] = strdup(*pair); - } - - // cwd - Nan::Utf8String cwd_(info[3]); - char *cwd = strdup(*cwd_); - - // size - struct winsize winp; - winp.ws_col = info[4]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_row = info[5]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_xpixel = 0; - winp.ws_ypixel = 0; - - // termios - struct termios t = termios(); - struct termios *term = &t; - term->c_iflag = ICRNL | IXON | IXANY | IMAXBEL | BRKINT; - if (Nan::To(info[8]).FromJust()) { -#if defined(IUTF8) - term->c_iflag |= IUTF8; -#endif - } - term->c_oflag = OPOST | ONLCR; - term->c_cflag = CREAD | CS8 | HUPCL; - term->c_lflag = ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL; - - term->c_cc[VEOF] = 4; - term->c_cc[VEOL] = -1; - term->c_cc[VEOL2] = -1; - term->c_cc[VERASE] = 0x7f; - term->c_cc[VWERASE] = 23; - term->c_cc[VKILL] = 21; - term->c_cc[VREPRINT] = 18; - term->c_cc[VINTR] = 3; - term->c_cc[VQUIT] = 0x1c; - term->c_cc[VSUSP] = 26; - term->c_cc[VSTART] = 17; - term->c_cc[VSTOP] = 19; - term->c_cc[VLNEXT] = 22; - term->c_cc[VDISCARD] = 15; - term->c_cc[VMIN] = 1; - term->c_cc[VTIME] = 0; - - #if (__APPLE__) - term->c_cc[VDSUSP] = 25; - term->c_cc[VSTATUS] = 20; - #endif - - cfsetispeed(term, B38400); - cfsetospeed(term, B38400); - - // uid / gid - int uid = info[6]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - int gid = info[7]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - - // fork the pty - int master = -1; - pid_t pid = pty_forkpty(&master, nullptr, term, &winp); - - if (pid) { - for (i = 0; i < argl; i++) free(argv[i]); - delete[] argv; - for (i = 0; i < envc; i++) free(env[i]); - delete[] env; - free(cwd); - } - - switch (pid) { - case -1: - return Nan::ThrowError("forkpty(3) failed."); - case 0: - if (strlen(cwd)) { - if (chdir(cwd) == -1) { - perror("chdir(2) failed."); - _exit(1); - } - } - - if (uid != -1 && gid != -1) { - if (setgid(gid) == -1) { - perror("setgid(2) failed."); - _exit(1); - } - if (setuid(uid) == -1) { - perror("setuid(2) failed."); - _exit(1); - } - } - - pty_execvpe(argv[0], argv, env); - - perror("execvp(3) failed."); - _exit(1); - default: - if (pty_nonblock(master) == -1) { - return Nan::ThrowError("Could not set master fd to nonblocking."); - } - - v8::Local obj = Nan::New(); - Nan::Set(obj, - Nan::New("fd").ToLocalChecked(), - Nan::New(master)); - Nan::Set(obj, - Nan::New("pid").ToLocalChecked(), - Nan::New(pid)); - Nan::Set(obj, - Nan::New("pty").ToLocalChecked(), - Nan::New(ptsname(master)).ToLocalChecked()); - - pty_baton *baton = new pty_baton(); - baton->exit_code = 0; - baton->signal_code = 0; - baton->cb.Reset(v8::Local::Cast(info[9])); - baton->pid = pid; - baton->async.data = baton; - - uv_async_init(uv_default_loop(), &baton->async, pty_after_waitpid); - - uv_thread_create(&baton->tid, pty_waitpid, static_cast(baton)); - - return info.GetReturnValue().Set(obj); - } - - return info.GetReturnValue().SetUndefined(); -} - -NAN_METHOD(PtyOpen) { - Nan::HandleScope scope; - - if (info.Length() != 2 || - !info[0]->IsNumber() || - !info[1]->IsNumber()) { - return Nan::ThrowError("Usage: pty.open(cols, rows)"); - } - - // size - struct winsize winp; - winp.ws_col = info[0]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_row = info[1]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_xpixel = 0; - winp.ws_ypixel = 0; - - // pty - int master, slave; - int ret = pty_openpty(&master, &slave, nullptr, NULL, &winp); - - if (ret == -1) { - return Nan::ThrowError("openpty(3) failed."); - } - - if (pty_nonblock(master) == -1) { - return Nan::ThrowError("Could not set master fd to nonblocking."); - } - - if (pty_nonblock(slave) == -1) { - return Nan::ThrowError("Could not set slave fd to nonblocking."); - } - - v8::Local obj = Nan::New(); - Nan::Set(obj, - Nan::New("master").ToLocalChecked(), - Nan::New(master)); - Nan::Set(obj, - Nan::New("slave").ToLocalChecked(), - Nan::New(slave)); - Nan::Set(obj, - Nan::New("pty").ToLocalChecked(), - Nan::New(ptsname(master)).ToLocalChecked()); - - return info.GetReturnValue().Set(obj); -} - -NAN_METHOD(PtyResize) { - Nan::HandleScope scope; - - if (info.Length() != 3 || - !info[0]->IsNumber() || - !info[1]->IsNumber() || - !info[2]->IsNumber()) { - return Nan::ThrowError("Usage: pty.resize(fd, cols, rows)"); - } - - int fd = info[0]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - - struct winsize winp; - winp.ws_col = info[1]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_row = info[2]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - winp.ws_xpixel = 0; - winp.ws_ypixel = 0; - - if (ioctl(fd, TIOCSWINSZ, &winp) == -1) { - switch (errno) { - case EBADF: return Nan::ThrowError("ioctl(2) failed, EBADF"); - case EFAULT: return Nan::ThrowError("ioctl(2) failed, EFAULT"); - case EINVAL: return Nan::ThrowError("ioctl(2) failed, EINVAL"); - case ENOTTY: return Nan::ThrowError("ioctl(2) failed, ENOTTY"); - } - return Nan::ThrowError("ioctl(2) failed"); - } - - return info.GetReturnValue().SetUndefined(); -} - -/** - * Foreground Process Name - */ -NAN_METHOD(PtyGetProc) { - Nan::HandleScope scope; - - if (info.Length() != 2 || - !info[0]->IsNumber() || - !info[1]->IsString()) { - return Nan::ThrowError("Usage: pty.process(fd, tty)"); - } - - int fd = info[0]->IntegerValue(Nan::GetCurrentContext()).FromJust(); - - Nan::Utf8String tty_(info[1]); - char *tty = strdup(*tty_); - char *name = pty_getproc(fd, tty); - free(tty); - - if (name == NULL) { - return info.GetReturnValue().SetUndefined(); - } - - v8::Local name_ = Nan::New(name).ToLocalChecked(); - free(name); - return info.GetReturnValue().Set(name_); -} - -/** - * execvpe - */ - -// execvpe(3) is not portable. -// http://www.gnu.org/software/gnulib/manual/html_node/execvpe.html -static int -pty_execvpe(const char *file, char **argv, char **envp) { - char **old = environ; - environ = envp; - int ret = execvp(file, argv); - environ = old; - return ret; -} - -/** - * Nonblocking FD - */ - -static int -pty_nonblock(int fd) { - int flags = fcntl(fd, F_GETFL, 0); - if (flags == -1) return -1; - return fcntl(fd, F_SETFL, flags | O_NONBLOCK); -} - -/** - * pty_waitpid - * Wait for SIGCHLD to read exit status. - */ - -static void -pty_waitpid(void *data) { - int ret; - int stat_loc; - - pty_baton *baton = static_cast(data); - - errno = 0; - - if ((ret = waitpid(baton->pid, &stat_loc, 0)) != baton->pid) { - if (ret == -1 && errno == EINTR) { - return pty_waitpid(baton); - } - if (ret == -1 && errno == ECHILD) { - // XXX node v0.8.x seems to have this problem. - // waitpid is already handled elsewhere. - ; - } else { - assert(false); - } - } - - if (WIFEXITED(stat_loc)) { - baton->exit_code = WEXITSTATUS(stat_loc); // errno? - } - - if (WIFSIGNALED(stat_loc)) { - baton->signal_code = WTERMSIG(stat_loc); - } - - uv_async_send(&baton->async); -} - -/** - * pty_after_waitpid - * Callback after exit status has been read. - */ - -static void -pty_after_waitpid(uv_async_t *async) { - Nan::HandleScope scope; - pty_baton *baton = static_cast(async->data); - - v8::Local argv[] = { - Nan::New(baton->exit_code), - Nan::New(baton->signal_code), - }; - - v8::Local cb = Nan::New(baton->cb); - baton->cb.Reset(); - memset(&baton->cb, -1, sizeof(baton->cb)); - Nan::AsyncResource resource("pty_after_waitpid"); - resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), cb, 2, argv); - - uv_close((uv_handle_t *)async, pty_after_close); -} - -/** - * pty_after_close - * uv_close() callback - free handle data - */ - -static void -pty_after_close(uv_handle_t *handle) { - uv_async_t *async = (uv_async_t *)handle; - pty_baton *baton = static_cast(async->data); - delete baton; -} - -/** - * pty_getproc - * Taken from tmux. - */ - -// Taken from: tmux (http://tmux.sourceforge.net/) -// Copyright (c) 2009 Nicholas Marriott -// Copyright (c) 2009 Joshua Elsasser -// Copyright (c) 2009 Todd Carson -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER -// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -// OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -#if defined(__linux__) - -static char * -pty_getproc(int fd, char *tty) { - FILE *f; - char *path, *buf; - size_t len; - int ch; - pid_t pgrp; - int r; - - if ((pgrp = tcgetpgrp(fd)) == -1) { - return NULL; - } - - r = asprintf(&path, "/proc/%lld/cmdline", (long long)pgrp); - if (r == -1 || path == NULL) return NULL; - - if ((f = fopen(path, "r")) == NULL) { - free(path); - return NULL; - } - - free(path); - - len = 0; - buf = NULL; - while ((ch = fgetc(f)) != EOF) { - if (ch == '\0') break; - buf = (char *)realloc(buf, len + 2); - if (buf == NULL) return NULL; - buf[len++] = ch; - } - - if (buf != NULL) { - buf[len] = '\0'; - } - - fclose(f); - return buf; -} - -#elif defined(__APPLE__) - -static char * -pty_getproc(int fd, char *tty) { - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 }; - size_t size; - struct kinfo_proc kp; - - if ((mib[3] = tcgetpgrp(fd)) == -1) { - return NULL; - } - - size = sizeof kp; - if (sysctl(mib, 4, &kp, &size, NULL, 0) == -1) { - return NULL; - } - - if (*kp.kp_proc.p_comm == '\0') { - return NULL; - } - - return strdup(kp.kp_proc.p_comm); -} - -#else - -static char * -pty_getproc(int fd, char *tty) { - return NULL; -} - -#endif - -/** - * openpty(3) / forkpty(3) - */ - -static int -pty_openpty(int *amaster, - int *aslave, - char *name, - const struct termios *termp, - const struct winsize *winp) { -#if defined(__sun) - char *slave_name; - int slave; - int master = open("/dev/ptmx", O_RDWR | O_NOCTTY); - if (master == -1) return -1; - if (amaster) *amaster = master; - - if (grantpt(master) == -1) goto err; - if (unlockpt(master) == -1) goto err; - - slave_name = ptsname(master); - if (slave_name == NULL) goto err; - if (name) strcpy(name, slave_name); - - slave = open(slave_name, O_RDWR | O_NOCTTY); - if (slave == -1) goto err; - if (aslave) *aslave = slave; - - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); - ioctl(slave, I_PUSH, "ttcompat"); - - if (termp) tcsetattr(slave, TCSAFLUSH, termp); - if (winp) ioctl(slave, TIOCSWINSZ, winp); - - return 0; - -err: - close(master); - return -1; -#else - return openpty(amaster, aslave, name, (termios *)termp, (winsize *)winp); -#endif -} - -static pid_t -pty_forkpty(int *amaster, - char *name, - const struct termios *termp, - const struct winsize *winp) { -#if defined(__sun) - int master, slave; - - int ret = pty_openpty(&master, &slave, name, termp, winp); - if (ret == -1) return -1; - if (amaster) *amaster = master; - - pid_t pid = fork(); - - switch (pid) { - case -1: - close(master); - close(slave); - return -1; - case 0: - close(master); - - setsid(); - -#if defined(TIOCSCTTY) - // glibc does this - if (ioctl(slave, TIOCSCTTY, NULL) == -1) { - _exit(1); - } -#endif - - dup2(slave, 0); - dup2(slave, 1); - dup2(slave, 2); - - if (slave > 2) close(slave); - - return 0; - default: - close(slave); - return pid; - } - - return -1; -#else - return forkpty(amaster, name, (termios *)termp, (winsize *)winp); -#endif -} - -/** - * Init - */ - -NAN_MODULE_INIT(init) { - Nan::HandleScope scope; - Nan::Export(target, "fork", PtyFork); - Nan::Export(target, "open", PtyOpen); - Nan::Export(target, "resize", PtyResize); - Nan::Export(target, "process", PtyGetProc); -} - -NODE_MODULE(pty, init)