/* lpty_new * * create a new lpty object, initialize it, put it into a userdata and * return it to the user. * * Arguments: * L Lua State * * Lua Stack: * - * * Lua Returns: * +1 the lpty userdata */ static int lpty_new(lua_State *L) { /* create pty master side */ int mfd = posix_openpt(O_RDWR); int sfd = -1; int failed = (mfd < 0); int throwe = 0; /* throw errors, default = no */ int nle = 0; /* no local echo, default 0 */ /* check for options */ if (lua_gettop(L) > 0) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushstring(L, "throw_errors"); lua_rawget(L, 1); throwe = lua_toboolean(L, 2); lua_pop(L, 1); lua_pushstring(L, "no_local_echo"); lua_rawget(L, 1); nle = lua_toboolean(L, 2); lua_pop(L, 1); } if (mfd > 0) { /* setup parent side of pty. BEWARE: * behaviour of grantpt is undefined if a SIGCHLD handler is active */ void * ochldhandler = signal(SIGCHLD, SIG_DFL); failed = grantpt(mfd); signal(SIGCHLD, ochldhandler); failed = failed || unlockpt(mfd); /* open slave side of pty */ if (!failed) { char *ttyn = ptsname(mfd); if (ttyn) { sfd = open(ttyn, O_RDWR); failed = (sfd < 0); } else failed = 1; } /* cleanup if anything went wrong */ if (failed) { close(mfd); } } if (failed) return lpty_error(L, throwe, "pty initialisation failed: %s", strerror(errno)); /* suppress local echo on slave side if wanted */ if (nle) { struct termios ttys; tcgetattr( sfd, &ttys ); ttys.c_lflag &= ~( ECHO ); tcsetattr( sfd, TCSAFLUSH, &ttys ); } lPty *pty = lpty_pushLPty(L); pty->m_fd = mfd; pty->s_fd = sfd; pty->child = -1; pty->flags.nolocalecho = nle; pty->flags.throwerrors = throwe; return 1; }
/* lpty_new * * create a new lpty object, initialize it, put it into a userdata and * return it to the user. * * Arguments: * L Lua State * * Lua Stack: * - * * Lua Returns: * +1 the lpty userdata */ static int lpty_new(lua_State *L) { /* create pty master side */ int mfd = posix_openpt(O_RDWR); int sfd = -1; int failed = (mfd < 0); int throwe = 0; /* throw errors, default = no */ int usep = 1; /* use path, default = yes */ int nle = 0; /* no local echo, default = no */ int rawm = 0; /* raw mode, default = no */ int sepse = 0; /* separate stderr, default = no */ /* check for options */ if (lua_gettop(L) > 0) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushnil(L); while (lua_next(L, 1) != 0) { const char* k = lua_tostring(L, -2); if (!strcmp(k, "throw_errors")) throwe = lua_toboolean(L, -1); else if (!strcmp(k, "no_local_echo")) nle = lua_toboolean(L, -1); else if (!strcmp(k, "raw_mode")) rawm = lua_toboolean(L, -1); else if (!strcmp(k, "use_path")) usep = lua_toboolean(L, -1); else if (!strcmp(k, "separate_stderr")) { sepse = lua_toboolean(L, -1); } else return _lpty_error(L, 1, "invalid configuration option: %s", k); lua_pop(L, 1); } } if (mfd > 0) { /* setup parent side of pty. BEWARE: * behaviour of grantpt is undefined if a SIGCHLD handler is active */ _lpty_set_sigchld_handler(SIG_DFL); failed = grantpt(mfd); _lpty_set_sigchld_handler(_lpty_sigchld_handler); failed = failed || unlockpt(mfd); /* open slave side of pty */ if (!failed) { char *ttyn = ptsname(mfd); if (ttyn) { sfd = open(ttyn, O_RDWR); failed = (sfd < 0); } else failed = 1; } /* cleanup if anything went wrong */ if (failed) { close(mfd); mfd = -1; } } if (failed) return _lpty_error(L, throwe, "pty initialisation failed: %s", strerror(errno)); lPty *pty = lpty_pushLPty(L); pty->m_fd = mfd; pty->s_fd = sfd; pty->child = -1; pty->flags.throwerrors = throwe; pty->flags.nolocalecho = nle; pty->flags.rawmode = rawm; pty->flags.usepath = usep; pty->e_mfd = -1; pty->e_sfd = -1; /* get original tty flags */ tcgetattr(sfd, &pty->otios); if (!_lpty_separate_stderr(pty, sepse)) return _lpty_error(L, throwe, "pty initialisation failed: %s", strerror(errno)); return 1; }