Blame ext/posix/stdlib.c

Packit 437b5e
/*
Packit 437b5e
 * POSIX library for Lua 5.1, 5.2 & 5.3.
Packit 437b5e
 * (c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2015
Packit 437b5e
 * (c) Reuben Thomas <rrt@sc3d.org> 2010-2013
Packit 437b5e
 * (c) Natanael Copa <natanael.copa@gmail.com> 2008-2010
Packit 437b5e
 * Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11
Packit 437b5e
 * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49
Packit 437b5e
 * Based on original by Claudio Terra for Lua 3.x.
Packit 437b5e
 * With contributions by Roberto Ierusalimschy.
Packit 437b5e
 * With documentation from Steve Donovan 2012
Packit 437b5e
 */
Packit 437b5e
/***
Packit 437b5e
 Standard Posix Library functions.
Packit 437b5e
Packit 437b5e
@module posix.stdlib
Packit 437b5e
*/
Packit 437b5e
Packit 437b5e
#include <config.h>
Packit 437b5e
Packit 437b5e
#include <fcntl.h>	/* for open(2) */
Packit 437b5e
#include <stdlib.h>
Packit 437b5e
Packit 437b5e
#include "_helpers.c"
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Abort the program immediately.
Packit 437b5e
@function abort
Packit 437b5e
@see abort(3)
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pabort(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	checknargs(L, 0);
Packit 437b5e
	abort();
Packit 437b5e
	return 0; /* Avoid a compiler warning (or possibly cause one
Packit 437b5e
		     if the compiler's too clever, sigh). */
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Get value of environment variable, or _all_ variables.
Packit 437b5e
@function getenv
Packit 437b5e
@see getenv(3)
Packit 437b5e
@string[opt] name if nil, get all
Packit 437b5e
@return value if name given, otherwise a name-indexed table of values.
Packit 437b5e
@usage for a,b in pairs(posix.getenv()) do print(a, b) end
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pgetenv(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	if (lua_isnoneornil(L, 1))
Packit 437b5e
	{
Packit 437b5e
		extern char **environ;
Packit 437b5e
		char **e;
Packit 437b5e
		lua_newtable(L);
Packit 437b5e
		for (e=environ; *e!=NULL; e++)
Packit 437b5e
		{
Packit 437b5e
			char *s=*e;
Packit 437b5e
			char *eq=strchr(s, '=');
Packit 437b5e
			if (eq==NULL)		/* will this ever happen? */
Packit 437b5e
			{
Packit 437b5e
				lua_pushstring(L, s);
Packit 437b5e
				lua_pushboolean(L, 1);
Packit 437b5e
			}
Packit 437b5e
			else
Packit 437b5e
			{
Packit 437b5e
				lua_pushlstring(L, s, eq-s);
Packit 437b5e
				lua_pushstring(L, eq+1);
Packit 437b5e
			}
Packit 437b5e
			lua_settable(L, -3);
Packit 437b5e
		}
Packit 437b5e
	}
Packit 437b5e
	else
Packit 437b5e
		lua_pushstring(L, getenv(optstring(L, 1,
Packit 437b5e
			"lua_isnoneornil prevents this happening")));
Packit 437b5e
	return 1;
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Grant access to a slave pseudoterminal
Packit 437b5e
@function grantpt
Packit 437b5e
@int fd descriptor returned by openpt
Packit 437b5e
@treturn[1] int `0`, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see grantpt(3)
Packit 437b5e
@see openpt
Packit 437b5e
@see ptsname
Packit 437b5e
@see unlockpt
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pgrantpt(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	int fd=checkint(L, 1);
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	return pushresult(L, grantpt(fd), "grantpt");
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Create a unique temporary directory.
Packit 437b5e
@function mkdtemp
Packit 437b5e
@string templ pattern that ends in six 'X' characters
Packit 437b5e
@treturn[1] string path to directory, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see mkdtemp(3)
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pmkdtemp(lua_State *L)
Packit 437b5e
{
Packit 437b5e
#if defined LPOSIX_2008_COMPLIANT
Packit 437b5e
	const char *path = luaL_checkstring(L, 1);
Packit 437b5e
	size_t path_len = strlen(path) + 1;
Packit 437b5e
	void *ud;
Packit 437b5e
	lua_Alloc lalloc;
Packit 437b5e
	char *tmppath;
Packit 437b5e
	char *r;
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	lalloc = lua_getallocf(L, &ud);
Packit 437b5e
Packit 437b5e
	if ((tmppath = lalloc(ud, NULL, 0, path_len)) == NULL)
Packit 437b5e
		return pusherror(L, "lalloc");
Packit 437b5e
	strcpy(tmppath, path);
Packit 437b5e
Packit 437b5e
	if ((r = mkdtemp(tmppath)))
Packit 437b5e
		lua_pushstring(L, tmppath);
Packit 437b5e
	lalloc(ud, tmppath, path_len, 0);
Packit 437b5e
	return (r == NULL) ? pusherror(L, path) : 1;
Packit 437b5e
#else
Packit 437b5e
	return binding_notimplemented(L, "mkdtemp", "C");
Packit 437b5e
#endif
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Create a unique temporary file.
Packit 437b5e
@function mkstemp
Packit 437b5e
@string templ pattern that ends in six 'X' characters
Packit 437b5e
@treturn[1] int open file descriptor
Packit 437b5e
@treturn[2] string path to file, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see mkstemp(3)
Packit 437b5e
@usage P.mkstemp 'wooXXXXXX'
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pmkstemp(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	const char *path = luaL_checkstring(L, 1);
Packit 437b5e
	size_t path_len = strlen(path) + 1;
Packit 437b5e
	void *ud;
Packit 437b5e
	lua_Alloc lalloc;
Packit 437b5e
	char *tmppath;
Packit 437b5e
	int r;
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	lalloc = lua_getallocf(L, &ud);
Packit 437b5e
Packit 437b5e
	if ((tmppath = lalloc(ud, NULL, 0, path_len)) == NULL)
Packit 437b5e
		return pusherror(L, "lalloc");
Packit 437b5e
	strcpy(tmppath, path);
Packit 437b5e
	r = mkstemp(tmppath);
Packit 437b5e
Packit 437b5e
	if (r != -1)
Packit 437b5e
	{
Packit 437b5e
		lua_pushinteger(L, r);
Packit 437b5e
		lua_pushstring(L, tmppath);
Packit 437b5e
	}
Packit 437b5e
Packit 437b5e
	lalloc(ud, tmppath, path_len, 0);
Packit 437b5e
	return (r == -1) ? pusherror(L, path) : 2;
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Open a pseudoterminal.
Packit 437b5e
@function openpt
Packit 437b5e
@int oflags bitwise OR of zero or more of `O_RDWR` and `O_NOCTTY`
Packit 437b5e
@return[1] file descriptor of pseudoterminal, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see posix_openpt(3)
Packit 437b5e
@see grantpt
Packit 437b5e
@see ptsname
Packit 437b5e
@see unlockpt
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Popenpt(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	int flags = checkint(L, 1);
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	/* The name of the pseudo-device is specified by POSIX */
Packit 437b5e
	return pushresult(L, open("/dev/ptmx", flags), NULL);
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Get the name of a slave pseudo-terminal
Packit 437b5e
@function ptsname
Packit 437b5e
@int fd descriptor returned by @{openpt}
Packit 437b5e
@return[1] path name of the slave terminal device, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see ptsname(3)
Packit 437b5e
@see grantpt
Packit 437b5e
@see unlockpt
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pptsname(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	int fd=checkint(L, 1);
Packit 437b5e
	const char* slave;
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	slave = ptsname(fd);
Packit 437b5e
	if (!slave)
Packit 437b5e
		return pusherror(L, "getptsname");
Packit 437b5e
	return pushstringresult(slave);
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Find canonicalized absolute pathname.
Packit 437b5e
@function realpath
Packit 437b5e
@string path file to act on
Packit 437b5e
@treturn[1] string canonicalized absolute path, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error messag
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see realpath(3)
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Prealpath(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	char *s;
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	if ((s = realpath(luaL_checkstring(L, 1), NULL)) == NULL)
Packit 437b5e
		return pusherror(L, "realpath");
Packit 437b5e
	lua_pushstring(L, s);
Packit 437b5e
	free(s);
Packit 437b5e
	return 1;
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Set an environment variable for this process.
Packit 437b5e
(Child processes will inherit this)
Packit 437b5e
@function setenv
Packit 437b5e
@string name
Packit 437b5e
@string[opt] value (maybe nil, meaning 'unset')
Packit 437b5e
@param[opt] overwrite non-nil prevents overwriting a variable
Packit 437b5e
@treturn[1] int `0`, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see setenv(3)
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Psetenv(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	const char *name=luaL_checkstring(L, 1);
Packit 437b5e
	const char *value=optstring(L, 2, NULL);
Packit 437b5e
	checknargs(L, 3);
Packit 437b5e
	if (value==NULL)
Packit 437b5e
	{
Packit 437b5e
		unsetenv(name);
Packit 437b5e
		return pushresult(L, 0, NULL);
Packit 437b5e
	}
Packit 437b5e
	else
Packit 437b5e
	{
Packit 437b5e
		int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
Packit 437b5e
		return pushresult(L, setenv(name,value,overwrite), NULL);
Packit 437b5e
	}
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Unlock a pseudoterminal master/slave pair
Packit 437b5e
@function unlockpt
Packit 437b5e
@int fd descriptor returned by openpt
Packit 437b5e
@treturn[1] int `0`, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see unlockpt(3)
Packit 437b5e
@see openpt
Packit 437b5e
@see ptsname
Packit 437b5e
@see grantpt
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Punlockpt(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	int fd=checkint(L, 1);
Packit 437b5e
	checknargs(L, 1);
Packit 437b5e
	return pushresult(L, unlockpt(fd), "unlockpt");
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
static const luaL_Reg posix_stdlib_fns[] =
Packit 437b5e
{
Packit 437b5e
	LPOSIX_FUNC( Pabort		),
Packit 437b5e
	LPOSIX_FUNC( Pgetenv		),
Packit 437b5e
	LPOSIX_FUNC( Pgrantpt		),
Packit 437b5e
	LPOSIX_FUNC( Pmkdtemp		),
Packit 437b5e
	LPOSIX_FUNC( Pmkstemp		),
Packit 437b5e
	LPOSIX_FUNC( Popenpt		),
Packit 437b5e
	LPOSIX_FUNC( Pptsname		),
Packit 437b5e
	LPOSIX_FUNC( Prealpath		),
Packit 437b5e
	LPOSIX_FUNC( Psetenv		),
Packit 437b5e
	LPOSIX_FUNC( Punlockpt		),
Packit 437b5e
	{NULL, NULL}
Packit 437b5e
};
Packit 437b5e
Packit 437b5e
Packit 437b5e
LUALIB_API int
Packit 437b5e
luaopen_posix_stdlib(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	luaL_register(L, "posix.stdlib", posix_stdlib_fns);
Packit 437b5e
	lua_pushliteral(L, "posix.stdlib for " LUA_VERSION " / " PACKAGE_STRING);
Packit 437b5e
	lua_setfield(L, -2, "version");
Packit 437b5e
Packit 437b5e
	return 1;
Packit 437b5e
}