Пример #1
0
/* 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;
}
Пример #2
0
/* 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;
}