1459 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			1459 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Index: lua-5.1.4/src/Makefile
 | |
| ===================================================================
 | |
| --- lua-5.1.4.orig/src/Makefile	2008-09-25 12:19:44.000000000 +0200
 | |
| +++ lua-5.1.4/src/Makefile	2008-09-25 12:20:03.000000000 +0200
 | |
| @@ -12,7 +12,7 @@
 | |
|  AR= ar rcu
 | |
|  RANLIB= ranlib
 | |
|  RM= rm -f
 | |
| -LIBS= -lm -lz $(MYLIBS)
 | |
| +LIBS= -lm -lz -lcrypt $(MYLIBS)
 | |
|  
 | |
|  MYCFLAGS=
 | |
|  MYLDFLAGS=
 | |
| @@ -29,7 +29,7 @@
 | |
|  	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
 | |
|  	lundump.o lvm.o lzio.o lnum.o
 | |
|  LIB_O=	lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
 | |
| -	lstrlib.o loadlib.o linit.o
 | |
| +	lstrlib.o loadlib.o linit.o lposix.o
 | |
|  
 | |
|  LUA_T=	lua
 | |
|  LUA_O=	lua.o
 | |
| Index: lua-5.1.4/src/linit.c
 | |
| ===================================================================
 | |
| --- lua-5.1.4.orig/src/linit.c	2008-09-25 12:19:02.000000000 +0200
 | |
| +++ lua-5.1.4/src/linit.c	2008-09-25 12:19:32.000000000 +0200
 | |
| @@ -23,6 +23,7 @@
 | |
|    {LUA_STRLIBNAME, luaopen_string},
 | |
|    {LUA_MATHLIBNAME, luaopen_math},
 | |
|    {LUA_DBLIBNAME, luaopen_debug},
 | |
| +  {LUA_POSIXLIBNAME, luaopen_posix},
 | |
|    {NULL, NULL}
 | |
|  };
 | |
|  
 | |
| Index: lua-5.1.4/src/lposix.c
 | |
| ===================================================================
 | |
| --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 | |
| +++ lua-5.1.4/src/lposix.c	2008-09-25 12:16:29.000000000 +0200
 | |
| @@ -0,0 +1,1139 @@
 | |
| +/*
 | |
| +* lposix.c
 | |
| +* POSIX library for Lua 5.1.
 | |
| +* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
 | |
| +* 07 Apr 2006 23:17:49
 | |
| +* Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11 <!LR> 
 | |
| +* Based on original by Claudio Terra for Lua 3.x.
 | |
| +* With contributions by Roberto Ierusalimschy.
 | |
| +*/
 | |
| +
 | |
| +#include <sys/stat.h>
 | |
| +#include <sys/times.h>
 | |
| +#include <sys/types.h>
 | |
| +#include <sys/utsname.h>
 | |
| +#include <sys/wait.h>
 | |
| +
 | |
| +#include <dirent.h>
 | |
| +#include <errno.h>
 | |
| +#include <fcntl.h>
 | |
| +#include <glob.h>
 | |
| +#include <grp.h>
 | |
| +#include <libgen.h>
 | |
| +#include <limits.h>
 | |
| +#include <poll.h>
 | |
| +#include <pwd.h>
 | |
| +#include <signal.h>
 | |
| +#include <stdio.h>
 | |
| +#include <stdlib.h>
 | |
| +#include <string.h>
 | |
| +#include <syslog.h>
 | |
| +#include <time.h>
 | |
| +#include <unistd.h>
 | |
| +#include <utime.h>
 | |
| +
 | |
| +#define MYNAME		"posix"
 | |
| +#define MYVERSION	MYNAME " library for " LUA_VERSION " / Jan 2008"
 | |
| +
 | |
| +#ifndef ENABLE_SYSLOG
 | |
| +#define ENABLE_SYSLOG 	1
 | |
| +#endif
 | |
| +
 | |
| +#include "lua.h"
 | |
| +#include "lualib.h"
 | |
| +#include "lauxlib.h"
 | |
| +
 | |
| +#include "modemuncher.c"
 | |
| +
 | |
| +/* compatibility with Lua 5.0 */
 | |
| +#ifndef LUA_VERSION_NUM
 | |
| +static int luaL_checkoption (lua_State *L, int narg, const char *def,
 | |
| +                                 const char *const lst[]) {
 | |
| +  const char *name = (def) ? luaL_optstring(L, narg, def) :
 | |
| +                             luaL_checkstring(L, narg);
 | |
| +  int i = luaL_findstring(name, lst);
 | |
| +  if (i == -1)
 | |
| +	luaL_argerror(L, narg, lua_pushfstring(L, "invalid option '%s'", name));
 | |
| +  return i;
 | |
| +}
 | |
| +#define lua_pushinteger			lua_pushnumber
 | |
| +#define lua_createtable(L,a,r)		lua_newtable(L)
 | |
| +#define LUA_FILEHANDLE			"FILE*"
 | |
| +
 | |
| +#define lua_setfield(l,i,k)
 | |
| +#define lua_getfield(l,i,k)
 | |
| +
 | |
| +#endif
 | |
| +
 | |
| +static const struct { char c; mode_t b; } M[] =
 | |
| +{
 | |
| +	{'r', S_IRUSR}, {'w', S_IWUSR}, {'x', S_IXUSR},
 | |
| +	{'r', S_IRGRP}, {'w', S_IWGRP}, {'x', S_IXGRP},
 | |
| +	{'r', S_IROTH}, {'w', S_IWOTH}, {'x', S_IXOTH},
 | |
| +};
 | |
| +
 | |
| +
 | |
| +static void pushmode(lua_State *L, mode_t mode)
 | |
| +{
 | |
| +	char m[9];
 | |
| +	int i;
 | |
| +	for (i=0; i<9; i++) m[i]= (mode & M[i].b) ? M[i].c : '-';
 | |
| +	if (mode & S_ISUID) m[2]= (mode & S_IXUSR) ? 's' : 'S';
 | |
| +	if (mode & S_ISGID) m[5]= (mode & S_IXGRP) ? 's' : 'S';
 | |
| +	lua_pushlstring(L, m, 9);
 | |
| +}
 | |
| +
 | |
| +typedef void (*Selector)(lua_State *L, int i, const void *data);
 | |
| +
 | |
| +static int doselection(lua_State *L, int i, int n, 
 | |
| +                       const char *const S[], 
 | |
| +                       Selector F, 
 | |
| +                       const void *data)
 | |
| +{
 | |
| +	if (lua_isnone(L, i) || lua_istable(L, i))
 | |
| +	{
 | |
| +		int j;
 | |
| +		if (lua_isnone(L, i)) lua_createtable(L,0,n); else lua_settop(L, i);
 | |
| +		for (j=0; S[j]!=NULL; j++)
 | |
| +		{
 | |
| +			lua_pushstring(L, S[j]);
 | |
| +			F(L, j, data);
 | |
| +			lua_settable(L, -3);
 | |
| +		}
 | |
| +		return 1;
 | |
| +	}
 | |
| +	else
 | |
| +	{
 | |
| +		int k,n=lua_gettop(L);
 | |
| +		for (k=i; k<=n; k++)
 | |
| +		{
 | |
| +			int j=luaL_checkoption(L, k, NULL, S);
 | |
| +			F(L, j, data);
 | |
| +			lua_replace(L, k);
 | |
| +		}
 | |
| +		return n-i+1;
 | |
| +	}
 | |
| +}
 | |
| +#define doselection(L,i,S,F,d) (doselection)(L,i,sizeof(S)/sizeof(*S)-1,S,F,d)
 | |
| +
 | |
| +static int pusherror(lua_State *L, const char *info)
 | |
| +{
 | |
| +	lua_pushnil(L);
 | |
| +	if (info==NULL)
 | |
| +		lua_pushstring(L, strerror(errno));
 | |
| +	else
 | |
| +		lua_pushfstring(L, "%s: %s", info, strerror(errno));
 | |
| +	lua_pushinteger(L, errno);
 | |
| +	return 3;
 | |
| +}
 | |
| +
 | |
| +static int pushresult(lua_State *L, int i, const char *info)
 | |
| +{
 | |
| +	if (i==-1) return pusherror(L, info);
 | |
| +	lua_pushinteger(L, i);
 | |
| +		return 1;
 | |
| +}
 | |
| +
 | |
| +static void badoption(lua_State *L, int i, const char *what, int option)
 | |
| +{
 | |
| +	luaL_argerror(L, 2,
 | |
| +		lua_pushfstring(L, "unknown %s option '%c'", what, option));
 | |
| +}
 | |
| +
 | |
| +static uid_t mygetuid(lua_State *L, int i)
 | |
| +{
 | |
| +	if (lua_isnone(L, i))
 | |
| +		return -1;
 | |
| +	else if (lua_isnumber(L, i))
 | |
| +		return (uid_t) lua_tonumber(L, i);
 | |
| +	else if (lua_isstring(L, i))
 | |
| +	{
 | |
| +		struct passwd *p=getpwnam(lua_tostring(L, i));
 | |
| +		return (p==NULL) ? -1 : p->pw_uid;
 | |
| +	}
 | |
| +	else
 | |
| +		return luaL_typerror(L, i, "string or number");
 | |
| +}
 | |
| +
 | |
| +static gid_t mygetgid(lua_State *L, int i)
 | |
| +{
 | |
| +	if (lua_isnone(L, i))
 | |
| +		return -1;
 | |
| +	else if (lua_isnumber(L, i))
 | |
| +		return (gid_t) lua_tonumber(L, i);
 | |
| +	else if (lua_isstring(L, i))
 | |
| +	{
 | |
| +		struct group *g=getgrnam(lua_tostring(L, i));
 | |
| +		return (g==NULL) ? -1 : g->gr_gid;
 | |
| +	}
 | |
| +	else
 | |
| +		return luaL_typerror(L, i, "string or number");
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Perrno(lua_State *L)			/** errno([n]) */
 | |
| +{
 | |
| +	int n = luaL_optint(L, 1, errno);
 | |
| +	lua_pushstring(L, strerror(n));
 | |
| +	lua_pushinteger(L, n);
 | |
| +	return 2;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pbasename(lua_State *L)		/** basename(path) */
 | |
| +{
 | |
| +	char b[PATH_MAX];
 | |
| +	size_t len;
 | |
| +	const char *path = luaL_checklstring(L, 1, &len);
 | |
| +	if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
 | |
| +	lua_pushstring(L, basename(strcpy(b,path)));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pdirname(lua_State *L)		/** dirname(path) */
 | |
| +{
 | |
| +	char b[PATH_MAX];
 | |
| +	size_t len;
 | |
| +	const char *path = luaL_checklstring(L, 1, &len);
 | |
| +	if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
 | |
| +	lua_pushstring(L, dirname(strcpy(b,path)));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pdir(lua_State *L)			/** dir([path]) */
 | |
| +{
 | |
| +	const char *path = luaL_optstring(L, 1, ".");
 | |
| +	DIR *d = opendir(path);
 | |
| +	if (d == NULL)
 | |
| +		return pusherror(L, path);
 | |
| +	else
 | |
| +	{
 | |
| +		int i;
 | |
| +		struct dirent *entry;
 | |
| +		lua_newtable(L);
 | |
| +		for (i=1; (entry = readdir(d)) != NULL; i++)
 | |
| +		{
 | |
| +			lua_pushstring(L, entry->d_name);
 | |
| +			lua_rawseti(L, -2, i);
 | |
| +		}
 | |
| +		closedir(d);
 | |
| +		lua_pushinteger(L, i-1);
 | |
| +		return 2;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static int Pglob(lua_State *L)                  /** glob(pattern) */
 | |
| +{
 | |
| + const char *pattern = luaL_optstring(L, 1, "*");
 | |
| + glob_t globres;
 | |
| +
 | |
| + if (glob(pattern, 0, NULL, &globres))
 | |
| +   return pusherror(L, pattern);
 | |
| + else
 | |
| +   {
 | |
| +     int i;
 | |
| +     lua_newtable(L);
 | |
| +     for (i=1; i<=globres.gl_pathc; i++) {
 | |
| +       lua_pushstring(L, globres.gl_pathv[i-1]);
 | |
| +       lua_rawseti(L, -2, i);
 | |
| +     }
 | |
| +     globfree(&globres);
 | |
| +     return 1;
 | |
| +   }
 | |
| +}
 | |
| +
 | |
| +static int aux_files(lua_State *L)
 | |
| +{
 | |
| +	DIR **p = (DIR **)lua_touserdata(L, lua_upvalueindex(1));
 | |
| +	DIR *d = *p;
 | |
| +	struct dirent *entry;
 | |
| +	if (d == NULL) return 0;
 | |
| +	entry = readdir(d);
 | |
| +	if (entry == NULL)
 | |
| +	{
 | |
| +		closedir(d);
 | |
| +		*p=NULL;
 | |
| +		return 0;
 | |
| +	}
 | |
| +	else
 | |
| +	{
 | |
| +		lua_pushstring(L, entry->d_name);
 | |
| +	return 1;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static int dir_gc (lua_State *L)
 | |
| +{
 | |
| +	DIR *d = *(DIR **)lua_touserdata(L, 1);
 | |
| +	if (d!=NULL) closedir(d);
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static int Pfiles(lua_State *L)			/** files([path]) */
 | |
| +{
 | |
| +	const char *path = luaL_optstring(L, 1, ".");
 | |
| +	DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *));
 | |
| +	if (luaL_newmetatable(L, MYNAME " dir handle"))
 | |
| +	{
 | |
| +		lua_pushliteral(L, "__gc");
 | |
| +		lua_pushcfunction(L, dir_gc);
 | |
| +		lua_settable(L, -3);
 | |
| +	}
 | |
| +	lua_setmetatable(L, -2);
 | |
| +	*d = opendir(path);
 | |
| +	if (*d == NULL) return pusherror(L, path);
 | |
| +		lua_pushcclosure(L, aux_files, 1);
 | |
| +		return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pgetcwd(lua_State *L)		/** getcwd() */
 | |
| +{
 | |
| +	char b[PATH_MAX];
 | |
| +	if (getcwd(b, sizeof(b)) == NULL) return pusherror(L, ".");
 | |
| +	lua_pushstring(L, b);
 | |
| +		return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pmkdir(lua_State *L)			/** mkdir(path) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	return pushresult(L, mkdir(path, 0777), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pchdir(lua_State *L)			/** chdir(path) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	return pushresult(L, chdir(path), path);
 | |
| +}
 | |
| +
 | |
| +static int Prmdir(lua_State *L)			/** rmdir(path) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	return pushresult(L, rmdir(path), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Punlink(lua_State *L)		/** unlink(path) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	return pushresult(L, unlink(path), path);
 | |
| +}
 | |
| +
 | |
| +static int Plink(lua_State *L)			/** link(old,new,[symbolic]) */
 | |
| +{
 | |
| +	const char *oldpath = luaL_checkstring(L, 1);
 | |
| +	const char *newpath = luaL_checkstring(L, 2);
 | |
| +	return pushresult(L,
 | |
| +		(lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Preadlink(lua_State *L)		/** readlink(path) */
 | |
| +{
 | |
| +	char b[PATH_MAX];
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	int n = readlink(path, b, sizeof(b));
 | |
| +	if (n==-1) return pusherror(L, path);
 | |
| +	lua_pushlstring(L, b, n);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Paccess(lua_State *L)		/** access(path,[mode]) */
 | |
| +{
 | |
| +	int mode=F_OK;
 | |
| +	const char *path=luaL_checkstring(L, 1);
 | |
| +	const char *s;
 | |
| +	for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
 | |
| +		switch (*s)
 | |
| +		{
 | |
| +			case ' ': break;
 | |
| +			case 'r': mode |= R_OK; break;
 | |
| +			case 'w': mode |= W_OK; break;
 | |
| +			case 'x': mode |= X_OK; break;
 | |
| +			case 'f': mode |= F_OK; break;
 | |
| +			default: badoption(L, 2, "mode", *s); break;
 | |
| +		}
 | |
| +	return pushresult(L, access(path, mode), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int myfclose (lua_State *L) {
 | |
| +  FILE **p = (FILE **)lua_touserdata(L, 1);
 | |
| +  int rc = fclose(*p);
 | |
| +  if (rc == 0) *p = NULL;
 | |
| +  return pushresult(L, rc, NULL);
 | |
| +} 
 | |
| +
 | |
| +static int pushfile (lua_State *L, int id, const char *mode) {
 | |
| +  FILE **f = (FILE **)lua_newuserdata(L, sizeof(FILE *));
 | |
| +  *f = NULL;
 | |
| +  luaL_getmetatable(L, LUA_FILEHANDLE);
 | |
| +  lua_setmetatable(L, -2);
 | |
| +  lua_getfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
 | |
| +  if (lua_isnil(L, -1)) {
 | |
| +    lua_pop(L, 1);
 | |
| +    lua_newtable(L);
 | |
| +    lua_pushvalue(L, -1);
 | |
| +    lua_pushcfunction(L, myfclose);
 | |
| +    lua_setfield(L, -2, "__close");
 | |
| +    lua_setfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
 | |
| +  }
 | |
| +  lua_setfenv(L, -2);
 | |
| +  *f = fdopen(id, mode);
 | |
| +  return (*f != NULL);
 | |
| +}
 | |
| +
 | |
| +static int Ppipe(lua_State *L)			/** pipe() */
 | |
| +{
 | |
| +	int fd[2];
 | |
| +	if (pipe(fd)==-1) return pusherror(L, NULL);
 | |
| +	if (!pushfile(L, fd[0], "r") || !pushfile(L, fd[1], "w"))
 | |
| +		return pusherror(L, "pipe");
 | |
| +	return 2;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pfileno(lua_State *L)	/** fileno(filehandle) */
 | |
| +{
 | |
| +	FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
 | |
| +	return pushresult(L, fileno(f), NULL);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pfdopen(lua_State *L)	/** fdopen(fd, mode) */
 | |
| +{
 | |
| +	int fd = luaL_checkint(L, 1);
 | |
| +	const char *mode = luaL_checkstring(L, 2);
 | |
| +	if (!pushfile(L, fd, mode))
 | |
| +		return pusherror(L, "fdpoen");
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +/* helper func for Pdup */
 | |
| +static const char *filemode(int fd)
 | |
| +{
 | |
| +	const char *m;
 | |
| +	int mode = fcntl(fd, F_GETFL);
 | |
| +	if (mode < 0)
 | |
| +		return NULL;
 | |
| +	switch (mode & O_ACCMODE) {
 | |
| +		case O_RDONLY:  m = "r"; break;
 | |
| +		case O_WRONLY:  m = "w"; break;
 | |
| +		default:    	m = "rw"; break;
 | |
| +	}
 | |
| +	return m;
 | |
| +}
 | |
| +
 | |
| +static int Pdup(lua_State *L)			/** dup(old,[new]) */
 | |
| +{
 | |
| +	FILE **oldf = (FILE**)luaL_checkudata(L, 1, LUA_FILEHANDLE);
 | |
| +  	FILE **newf = (FILE **)lua_touserdata(L, 2);
 | |
| +	int fd;
 | |
| +	const char *msg = "dup2";
 | |
| +	fflush(*newf);
 | |
| +	if (newf == NULL) {
 | |
| +		fd = dup(fileno(*oldf));
 | |
| +		msg = "dup";
 | |
| +	} else {
 | |
| +		fflush(*newf);
 | |
| +		fd = dup2(fileno(*oldf), fileno(*newf));
 | |
| +	}
 | |
| +
 | |
| +	if ((fd < 0) || !pushfile(L, fd, filemode(fd)))
 | |
| +		return pusherror(L, msg);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pmkfifo(lua_State *L)		/** mkfifo(path) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	return pushresult(L, mkfifo(path, 0777), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int runexec(lua_State *L, int use_shell)
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	int i,n=lua_gettop(L);
 | |
| +	char **argv = lua_newuserdata(L,(n+1)*sizeof(char*));
 | |
| +	argv[0] = (char*)path;
 | |
| +	for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
 | |
| +	argv[n] = NULL;
 | |
| +	if (use_shell) {
 | |
| +		execvp(path, argv);
 | |
| +	} else {
 | |
| +		execv(path, argv);
 | |
| +	}
 | |
| +	return pusherror(L, path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pexec(lua_State *L)			/** exec(path,[args]) */
 | |
| +{
 | |
| +	return runexec(L, 0);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pexecp(lua_State *L)			/** execp(path,[args]) */
 | |
| +{
 | |
| +	return runexec(L, 1);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pfork(lua_State *L)			/** fork() */
 | |
| +{
 | |
| +	return pushresult(L, fork(), NULL);
 | |
| +}
 | |
| +
 | |
| +/* from http://lua-users.org/lists/lua-l/2007-11/msg00346.html */
 | |
| +static int Ppoll(lua_State *L)   /** poll(filehandle, timeout) */
 | |
| +{
 | |
| +	struct pollfd fds;
 | |
| +	FILE* file = *(FILE**)luaL_checkudata(L,1,LUA_FILEHANDLE);
 | |
| +	int timeout = luaL_checkint(L,2);
 | |
| +	fds.fd = fileno(file);
 | |
| +	fds.events = POLLIN;
 | |
| +	return pushresult(L, poll(&fds,1,timeout), NULL);
 | |
| +}
 | |
| +
 | |
| +static int Pwait(lua_State *L)			/** wait([pid]) */
 | |
| +{
 | |
| +	int status;
 | |
| +	pid_t pid = luaL_optint(L, 1, -1);
 | |
| +	pid = waitpid(pid, &status, 0);
 | |
| +	if (pid == -1) return pusherror(L, NULL);
 | |
| +	lua_pushinteger(L, pid);
 | |
| +	if (WIFEXITED(status))
 | |
| +	{
 | |
| +		lua_pushliteral(L,"exited");
 | |
| +		lua_pushinteger(L, WEXITSTATUS(status));
 | |
| +		return 3;
 | |
| +	}
 | |
| +	else if (WIFSIGNALED(status))
 | |
| +	{
 | |
| +		lua_pushliteral(L,"killed");
 | |
| +		lua_pushinteger(L, WTERMSIG(status));
 | |
| +		return 3;
 | |
| +	}
 | |
| +	else if (WIFSTOPPED(status))
 | |
| +	{
 | |
| +		lua_pushliteral(L,"stopped");
 | |
| +		lua_pushinteger(L, WSTOPSIG(status));
 | |
| +		return 3;
 | |
| +	}
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pkill(lua_State *L)			/** kill(pid,[sig]) */
 | |
| +{
 | |
| +	pid_t pid = luaL_checkint(L, 1);
 | |
| +	int sig = luaL_optint(L, 2, SIGTERM);
 | |
| +	return pushresult(L, kill(pid, sig), NULL);
 | |
| +}
 | |
| +
 | |
| +static int Psetpid(lua_State *L)		/** setpid(option,...) */
 | |
| +{
 | |
| +	const char *what=luaL_checkstring(L, 1);
 | |
| +	switch (*what)
 | |
| +	{
 | |
| +		case 'U':
 | |
| +			return pushresult(L, seteuid(mygetuid(L, 2)), NULL);
 | |
| +		case 'u':
 | |
| +			return pushresult(L, setuid(mygetuid(L, 2)), NULL);
 | |
| +		case 'G':
 | |
| +			return pushresult(L, setegid(mygetgid(L, 2)), NULL);
 | |
| +		case 'g':
 | |
| +			return pushresult(L, setgid(mygetgid(L, 2)), NULL);
 | |
| +		case 's':
 | |
| +			return pushresult(L, setsid(), NULL);
 | |
| +		case 'p':
 | |
| +		{
 | |
| +			pid_t pid  = luaL_checkint(L, 2);
 | |
| +			pid_t pgid = luaL_checkint(L, 3);
 | |
| +			return pushresult(L, setpgid(pid,pgid), NULL);
 | |
| +		}
 | |
| +		default:
 | |
| +			badoption(L, 2, "id", *what);
 | |
| +			return 0;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Psleep(lua_State *L)			/** sleep(seconds) */
 | |
| +{
 | |
| +	unsigned int seconds = luaL_checkint(L, 1);
 | |
| +	lua_pushinteger(L, sleep(seconds));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Psetenv(lua_State *L)		/** setenv(name,value,[over]) */
 | |
| +{
 | |
| +	const char *name=luaL_checkstring(L, 1);
 | |
| +	const char *value=luaL_optstring(L, 2, NULL);
 | |
| +	if (value==NULL)
 | |
| +	{
 | |
| +	unsetenv(name);
 | |
| +		return pushresult(L, 0, NULL);
 | |
| +	}
 | |
| +	else
 | |
| +	{
 | |
| +		int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
 | |
| +		return pushresult(L, setenv(name,value,overwrite), NULL);
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pgetenv(lua_State *L)		/** getenv([name]) */
 | |
| +{
 | |
| +	if (lua_isnone(L, 1))
 | |
| +	{
 | |
| +		extern char **environ;
 | |
| +		char **e;
 | |
| +		lua_newtable(L);
 | |
| +		for (e=environ; *e!=NULL; e++)
 | |
| +		{
 | |
| +			char *s=*e;
 | |
| +			char *eq=strchr(s, '=');
 | |
| +			if (eq==NULL)		/* will this ever happen? */
 | |
| +			{
 | |
| +				lua_pushstring(L,s);
 | |
| +				lua_pushboolean(L,1);
 | |
| +			}
 | |
| +			else
 | |
| +			{
 | |
| +				lua_pushlstring(L,s,eq-s);
 | |
| +				lua_pushstring(L,eq+1);
 | |
| +			}
 | |
| +			lua_settable(L,-3);
 | |
| +		}
 | |
| +	}
 | |
| +	else
 | |
| +		lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +static int Pumask(lua_State *L)			/** umask([mode]) */
 | |
| +{/* <!LR> from old lposix-5.0 version */
 | |
| +	char m[10];
 | |
| +	mode_t mode;
 | |
| +	umask(mode=umask(0));
 | |
| +	mode=(~mode)&0777;
 | |
| +	if (!lua_isnone(L, 1))
 | |
| +	{
 | |
| +		if (mode_munch(&mode, luaL_checkstring(L, 1)))
 | |
| +		{
 | |
| +			lua_pushnil(L);
 | |
| +			return 1;
 | |
| +		}
 | |
| +		mode&=0777;
 | |
| +		umask(~mode);
 | |
| +	}
 | |
| +	modechopper(mode, m);
 | |
| +	lua_pushstring(L, m);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pchmod(lua_State *L)			/** chmod(path,mode) */
 | |
| +{
 | |
| +	mode_t mode;
 | |
| +	struct stat s;
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	const char *modestr = luaL_checkstring(L, 2);
 | |
| +	if (stat(path, &s)) return pusherror(L, path);
 | |
| +	mode = s.st_mode;
 | |
| +	if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
 | |
| +	return pushresult(L, chmod(path, mode), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pchown(lua_State *L)			/** chown(path,uid,gid) */
 | |
| +{
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	uid_t uid = mygetuid(L, 2);
 | |
| +	gid_t gid = mygetgid(L, 3);
 | |
| +	return pushresult(L, chown(path, uid, gid), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Putime(lua_State *L)			/** utime(path,[mtime,atime]) */
 | |
| +{
 | |
| +	struct utimbuf times;
 | |
| +	time_t currtime = time(NULL);
 | |
| +	const char *path = luaL_checkstring(L, 1);
 | |
| +	times.modtime = luaL_optnumber(L, 2, currtime);
 | |
| +	times.actime  = luaL_optnumber(L, 3, currtime);
 | |
| +	return pushresult(L, utime(path, ×), path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static void FgetID(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +	switch (i)
 | |
| +	{
 | |
| +		case 0:	lua_pushinteger(L, getegid());	break;
 | |
| +		case 1:	lua_pushinteger(L, geteuid());	break;
 | |
| +		case 2:	lua_pushinteger(L, getgid());	break;
 | |
| +		case 3:	lua_pushinteger(L, getuid());	break;
 | |
| +		case 4:	lua_pushinteger(L, getpgrp());	break;
 | |
| +		case 5:	lua_pushinteger(L, getpid());	break;
 | |
| +		case 6:	lua_pushinteger(L, getppid());	break;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static const char *const SgetID[] =
 | |
| +{
 | |
| +	"egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
 | |
| +};
 | |
| +
 | |
| +static int Pgetpid(lua_State *L)		/** getpid([options]) */
 | |
| +{
 | |
| +	return doselection(L, 1, SgetID, FgetID, NULL);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Phostid(lua_State *L)		/** hostid() */
 | |
| +{
 | |
| +	char b[32];
 | |
| +	sprintf(b,"%ld",gethostid());
 | |
| +	lua_pushstring(L, b);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pttyname(lua_State *L)		/** ttyname([fd]) */
 | |
| +{
 | |
| +	int fd=luaL_optint(L, 1, 0);
 | |
| +	lua_pushstring(L, ttyname(fd));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pctermid(lua_State *L)		/** ctermid() */
 | |
| +{
 | |
| +	char b[L_ctermid];
 | |
| +	lua_pushstring(L, ctermid(b));
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pgetlogin(lua_State *L)		/** getlogin() */
 | |
| +{
 | |
| +	lua_pushstring(L, getlogin());
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static void Fgetpasswd(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +	const struct passwd *p=data;
 | |
| +	switch (i)
 | |
| +	{
 | |
| +		case 0: lua_pushstring(L, p->pw_name); break;
 | |
| +		case 1: lua_pushinteger(L, p->pw_uid); break;
 | |
| +		case 2: lua_pushinteger(L, p->pw_gid); break;
 | |
| +		case 3: lua_pushstring(L, p->pw_dir); break;
 | |
| +		case 4: lua_pushstring(L, p->pw_shell); break;
 | |
| +/* not strictly POSIX */
 | |
| +		case 5: lua_pushstring(L, p->pw_gecos); break;
 | |
| +		case 6: lua_pushstring(L, p->pw_passwd); break;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static const char *const Sgetpasswd[] =
 | |
| +{
 | |
| +	"name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
 | |
| +};
 | |
| +
 | |
| +
 | |
| +static int Pgetpasswd(lua_State *L)		/** getpasswd(name|id,[sel]) */
 | |
| +{
 | |
| +	struct passwd *p=NULL;
 | |
| +	if (lua_isnoneornil(L, 1))
 | |
| +		p = getpwuid(geteuid());
 | |
| +	else if (lua_isnumber(L, 1))
 | |
| +		p = getpwuid((uid_t)lua_tonumber(L, 1));
 | |
| +	else if (lua_isstring(L, 1))
 | |
| +		p = getpwnam(lua_tostring(L, 1));
 | |
| +	else
 | |
| +		luaL_typerror(L, 1, "string or number");
 | |
| +	if (p==NULL)
 | |
| +		lua_pushnil(L);
 | |
| +	else
 | |
| +		return doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pgetgroup(lua_State *L)		/** getgroup(name|id) */
 | |
| +{
 | |
| +	struct group *g=NULL;
 | |
| +	if (lua_isnumber(L, 1))
 | |
| +		g = getgrgid((gid_t)lua_tonumber(L, 1));
 | |
| +	else if (lua_isstring(L, 1))
 | |
| +		g = getgrnam(lua_tostring(L, 1));
 | |
| +	else
 | |
| +		luaL_typerror(L, 1, "string or number");
 | |
| +	if (g==NULL)
 | |
| +		lua_pushnil(L);
 | |
| +	else
 | |
| +	{
 | |
| +		int i;
 | |
| +		lua_newtable(L);
 | |
| +		lua_pushliteral(L, "name");
 | |
| +		lua_pushstring(L, g->gr_name);
 | |
| +		lua_settable(L, -3);
 | |
| +		lua_pushliteral(L, "gid");
 | |
| +		lua_pushinteger(L, g->gr_gid);
 | |
| +		lua_settable(L, -3);
 | |
| +		for (i=0; g->gr_mem[i]!=NULL; i++)
 | |
| +		{
 | |
| +			lua_pushstring(L, g->gr_mem[i]);
 | |
| +			lua_rawseti(L, -2, i);
 | |
| +		}
 | |
| +	}
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +struct mytimes
 | |
| +{
 | |
| + struct tms t;
 | |
| + clock_t elapsed;
 | |
| +};
 | |
| +
 | |
| +/* #define pushtime(L,x)	lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC) */
 | |
| +#define pushtime(L,x)	lua_pushnumber(L, ((lua_Number)x)/clk_tck)
 | |
| +
 | |
| +static void Ftimes(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +    static long clk_tck = 0; 
 | |
| +	const struct mytimes *t=data;
 | |
| +
 | |
| +    if( !clk_tck){ clk_tck= sysconf(_SC_CLK_TCK);}
 | |
| +	switch (i)
 | |
| +	{
 | |
| +		case 0: pushtime(L, t->t.tms_utime); break;
 | |
| +		case 1: pushtime(L, t->t.tms_stime); break;
 | |
| +		case 2: pushtime(L, t->t.tms_cutime); break;
 | |
| +		case 3: pushtime(L, t->t.tms_cstime); break;
 | |
| +		case 4: pushtime(L, t->elapsed); break;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static const char *const Stimes[] =
 | |
| +{
 | |
| +	"utime", "stime", "cutime", "cstime", "elapsed", NULL
 | |
| +};
 | |
| +
 | |
| +static int Ptimes(lua_State *L)			/** times([options]) */
 | |
| +{
 | |
| +	struct mytimes t;
 | |
| +	t.elapsed = times(&t.t);
 | |
| +	return doselection(L, 1, Stimes, Ftimes, &t);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static const char *filetype(mode_t m)
 | |
| +{
 | |
| +	if (S_ISREG(m))		return "regular";
 | |
| +	else if (S_ISLNK(m))	return "link";
 | |
| +	else if (S_ISDIR(m))	return "directory";
 | |
| +	else if (S_ISCHR(m))	return "character device";
 | |
| +	else if (S_ISBLK(m))	return "block device";
 | |
| +	else if (S_ISFIFO(m))	return "fifo";
 | |
| +	else if (S_ISSOCK(m))	return "socket";
 | |
| +	else			return "?";
 | |
| +}
 | |
| +
 | |
| +static void Fstat(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +	const struct stat *s=data;
 | |
| +	switch (i)
 | |
| +	{
 | |
| +		case 0: pushmode(L, s->st_mode); break;
 | |
| +		case 1: lua_pushinteger(L, s->st_ino); break;
 | |
| +		case 2: lua_pushinteger(L, s->st_dev); break;
 | |
| +		case 3: lua_pushinteger(L, s->st_nlink); break;
 | |
| +		case 4: lua_pushinteger(L, s->st_uid); break;
 | |
| +		case 5: lua_pushinteger(L, s->st_gid); break;
 | |
| +		case 6: lua_pushinteger(L, s->st_size); break;
 | |
| +		case 7: lua_pushinteger(L, s->st_atime); break;
 | |
| +		case 8: lua_pushinteger(L, s->st_mtime); break;
 | |
| +		case 9: lua_pushinteger(L, s->st_ctime); break;
 | |
| +		case 10:lua_pushstring(L, filetype(s->st_mode)); break;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static const char *const Sstat[] =
 | |
| +{
 | |
| +	"mode", "ino", "dev", "nlink", "uid", "gid",
 | |
| +	"size", "atime", "mtime", "ctime", "type",
 | |
| +	NULL
 | |
| +};
 | |
| +
 | |
| +static int Pstat(lua_State *L)			/** stat(path,[options]) */
 | |
| +{
 | |
| +	struct stat s;
 | |
| +	const char *path=luaL_checkstring(L, 1);
 | |
| +	if (lstat(path,&s)==-1) return pusherror(L, path);
 | |
| +	return doselection(L, 2, Sstat, Fstat, &s);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Puname(lua_State *L)			/** uname([string]) */
 | |
| +{
 | |
| +	struct utsname u;
 | |
| +	luaL_Buffer b;
 | |
| +	const char *s;
 | |
| +	if (uname(&u)==-1) return pusherror(L, NULL);
 | |
| +	luaL_buffinit(L, &b);
 | |
| +	for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
 | |
| +		if (*s!='%')
 | |
| +			luaL_putchar(&b, *s);
 | |
| +		else switch (*++s)
 | |
| +		{
 | |
| +			case '%': luaL_putchar(&b, *s); break;
 | |
| +			case 'm': luaL_addstring(&b,u.machine); break;
 | |
| +			case 'n': luaL_addstring(&b,u.nodename); break;
 | |
| +			case 'r': luaL_addstring(&b,u.release); break;
 | |
| +			case 's': luaL_addstring(&b,u.sysname); break;
 | |
| +			case 'v': luaL_addstring(&b,u.version); break;
 | |
| +			default: badoption(L, 2, "format", *s); break;
 | |
| +		}
 | |
| +	luaL_pushresult(&b);
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static const int Kpathconf[] =
 | |
| +{
 | |
| +	_PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
 | |
| +	_PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
 | |
| +	-1
 | |
| +};
 | |
| +
 | |
| +static void Fpathconf(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +	const char *path=data;
 | |
| +	lua_pushinteger(L, pathconf(path, Kpathconf[i]));
 | |
| +}
 | |
| +
 | |
| +static const char *const Spathconf[] =
 | |
| +{
 | |
| +	"link_max", "max_canon", "max_input", "name_max", "path_max",
 | |
| +	"pipe_buf", "chown_restricted", "no_trunc", "vdisable",
 | |
| +	NULL
 | |
| +};
 | |
| +
 | |
| +static int Ppathconf(lua_State *L)		/** pathconf([path,options]) */
 | |
| +{
 | |
| +	const char *path = luaL_optstring(L, 1, ".");
 | |
| +	return doselection(L, 2, Spathconf, Fpathconf, path);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static const int Ksysconf[] =
 | |
| +{
 | |
| +	_SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
 | |
| +	_SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
 | |
| +	-1
 | |
| +};
 | |
| +
 | |
| +static void Fsysconf(lua_State *L, int i, const void *data)
 | |
| +{
 | |
| +	lua_pushinteger(L, sysconf(Ksysconf[i]));
 | |
| +}
 | |
| +
 | |
| +static const char *const Ssysconf[] =
 | |
| +{
 | |
| +	"arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
 | |
| +	"tzname_max", "open_max", "job_control", "saved_ids", "version",
 | |
| +	NULL
 | |
| +};
 | |
| +
 | |
| +static int Psysconf(lua_State *L)		/** sysconf([options]) */
 | |
| +{
 | |
| +	return doselection(L, 1, Ssysconf, Fsysconf, NULL);
 | |
| +}
 | |
| +
 | |
| +#if ENABLE_SYSLOG
 | |
| +/* syslog funcs */
 | |
| +static int Popenlog(lua_State *L)	/** openlog(ident, [option], [facility]) */
 | |
| +{
 | |
| +	const char *ident = luaL_checkstring(L, 1);
 | |
| +	int option = 0;
 | |
| +	int facility = luaL_optint(L, 3, LOG_USER);
 | |
| +	const char *s = luaL_optstring(L, 2, "");
 | |
| +	while (*s) {
 | |
| +		switch (*s) {
 | |
| +			case ' ': break;
 | |
| +			case 'c': option |= LOG_CONS; break;
 | |
| +			case 'n': option |= LOG_NDELAY; break;
 | |
| +			case 'e': option |= LOG_PERROR; break;
 | |
| +			case 'p': option |= LOG_PID; break;
 | |
| +			default: badoption(L, 2, "option", *s); break;
 | |
| +		}
 | |
| +		s++;
 | |
| +	}
 | |
| +	openlog(ident, option, facility);
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Psyslog(lua_State *L)		/** syslog(priority, message) */
 | |
| +{
 | |
| +	int priority = luaL_checkint(L, 1);
 | |
| +	const char *msg = luaL_checkstring(L, 2);
 | |
| +	syslog(priority, "%s", msg);
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int Pcloselog(lua_State *L)		/** closelog() */
 | |
| +{
 | |
| +	closelog();
 | |
| +	return 0;
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +/*
 | |
| + * XXX: GNU and BSD handle the forward declaration of crypt() in different
 | |
| + * and annoying ways (especially GNU). Declare it here just to make sure
 | |
| + * that it's there
 | |
| + */
 | |
| +char *crypt(const char *, const char *);
 | |
| +
 | |
| +static int Pcrypt(lua_State *L)
 | |
| +{
 | |
| +	const char *str, *salt;
 | |
| +	char *res;
 | |
| +
 | |
| +	str = luaL_checkstring(L, 1);
 | |
| +	salt = luaL_checkstring(L, 2);
 | |
| +	if (strlen(salt) < 2)
 | |
| +		luaL_error(L, "not enough salt");
 | |
| +
 | |
| +	res = crypt(str, salt);
 | |
| +	lua_pushstring(L, res);
 | |
| +
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +static const luaL_reg R[] =
 | |
| +{
 | |
| +	{"access",		Paccess},
 | |
| +	{"basename",		Pbasename},
 | |
| +	{"chdir",		Pchdir},
 | |
| +	{"chmod",		Pchmod},
 | |
| +	{"chown",		Pchown},
 | |
| +	{"crypt",		Pcrypt},
 | |
| +	{"ctermid",		Pctermid},
 | |
| +	{"dirname",		Pdirname},
 | |
| +	{"dir",			Pdir},
 | |
| +	{"dup",			Pdup},
 | |
| +	{"errno",		Perrno},
 | |
| +	{"exec",		Pexec},
 | |
| +	{"execp",		Pexecp},
 | |
| +	{"fdopen",		Pfdopen},
 | |
| +	{"fileno",		Pfileno},
 | |
| +	{"files",		Pfiles},
 | |
| +	{"fork",		Pfork},
 | |
| +	{"getcwd",		Pgetcwd},
 | |
| +	{"getenv",		Pgetenv},
 | |
| +	{"getgroup",		Pgetgroup},
 | |
| +	{"getlogin",		Pgetlogin},
 | |
| +	{"getpasswd",		Pgetpasswd},
 | |
| +	{"getpid",		Pgetpid},
 | |
| +	{"glob",		Pglob},
 | |
| +	{"hostid",		Phostid},
 | |
| +	{"kill",		Pkill},
 | |
| +	{"link",		Plink},
 | |
| +	{"mkdir",		Pmkdir},
 | |
| +	{"mkfifo",		Pmkfifo},
 | |
| +	{"pathconf",		Ppathconf},
 | |
| +	{"pipe",		Ppipe},
 | |
| +	{"readlink",		Preadlink},
 | |
| +	{"rmdir",		Prmdir},
 | |
| +	{"rpoll",		Ppoll},
 | |
| +	{"setenv",		Psetenv},
 | |
| +	{"setpid",		Psetpid},
 | |
| +	{"sleep",		Psleep},
 | |
| +	{"stat",		Pstat},
 | |
| +	{"sysconf",		Psysconf},
 | |
| +	{"times",		Ptimes},
 | |
| +	{"ttyname",		Pttyname},
 | |
| +	{"unlink",		Punlink},
 | |
| +	{"umask",		Pumask},
 | |
| +	{"uname",		Puname},
 | |
| +	{"utime",		Putime},
 | |
| +	{"wait",		Pwait},
 | |
| +
 | |
| +#if ENABLE_SYSLOG
 | |
| +	{"openlog",		Popenlog},
 | |
| +	{"syslog",		Psyslog},
 | |
| +	{"closelog",		Pcloselog},
 | |
| +#endif
 | |
| +
 | |
| +	{NULL,			NULL}
 | |
| +};
 | |
| +
 | |
| +#define set_const(key, value)		\
 | |
| +	lua_pushliteral(L, key);	\
 | |
| +	lua_pushnumber(L, value);	\
 | |
| +	lua_settable(L, -3)
 | |
| +
 | |
| +LUALIB_API int luaopen_posix (lua_State *L)
 | |
| +{
 | |
| +	luaL_register(L,MYNAME,R);
 | |
| +	lua_pushliteral(L,"version");		/** version */
 | |
| +	lua_pushliteral(L,MYVERSION);
 | |
| +	lua_settable(L,-3);
 | |
| +
 | |
| +#if ENABLE_SYSLOG
 | |
| +	set_const("LOG_AUTH", LOG_AUTH);
 | |
| +	set_const("LOG_AUTHPRIV", LOG_AUTHPRIV);
 | |
| +	set_const("LOG_CRON", LOG_CRON);
 | |
| +	set_const("LOG_DAEMON", LOG_DAEMON);
 | |
| +	set_const("LOG_FTP", LOG_FTP);
 | |
| +	set_const("LOG_KERN", LOG_KERN);
 | |
| +	set_const("LOG_LOCAL0", LOG_LOCAL0);
 | |
| +	set_const("LOG_LOCAL1", LOG_LOCAL1);
 | |
| +	set_const("LOG_LOCAL2", LOG_LOCAL2);
 | |
| +	set_const("LOG_LOCAL3", LOG_LOCAL3);
 | |
| +	set_const("LOG_LOCAL4", LOG_LOCAL4);
 | |
| +	set_const("LOG_LOCAL5", LOG_LOCAL5);
 | |
| +	set_const("LOG_LOCAL6", LOG_LOCAL6);
 | |
| +	set_const("LOG_LOCAL7", LOG_LOCAL7);
 | |
| +	set_const("LOG_LPR", LOG_LPR);
 | |
| +	set_const("LOG_MAIL", LOG_MAIL);
 | |
| +	set_const("LOG_NEWS", LOG_NEWS);
 | |
| +	set_const("LOG_SYSLOG", LOG_SYSLOG);
 | |
| +	set_const("LOG_USER", LOG_USER);
 | |
| +	set_const("LOG_UUCP", LOG_UUCP);
 | |
| +
 | |
| +	set_const("LOG_EMERG", LOG_EMERG);
 | |
| +	set_const("LOG_ALERT", LOG_ALERT);
 | |
| +	set_const("LOG_CRIT", LOG_CRIT);
 | |
| +	set_const("LOG_ERR", LOG_ERR);
 | |
| +	set_const("LOG_WARNING", LOG_WARNING);
 | |
| +	set_const("LOG_NOTICE", LOG_NOTICE);
 | |
| +	set_const("LOG_INFO", LOG_INFO);
 | |
| +	set_const("LOG_DEBUG", LOG_DEBUG);
 | |
| +#endif
 | |
| +
 | |
| +
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +/*EOF*/
 | |
| Index: lua-5.1.4/src/lualib.h
 | |
| ===================================================================
 | |
| --- lua-5.1.4.orig/src/lualib.h	2008-09-25 12:18:14.000000000 +0200
 | |
| +++ lua-5.1.4/src/lualib.h	2008-09-25 12:18:53.000000000 +0200
 | |
| @@ -39,6 +39,9 @@
 | |
|  #define LUA_LOADLIBNAME	"package"
 | |
|  LUALIB_API int (luaopen_package) (lua_State *L);
 | |
|  
 | |
| +#define LUA_POSIXLIBNAME "posix"
 | |
| +LUALIB_API int (luaopen_posix) (lua_State *L);
 | |
| +
 | |
|  
 | |
|  /* open all previous libraries */
 | |
|  LUALIB_API void (luaL_openlibs) (lua_State *L); 
 | |
| Index: lua-5.1.4/src/modemuncher.c
 | |
| ===================================================================
 | |
| --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 | |
| +++ lua-5.1.4/src/modemuncher.c	2008-09-25 12:16:29.000000000 +0200
 | |
| @@ -0,0 +1,261 @@
 | |
| +/* 
 | |
| +	Mode Muncher -- modemuncher.c
 | |
| +	961110 Claudio Terra
 | |
| +
 | |
| +	munch vb
 | |
| +	[ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
 | |
| +	:to chew with a crunching sound: eat with relish
 | |
| +	:to chew food with a crunching sound: eat food with relish
 | |
| +	--munch-er n
 | |
| +		
 | |
| +	The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
 | |
| +	and Webster's Collegiate Thesaurus
 | |
| +*/
 | |
| +
 | |
| +/* struct for rwx <-> POSIX constant lookup tables */
 | |
| +struct modeLookup
 | |
| +{
 | |
| +	char rwx;
 | |
| +	mode_t bits;
 | |
| +};
 | |
| +
 | |
| +typedef struct modeLookup modeLookup;
 | |
| +
 | |
| +static modeLookup modesel[] =
 | |
| +{
 | |
| +	/* RWX char				Posix Constant */
 | |
| +	{'r',					S_IRUSR},
 | |
| +	{'w',					S_IWUSR},
 | |
| +	{'x',					S_IXUSR},
 | |
| +	
 | |
| +	{'r',					S_IRGRP},
 | |
| +	{'w',					S_IWGRP},
 | |
| +	{'x',					S_IXGRP},
 | |
| +	
 | |
| +	{'r',					S_IROTH},
 | |
| +	{'w',					S_IWOTH},
 | |
| +	{'x',					S_IXOTH},
 | |
| +	{0, 					(mode_t)-1} /* do not delete this line */
 | |
| +};
 | |
| +
 | |
| +
 | |
| +
 | |
| +static int rwxrwxrwx(mode_t *mode, const char *p)
 | |
| +{
 | |
| +	int count;
 | |
| +	mode_t tmp_mode = *mode;
 | |
| +	
 | |
| +	tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */
 | |
| +	for (count=0; count<9; count ++)
 | |
| +	{
 | |
| +		if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits;	/* set a bit */
 | |
| +		else if (*p == '-') tmp_mode &= ~modesel[count].bits;			/* clear a bit */
 | |
| +		else if (*p=='s') switch(count)
 | |
| +		{
 | |
| +			case 2: /* turn on suid flag */
 | |
| +			tmp_mode |= S_ISUID | S_IXUSR;
 | |
| +			break;
 | |
| +			
 | |
| +			case 5: /* turn on sgid flag */
 | |
| +			tmp_mode |= S_ISGID | S_IXGRP;
 | |
| +			break;
 | |
| +
 | |
| +			default:
 | |
| +			return -4; /* failed! -- bad rwxrwxrwx mode change */
 | |
| +			break;
 | |
| +		}
 | |
| +		p++;
 | |
| +	}
 | |
| +	*mode = tmp_mode;
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static void modechopper(mode_t mode, char *p)
 | |
| +{
 | |
| +	/* requires char p[10] */
 | |
| +	int count;
 | |
| +	char *pp;
 | |
| +	
 | |
| +	pp=p;
 | |
| +	
 | |
| +	for (count=0; count<9; count ++)
 | |
| +	{
 | |
| +		if (mode & modesel[count].bits) *p = modesel[count].rwx;
 | |
| +		else *p='-';
 | |
| +		
 | |
| +		p++;
 | |
| +	}
 | |
| +	*p=0; /* to finish the string */
 | |
| +	
 | |
| +	/* dealing with suid and sgid flags */
 | |
| +	if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S';
 | |
| +	if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S';
 | |
| +
 | |
| +}
 | |
| +
 | |
| +static int mode_munch(mode_t *mode, const char* p)
 | |
| +{
 | |
| +
 | |
| +	char op=0;
 | |
| +	mode_t affected_bits, ch_mode;
 | |
| +	int doneFlag = 0;
 | |
| +#ifdef DEBUG
 | |
| +char tmp[10];
 | |
| +#endif
 | |
| +
 | |
| +#ifdef DEBUG
 | |
| +modechopper(*mode, tmp);
 | |
| +printf("modemuncher: got base mode = %s\n", tmp);
 | |
| +#endif
 | |
| +
 | |
| +	while (!doneFlag)
 | |
| +	{
 | |
| +		/* step 0 -- clear temporary variables */
 | |
| +		affected_bits=0;
 | |
| +		ch_mode=0;
 | |
| +		
 | |
| +		/* step 1 -- who's affected? */
 | |
| +
 | |
| +#ifdef DEBUG
 | |
| +printf("modemuncher step 1\n");
 | |
| +#endif
 | |
| +		
 | |
| +		/* mode string given in rwxrwxrwx format */
 | |
| +		if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
 | |
| +		
 | |
| +		/* mode string given in ugoa+-=rwx format */
 | |
| +		for ( ; ; p++)
 | |
| +			switch (*p)
 | |
| +			{
 | |
| +				case 'u':
 | |
| +				affected_bits |= 04700;
 | |
| +				break;
 | |
| +				
 | |
| +				case 'g':
 | |
| +				affected_bits |= 02070;
 | |
| +				break;
 | |
| +				
 | |
| +				case 'o':
 | |
| +				affected_bits |= 01007;
 | |
| +				break;
 | |
| +				
 | |
| +				case 'a':
 | |
| +				affected_bits |= 07777;
 | |
| +				break;
 | |
| +				
 | |
| +				/* ignore spaces */
 | |
| +				case ' ':
 | |
| +				break;
 | |
| +				
 | |
| +				
 | |
| +				default:
 | |
| +				goto no_more_affected;
 | |
| +			}
 | |
| +
 | |
| +		no_more_affected:
 | |
| +		/* If none specified, affect all bits. */
 | |
| +		if (affected_bits == 0) affected_bits = 07777;
 | |
| +
 | |
| +		/* step 2 -- how is it changed? */
 | |
| +		
 | |
| +#ifdef DEBUG
 | |
| +printf("modemuncher step 2 (*p='%c')\n", *p);
 | |
| +#endif
 | |
| +
 | |
| +		switch (*p)
 | |
| +		{
 | |
| +			case '+':
 | |
| +			case '-':
 | |
| +			case '=':
 | |
| +			op = *p;
 | |
| +			break;
 | |
| +			
 | |
| +			/* ignore spaces */
 | |
| +			case ' ':
 | |
| +			break;
 | |
| +			
 | |
| +			default:
 | |
| +			return -1; /* failed! -- bad operator */
 | |
| +		}
 | |
| +		
 | |
| +		
 | |
| +		/* step 3 -- what are the changes? */
 | |
| +		
 | |
| +#ifdef DEBUG
 | |
| +printf("modemuncher step 3\n");
 | |
| +#endif
 | |
| +
 | |
| +		for (p++ ; *p!=0 ; p++)
 | |
| +			switch (*p)
 | |
| +			{
 | |
| +				case 'r':
 | |
| +				ch_mode |= 00444;
 | |
| +				break;
 | |
| +				
 | |
| +				case 'w':
 | |
| +				ch_mode |= 00222;
 | |
| +				break;
 | |
| +				
 | |
| +				case 'x':
 | |
| +				ch_mode |= 00111;
 | |
| +				break;
 | |
| +				
 | |
| +				case 's':
 | |
| +				/* Set the setuid/gid bits if `u' or `g' is selected. */
 | |
| +				ch_mode |= 06000;
 | |
| +				break;
 | |
| +			
 | |
| +				/* ignore spaces */
 | |
| +				case ' ':
 | |
| +				break;
 | |
| +				
 | |
| +				default:
 | |
| +				goto specs_done;
 | |
| +			}
 | |
| +
 | |
| +		specs_done:
 | |
| +		/* step 4 -- apply the changes */
 | |
| +
 | |
| +#ifdef DEBUG
 | |
| +		printf("modemuncher step 4\n");
 | |
| +#endif
 | |
| +		if (*p != ',') doneFlag = 1;
 | |
| +		if (*p != 0 && *p != ' ' && *p != ',')
 | |
| +		{
 | |
| +		
 | |
| +#ifdef DEBUG
 | |
| +printf("modemuncher: comma error!\n");
 | |
| +printf("modemuncher: doneflag = %u\n", doneFlag);
 | |
| +#endif
 | |
| +			return -2; /* failed! -- bad mode change */
 | |
| +		
 | |
| +		}
 | |
| +		p++;
 | |
| +		/*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
 | |
| +		if (ch_mode) switch (op)
 | |
| +		{
 | |
| +			case '+':
 | |
| +			*mode = *mode |= ch_mode & affected_bits;
 | |
| +			break;
 | |
| +
 | |
| +			case '-':
 | |
| +			*mode = *mode &= ~(ch_mode & affected_bits);
 | |
| +			break;
 | |
| +
 | |
| +			case '=':
 | |
| +			*mode = ch_mode & affected_bits;
 | |
| +			break;
 | |
| +		
 | |
| +			default:
 | |
| +			return -3; /* failed! -- unknown error */
 | |
| +		}
 | |
| +	}
 | |
| +#ifdef DEBUG
 | |
| +modechopper(*mode, tmp);
 | |
| +printf("modemuncher: returning mode = %s\n", tmp);
 | |
| +#endif
 | |
| +
 | |
| +	return 0; /* successful call */
 | |
| +}
 | |
| +
 | |
| +
 | 
