3 @@ -12,7 +12,7 @@ CFLAGS= -O2 -Wall $(MYCFLAGS)
8 +LIBS= -lm -lcrypt $(MYLIBS)
12 @@ -29,7 +29,7 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ld
13 lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
14 lundump.o lvm.o lzio.o lnum.o
15 LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
16 - lstrlib.o loadlib.o linit.o
17 + lstrlib.o loadlib.o linit.o lposix.o
23 @@ -23,6 +23,7 @@ static const luaL_Reg lualibs[] = {
24 {LUA_STRLIBNAME, luaopen_string},
25 {LUA_MATHLIBNAME, luaopen_math},
26 {LUA_DBLIBNAME, luaopen_debug},
27 + {LUA_POSIXLIBNAME, luaopen_posix},
36 +* POSIX library for Lua 5.1.
37 +* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
38 +* 07 Apr 2006 23:17:49
39 +* Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11 <!LR>
40 +* Based on original by Claudio Terra for Lua 3.x.
41 +* With contributions by Roberto Ierusalimschy.
44 +#include <sys/stat.h>
45 +#include <sys/times.h>
46 +#include <sys/types.h>
47 +#include <sys/utsname.h>
48 +#include <sys/wait.h>
68 +#define MYNAME "posix"
69 +#define MYVERSION MYNAME " library for " LUA_VERSION " / Jan 2008"
71 +#ifndef ENABLE_SYSLOG
72 +#define ENABLE_SYSLOG 1
79 +#include "modemuncher.c"
81 +/* compatibility with Lua 5.0 */
82 +#ifndef LUA_VERSION_NUM
83 +static int luaL_checkoption (lua_State *L, int narg, const char *def,
84 + const char *const lst[]) {
85 + const char *name = (def) ? luaL_optstring(L, narg, def) :
86 + luaL_checkstring(L, narg);
87 + int i = luaL_findstring(name, lst);
89 + luaL_argerror(L, narg, lua_pushfstring(L, "invalid option '%s'", name));
92 +#define lua_pushinteger lua_pushnumber
93 +#define lua_createtable(L,a,r) lua_newtable(L)
94 +#define LUA_FILEHANDLE "FILE*"
96 +#define lua_setfield(l,i,k)
97 +#define lua_getfield(l,i,k)
101 +static const struct { char c; mode_t b; } M[] =
103 + {'r', S_IRUSR}, {'w', S_IWUSR}, {'x', S_IXUSR},
104 + {'r', S_IRGRP}, {'w', S_IWGRP}, {'x', S_IXGRP},
105 + {'r', S_IROTH}, {'w', S_IWOTH}, {'x', S_IXOTH},
109 +static void pushmode(lua_State *L, mode_t mode)
113 + for (i=0; i<9; i++) m[i]= (mode & M[i].b) ? M[i].c : '-';
114 + if (mode & S_ISUID) m[2]= (mode & S_IXUSR) ? 's' : 'S';
115 + if (mode & S_ISGID) m[5]= (mode & S_IXGRP) ? 's' : 'S';
116 + lua_pushlstring(L, m, 9);
119 +typedef void (*Selector)(lua_State *L, int i, const void *data);
121 +static int doselection(lua_State *L, int i, int n,
122 + const char *const S[],
126 + if (lua_isnone(L, i) || lua_istable(L, i))
129 + if (lua_isnone(L, i)) lua_createtable(L,0,n); else lua_settop(L, i);
130 + for (j=0; S[j]!=NULL; j++)
132 + lua_pushstring(L, S[j]);
134 + lua_settable(L, -3);
140 + int k,n=lua_gettop(L);
141 + for (k=i; k<=n; k++)
143 + int j=luaL_checkoption(L, k, NULL, S);
150 +#define doselection(L,i,S,F,d) (doselection)(L,i,sizeof(S)/sizeof(*S)-1,S,F,d)
152 +static int pusherror(lua_State *L, const char *info)
156 + lua_pushstring(L, strerror(errno));
158 + lua_pushfstring(L, "%s: %s", info, strerror(errno));
159 + lua_pushinteger(L, errno);
163 +static int pushresult(lua_State *L, int i, const char *info)
165 + if (i==-1) return pusherror(L, info);
166 + lua_pushinteger(L, i);
170 +static void badoption(lua_State *L, int i, const char *what, int option)
172 + luaL_argerror(L, 2,
173 + lua_pushfstring(L, "unknown %s option '%c'", what, option));
176 +static uid_t mygetuid(lua_State *L, int i)
178 + if (lua_isnone(L, i))
180 + else if (lua_isnumber(L, i))
181 + return (uid_t) lua_tonumber(L, i);
182 + else if (lua_isstring(L, i))
184 + struct passwd *p=getpwnam(lua_tostring(L, i));
185 + return (p==NULL) ? -1 : p->pw_uid;
188 + return luaL_typerror(L, i, "string or number");
191 +static gid_t mygetgid(lua_State *L, int i)
193 + if (lua_isnone(L, i))
195 + else if (lua_isnumber(L, i))
196 + return (gid_t) lua_tonumber(L, i);
197 + else if (lua_isstring(L, i))
199 + struct group *g=getgrnam(lua_tostring(L, i));
200 + return (g==NULL) ? -1 : g->gr_gid;
203 + return luaL_typerror(L, i, "string or number");
207 +static int Perrno(lua_State *L) /** errno([n]) */
209 + int n = luaL_optint(L, 1, errno);
210 + lua_pushstring(L, strerror(n));
211 + lua_pushinteger(L, n);
216 +static int Pbasename(lua_State *L) /** basename(path) */
220 + const char *path = luaL_checklstring(L, 1, &len);
221 + if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
222 + lua_pushstring(L, basename(strcpy(b,path)));
227 +static int Pdirname(lua_State *L) /** dirname(path) */
231 + const char *path = luaL_checklstring(L, 1, &len);
232 + if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
233 + lua_pushstring(L, dirname(strcpy(b,path)));
238 +static int Pdir(lua_State *L) /** dir([path]) */
240 + const char *path = luaL_optstring(L, 1, ".");
241 + DIR *d = opendir(path);
243 + return pusherror(L, path);
247 + struct dirent *entry;
249 + for (i=1; (entry = readdir(d)) != NULL; i++)
251 + lua_pushstring(L, entry->d_name);
252 + lua_rawseti(L, -2, i);
255 + lua_pushinteger(L, i-1);
260 +static int Pglob(lua_State *L) /** glob(pattern) */
262 + const char *pattern = luaL_optstring(L, 1, "*");
265 + if (glob(pattern, 0, NULL, &globres))
266 + return pusherror(L, pattern);
271 + for (i=1; i<=globres.gl_pathc; i++) {
272 + lua_pushstring(L, globres.gl_pathv[i-1]);
273 + lua_rawseti(L, -2, i);
275 + globfree(&globres);
280 +static int aux_files(lua_State *L)
282 + DIR **p = (DIR **)lua_touserdata(L, lua_upvalueindex(1));
284 + struct dirent *entry;
285 + if (d == NULL) return 0;
286 + entry = readdir(d);
295 + lua_pushstring(L, entry->d_name);
300 +static int dir_gc (lua_State *L)
302 + DIR *d = *(DIR **)lua_touserdata(L, 1);
303 + if (d!=NULL) closedir(d);
307 +static int Pfiles(lua_State *L) /** files([path]) */
309 + const char *path = luaL_optstring(L, 1, ".");
310 + DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *));
311 + if (luaL_newmetatable(L, MYNAME " dir handle"))
313 + lua_pushliteral(L, "__gc");
314 + lua_pushcfunction(L, dir_gc);
315 + lua_settable(L, -3);
317 + lua_setmetatable(L, -2);
318 + *d = opendir(path);
319 + if (*d == NULL) return pusherror(L, path);
320 + lua_pushcclosure(L, aux_files, 1);
325 +static int Pgetcwd(lua_State *L) /** getcwd() */
328 + if (getcwd(b, sizeof(b)) == NULL) return pusherror(L, ".");
329 + lua_pushstring(L, b);
334 +static int Pmkdir(lua_State *L) /** mkdir(path) */
336 + const char *path = luaL_checkstring(L, 1);
337 + return pushresult(L, mkdir(path, 0777), path);
341 +static int Pchdir(lua_State *L) /** chdir(path) */
343 + const char *path = luaL_checkstring(L, 1);
344 + return pushresult(L, chdir(path), path);
347 +static int Prmdir(lua_State *L) /** rmdir(path) */
349 + const char *path = luaL_checkstring(L, 1);
350 + return pushresult(L, rmdir(path), path);
354 +static int Punlink(lua_State *L) /** unlink(path) */
356 + const char *path = luaL_checkstring(L, 1);
357 + return pushresult(L, unlink(path), path);
360 +static int Plink(lua_State *L) /** link(old,new,[symbolic]) */
362 + const char *oldpath = luaL_checkstring(L, 1);
363 + const char *newpath = luaL_checkstring(L, 2);
364 + return pushresult(L,
365 + (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
369 +static int Preadlink(lua_State *L) /** readlink(path) */
372 + const char *path = luaL_checkstring(L, 1);
373 + int n = readlink(path, b, sizeof(b));
374 + if (n==-1) return pusherror(L, path);
375 + lua_pushlstring(L, b, n);
380 +static int Paccess(lua_State *L) /** access(path,[mode]) */
383 + const char *path=luaL_checkstring(L, 1);
385 + for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
389 + case 'r': mode |= R_OK; break;
390 + case 'w': mode |= W_OK; break;
391 + case 'x': mode |= X_OK; break;
392 + case 'f': mode |= F_OK; break;
393 + default: badoption(L, 2, "mode", *s); break;
395 + return pushresult(L, access(path, mode), path);
399 +static int myfclose (lua_State *L) {
400 + FILE **p = (FILE **)lua_touserdata(L, 1);
401 + int rc = fclose(*p);
402 + if (rc == 0) *p = NULL;
403 + return pushresult(L, rc, NULL);
406 +static int pushfile (lua_State *L, int id, const char *mode) {
407 + FILE **f = (FILE **)lua_newuserdata(L, sizeof(FILE *));
409 + luaL_getmetatable(L, LUA_FILEHANDLE);
410 + lua_setmetatable(L, -2);
411 + lua_getfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
412 + if (lua_isnil(L, -1)) {
415 + lua_pushvalue(L, -1);
416 + lua_pushcfunction(L, myfclose);
417 + lua_setfield(L, -2, "__close");
418 + lua_setfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
420 + lua_setfenv(L, -2);
421 + *f = fdopen(id, mode);
422 + return (*f != NULL);
425 +static int Ppipe(lua_State *L) /** pipe() */
428 + if (pipe(fd)==-1) return pusherror(L, NULL);
429 + if (!pushfile(L, fd[0], "r") || !pushfile(L, fd[1], "w"))
430 + return pusherror(L, "pipe");
435 +static int Pfileno(lua_State *L) /** fileno(filehandle) */
437 + FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
438 + return pushresult(L, fileno(f), NULL);
442 +static int Pfdopen(lua_State *L) /** fdopen(fd, mode) */
444 + int fd = luaL_checkint(L, 1);
445 + const char *mode = luaL_checkstring(L, 2);
446 + if (!pushfile(L, fd, mode))
447 + return pusherror(L, "fdpoen");
452 +/* helper func for Pdup */
453 +static const char *filemode(int fd)
456 + int mode = fcntl(fd, F_GETFL);
459 + switch (mode & O_ACCMODE) {
460 + case O_RDONLY: m = "r"; break;
461 + case O_WRONLY: m = "w"; break;
462 + default: m = "rw"; break;
467 +static int Pdup(lua_State *L) /** dup(old,[new]) */
469 + FILE **oldf = (FILE**)luaL_checkudata(L, 1, LUA_FILEHANDLE);
470 + FILE **newf = (FILE **)lua_touserdata(L, 2);
472 + const char *msg = "dup2";
474 + if (newf == NULL) {
475 + fd = dup(fileno(*oldf));
479 + fd = dup2(fileno(*oldf), fileno(*newf));
482 + if ((fd < 0) || !pushfile(L, fd, filemode(fd)))
483 + return pusherror(L, msg);
488 +static int Pmkfifo(lua_State *L) /** mkfifo(path) */
490 + const char *path = luaL_checkstring(L, 1);
491 + return pushresult(L, mkfifo(path, 0777), path);
495 +static int runexec(lua_State *L, int use_shell)
497 + const char *path = luaL_checkstring(L, 1);
498 + int i,n=lua_gettop(L);
499 + char **argv = lua_newuserdata(L,(n+1)*sizeof(char*));
500 + argv[0] = (char*)path;
501 + for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
504 + execvp(path, argv);
508 + return pusherror(L, path);
512 +static int Pexec(lua_State *L) /** exec(path,[args]) */
514 + return runexec(L, 0);
518 +static int Pexecp(lua_State *L) /** execp(path,[args]) */
520 + return runexec(L, 1);
524 +static int Pfork(lua_State *L) /** fork() */
526 + return pushresult(L, fork(), NULL);
529 +/* from http://lua-users.org/lists/lua-l/2007-11/msg00346.html */
530 +static int Ppoll(lua_State *L) /** poll(filehandle, timeout) */
533 + FILE* file = *(FILE**)luaL_checkudata(L,1,LUA_FILEHANDLE);
534 + int timeout = luaL_checkint(L,2);
535 + fds.fd = fileno(file);
536 + fds.events = POLLIN;
537 + return pushresult(L, poll(&fds,1,timeout), NULL);
540 +static int Pwait(lua_State *L) /** wait([pid]) */
543 + pid_t pid = luaL_optint(L, 1, -1);
544 + pid = waitpid(pid, &status, 0);
545 + if (pid == -1) return pusherror(L, NULL);
546 + lua_pushinteger(L, pid);
547 + if (WIFEXITED(status))
549 + lua_pushliteral(L,"exited");
550 + lua_pushinteger(L, WEXITSTATUS(status));
553 + else if (WIFSIGNALED(status))
555 + lua_pushliteral(L,"killed");
556 + lua_pushinteger(L, WTERMSIG(status));
559 + else if (WIFSTOPPED(status))
561 + lua_pushliteral(L,"stopped");
562 + lua_pushinteger(L, WSTOPSIG(status));
569 +static int Pkill(lua_State *L) /** kill(pid,[sig]) */
571 + pid_t pid = luaL_checkint(L, 1);
572 + int sig = luaL_optint(L, 2, SIGTERM);
573 + return pushresult(L, kill(pid, sig), NULL);
576 +static int Psetpid(lua_State *L) /** setpid(option,...) */
578 + const char *what=luaL_checkstring(L, 1);
582 + return pushresult(L, seteuid(mygetuid(L, 2)), NULL);
584 + return pushresult(L, setuid(mygetuid(L, 2)), NULL);
586 + return pushresult(L, setegid(mygetgid(L, 2)), NULL);
588 + return pushresult(L, setgid(mygetgid(L, 2)), NULL);
590 + return pushresult(L, setsid(), NULL);
593 + pid_t pid = luaL_checkint(L, 2);
594 + pid_t pgid = luaL_checkint(L, 3);
595 + return pushresult(L, setpgid(pid,pgid), NULL);
598 + badoption(L, 2, "id", *what);
604 +static int Psleep(lua_State *L) /** sleep(seconds) */
606 + unsigned int seconds = luaL_checkint(L, 1);
607 + lua_pushinteger(L, sleep(seconds));
612 +static int Psetenv(lua_State *L) /** setenv(name,value,[over]) */
614 + const char *name=luaL_checkstring(L, 1);
615 + const char *value=luaL_optstring(L, 2, NULL);
619 + return pushresult(L, 0, NULL);
623 + int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
624 + return pushresult(L, setenv(name,value,overwrite), NULL);
629 +static int Pgetenv(lua_State *L) /** getenv([name]) */
631 + if (lua_isnone(L, 1))
633 + extern char **environ;
636 + for (e=environ; *e!=NULL; e++)
639 + char *eq=strchr(s, '=');
640 + if (eq==NULL) /* will this ever happen? */
642 + lua_pushstring(L,s);
643 + lua_pushboolean(L,1);
647 + lua_pushlstring(L,s,eq-s);
648 + lua_pushstring(L,eq+1);
650 + lua_settable(L,-3);
654 + lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
658 +static int Pumask(lua_State *L) /** umask([mode]) */
659 +{/* <!LR> from old lposix-5.0 version */
662 + umask(mode=umask(0));
664 + if (!lua_isnone(L, 1))
666 + if (mode_munch(&mode, luaL_checkstring(L, 1)))
674 + modechopper(mode, m);
675 + lua_pushstring(L, m);
680 +static int Pchmod(lua_State *L) /** chmod(path,mode) */
684 + const char *path = luaL_checkstring(L, 1);
685 + const char *modestr = luaL_checkstring(L, 2);
686 + if (stat(path, &s)) return pusherror(L, path);
688 + if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
689 + return pushresult(L, chmod(path, mode), path);
693 +static int Pchown(lua_State *L) /** chown(path,uid,gid) */
695 + const char *path = luaL_checkstring(L, 1);
696 + uid_t uid = mygetuid(L, 2);
697 + gid_t gid = mygetgid(L, 3);
698 + return pushresult(L, chown(path, uid, gid), path);
702 +static int Putime(lua_State *L) /** utime(path,[mtime,atime]) */
704 + struct utimbuf times;
705 + time_t currtime = time(NULL);
706 + const char *path = luaL_checkstring(L, 1);
707 + times.modtime = luaL_optnumber(L, 2, currtime);
708 + times.actime = luaL_optnumber(L, 3, currtime);
709 + return pushresult(L, utime(path, ×), path);
713 +static void FgetID(lua_State *L, int i, const void *data)
717 + case 0: lua_pushinteger(L, getegid()); break;
718 + case 1: lua_pushinteger(L, geteuid()); break;
719 + case 2: lua_pushinteger(L, getgid()); break;
720 + case 3: lua_pushinteger(L, getuid()); break;
721 + case 4: lua_pushinteger(L, getpgrp()); break;
722 + case 5: lua_pushinteger(L, getpid()); break;
723 + case 6: lua_pushinteger(L, getppid()); break;
727 +static const char *const SgetID[] =
729 + "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
732 +static int Pgetpid(lua_State *L) /** getpid([options]) */
734 + return doselection(L, 1, SgetID, FgetID, NULL);
738 +static int Phostid(lua_State *L) /** hostid() */
741 + sprintf(b,"%ld",gethostid());
742 + lua_pushstring(L, b);
747 +static int Pttyname(lua_State *L) /** ttyname([fd]) */
749 + int fd=luaL_optint(L, 1, 0);
750 + lua_pushstring(L, ttyname(fd));
755 +static int Pctermid(lua_State *L) /** ctermid() */
758 + lua_pushstring(L, ctermid(b));
763 +static int Pgetlogin(lua_State *L) /** getlogin() */
765 + lua_pushstring(L, getlogin());
770 +static void Fgetpasswd(lua_State *L, int i, const void *data)
772 + const struct passwd *p=data;
775 + case 0: lua_pushstring(L, p->pw_name); break;
776 + case 1: lua_pushinteger(L, p->pw_uid); break;
777 + case 2: lua_pushinteger(L, p->pw_gid); break;
778 + case 3: lua_pushstring(L, p->pw_dir); break;
779 + case 4: lua_pushstring(L, p->pw_shell); break;
780 +/* not strictly POSIX */
781 + case 5: lua_pushstring(L, p->pw_gecos); break;
782 + case 6: lua_pushstring(L, p->pw_passwd); break;
786 +static const char *const Sgetpasswd[] =
788 + "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
792 +static int Pgetpasswd(lua_State *L) /** getpasswd(name|id,[sel]) */
794 + struct passwd *p=NULL;
795 + if (lua_isnoneornil(L, 1))
796 + p = getpwuid(geteuid());
797 + else if (lua_isnumber(L, 1))
798 + p = getpwuid((uid_t)lua_tonumber(L, 1));
799 + else if (lua_isstring(L, 1))
800 + p = getpwnam(lua_tostring(L, 1));
802 + luaL_typerror(L, 1, "string or number");
806 + return doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
811 +static int Pgetgroup(lua_State *L) /** getgroup(name|id) */
813 + struct group *g=NULL;
814 + if (lua_isnumber(L, 1))
815 + g = getgrgid((gid_t)lua_tonumber(L, 1));
816 + else if (lua_isstring(L, 1))
817 + g = getgrnam(lua_tostring(L, 1));
819 + luaL_typerror(L, 1, "string or number");
826 + lua_pushliteral(L, "name");
827 + lua_pushstring(L, g->gr_name);
828 + lua_settable(L, -3);
829 + lua_pushliteral(L, "gid");
830 + lua_pushinteger(L, g->gr_gid);
831 + lua_settable(L, -3);
832 + for (i=0; g->gr_mem[i]!=NULL; i++)
834 + lua_pushstring(L, g->gr_mem[i]);
835 + lua_rawseti(L, -2, i);
848 +/* #define pushtime(L,x) lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC) */
849 +#define pushtime(L,x) lua_pushnumber(L, ((lua_Number)x)/clk_tck)
851 +static void Ftimes(lua_State *L, int i, const void *data)
853 + static long clk_tck = 0;
854 + const struct mytimes *t=data;
856 + if( !clk_tck){ clk_tck= sysconf(_SC_CLK_TCK);}
859 + case 0: pushtime(L, t->t.tms_utime); break;
860 + case 1: pushtime(L, t->t.tms_stime); break;
861 + case 2: pushtime(L, t->t.tms_cutime); break;
862 + case 3: pushtime(L, t->t.tms_cstime); break;
863 + case 4: pushtime(L, t->elapsed); break;
867 +static const char *const Stimes[] =
869 + "utime", "stime", "cutime", "cstime", "elapsed", NULL
872 +static int Ptimes(lua_State *L) /** times([options]) */
875 + t.elapsed = times(&t.t);
876 + return doselection(L, 1, Stimes, Ftimes, &t);
880 +static const char *filetype(mode_t m)
882 + if (S_ISREG(m)) return "regular";
883 + else if (S_ISLNK(m)) return "link";
884 + else if (S_ISDIR(m)) return "directory";
885 + else if (S_ISCHR(m)) return "character device";
886 + else if (S_ISBLK(m)) return "block device";
887 + else if (S_ISFIFO(m)) return "fifo";
888 + else if (S_ISSOCK(m)) return "socket";
892 +static void Fstat(lua_State *L, int i, const void *data)
894 + const struct stat *s=data;
897 + case 0: pushmode(L, s->st_mode); break;
898 + case 1: lua_pushinteger(L, s->st_ino); break;
899 + case 2: lua_pushinteger(L, s->st_dev); break;
900 + case 3: lua_pushinteger(L, s->st_nlink); break;
901 + case 4: lua_pushinteger(L, s->st_uid); break;
902 + case 5: lua_pushinteger(L, s->st_gid); break;
903 + case 6: lua_pushinteger(L, s->st_size); break;
904 + case 7: lua_pushinteger(L, s->st_atime); break;
905 + case 8: lua_pushinteger(L, s->st_mtime); break;
906 + case 9: lua_pushinteger(L, s->st_ctime); break;
907 + case 10:lua_pushstring(L, filetype(s->st_mode)); break;
911 +static const char *const Sstat[] =
913 + "mode", "ino", "dev", "nlink", "uid", "gid",
914 + "size", "atime", "mtime", "ctime", "type",
918 +static int Pstat(lua_State *L) /** stat(path,[options]) */
921 + const char *path=luaL_checkstring(L, 1);
922 + if (lstat(path,&s)==-1) return pusherror(L, path);
923 + return doselection(L, 2, Sstat, Fstat, &s);
927 +static int Puname(lua_State *L) /** uname([string]) */
932 + if (uname(&u)==-1) return pusherror(L, NULL);
933 + luaL_buffinit(L, &b);
934 + for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
936 + luaL_putchar(&b, *s);
939 + case '%': luaL_putchar(&b, *s); break;
940 + case 'm': luaL_addstring(&b,u.machine); break;
941 + case 'n': luaL_addstring(&b,u.nodename); break;
942 + case 'r': luaL_addstring(&b,u.release); break;
943 + case 's': luaL_addstring(&b,u.sysname); break;
944 + case 'v': luaL_addstring(&b,u.version); break;
945 + default: badoption(L, 2, "format", *s); break;
947 + luaL_pushresult(&b);
952 +static const int Kpathconf[] =
954 + _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
955 + _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
959 +static void Fpathconf(lua_State *L, int i, const void *data)
961 + const char *path=data;
962 + lua_pushinteger(L, pathconf(path, Kpathconf[i]));
965 +static const char *const Spathconf[] =
967 + "link_max", "max_canon", "max_input", "name_max", "path_max",
968 + "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
972 +static int Ppathconf(lua_State *L) /** pathconf([path,options]) */
974 + const char *path = luaL_optstring(L, 1, ".");
975 + return doselection(L, 2, Spathconf, Fpathconf, path);
979 +static const int Ksysconf[] =
981 + _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
982 + _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
986 +static void Fsysconf(lua_State *L, int i, const void *data)
988 + lua_pushinteger(L, sysconf(Ksysconf[i]));
991 +static const char *const Ssysconf[] =
993 + "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
994 + "tzname_max", "open_max", "job_control", "saved_ids", "version",
998 +static int Psysconf(lua_State *L) /** sysconf([options]) */
1000 + return doselection(L, 1, Ssysconf, Fsysconf, NULL);
1005 +static int Popenlog(lua_State *L) /** openlog(ident, [option], [facility]) */
1007 + const char *ident = luaL_checkstring(L, 1);
1009 + int facility = luaL_optint(L, 3, LOG_USER);
1010 + const char *s = luaL_optstring(L, 2, "");
1014 + case 'c': option |= LOG_CONS; break;
1015 + case 'n': option |= LOG_NDELAY; break;
1016 + case 'e': option |= LOG_PERROR; break;
1017 + case 'p': option |= LOG_PID; break;
1018 + default: badoption(L, 2, "option", *s); break;
1022 + openlog(ident, option, facility);
1027 +static int Psyslog(lua_State *L) /** syslog(priority, message) */
1029 + int priority = luaL_checkint(L, 1);
1030 + const char *msg = luaL_checkstring(L, 2);
1031 + syslog(priority, "%s", msg);
1036 +static int Pcloselog(lua_State *L) /** closelog() */
1044 + * XXX: GNU and BSD handle the forward declaration of crypt() in different
1045 + * and annoying ways (especially GNU). Declare it here just to make sure
1048 +char *crypt(const char *, const char *);
1050 +static int Pcrypt(lua_State *L)
1052 + const char *str, *salt;
1055 + str = luaL_checkstring(L, 1);
1056 + salt = luaL_checkstring(L, 2);
1057 + if (strlen(salt) < 2)
1058 + luaL_error(L, "not enough salt");
1060 + res = crypt(str, salt);
1061 + lua_pushstring(L, res);
1066 +static const luaL_reg R[] =
1068 + {"access", Paccess},
1069 + {"basename", Pbasename},
1070 + {"chdir", Pchdir},
1071 + {"chmod", Pchmod},
1072 + {"chown", Pchown},
1073 + {"crypt", Pcrypt},
1074 + {"ctermid", Pctermid},
1075 + {"dirname", Pdirname},
1078 + {"errno", Perrno},
1080 + {"execp", Pexecp},
1081 + {"fdopen", Pfdopen},
1082 + {"fileno", Pfileno},
1083 + {"files", Pfiles},
1085 + {"getcwd", Pgetcwd},
1086 + {"getenv", Pgetenv},
1087 + {"getgroup", Pgetgroup},
1088 + {"getlogin", Pgetlogin},
1089 + {"getpasswd", Pgetpasswd},
1090 + {"getpid", Pgetpid},
1092 + {"hostid", Phostid},
1095 + {"mkdir", Pmkdir},
1096 + {"mkfifo", Pmkfifo},
1097 + {"pathconf", Ppathconf},
1099 + {"readlink", Preadlink},
1100 + {"rmdir", Prmdir},
1102 + {"setenv", Psetenv},
1103 + {"setpid", Psetpid},
1104 + {"sleep", Psleep},
1106 + {"sysconf", Psysconf},
1107 + {"times", Ptimes},
1108 + {"ttyname", Pttyname},
1109 + {"unlink", Punlink},
1110 + {"umask", Pumask},
1111 + {"uname", Puname},
1112 + {"utime", Putime},
1116 + {"openlog", Popenlog},
1117 + {"syslog", Psyslog},
1118 + {"closelog", Pcloselog},
1124 +#define set_const(key, value) \
1125 + lua_pushliteral(L, key); \
1126 + lua_pushnumber(L, value); \
1127 + lua_settable(L, -3)
1129 +LUALIB_API int luaopen_posix (lua_State *L)
1131 + luaL_register(L,MYNAME,R);
1132 + lua_pushliteral(L,"version"); /** version */
1133 + lua_pushliteral(L,MYVERSION);
1134 + lua_settable(L,-3);
1137 + set_const("LOG_AUTH", LOG_AUTH);
1138 + set_const("LOG_AUTHPRIV", LOG_AUTHPRIV);
1139 + set_const("LOG_CRON", LOG_CRON);
1140 + set_const("LOG_DAEMON", LOG_DAEMON);
1141 + set_const("LOG_FTP", LOG_FTP);
1142 + set_const("LOG_KERN", LOG_KERN);
1143 + set_const("LOG_LOCAL0", LOG_LOCAL0);
1144 + set_const("LOG_LOCAL1", LOG_LOCAL1);
1145 + set_const("LOG_LOCAL2", LOG_LOCAL2);
1146 + set_const("LOG_LOCAL3", LOG_LOCAL3);
1147 + set_const("LOG_LOCAL4", LOG_LOCAL4);
1148 + set_const("LOG_LOCAL5", LOG_LOCAL5);
1149 + set_const("LOG_LOCAL6", LOG_LOCAL6);
1150 + set_const("LOG_LOCAL7", LOG_LOCAL7);
1151 + set_const("LOG_LPR", LOG_LPR);
1152 + set_const("LOG_MAIL", LOG_MAIL);
1153 + set_const("LOG_NEWS", LOG_NEWS);
1154 + set_const("LOG_SYSLOG", LOG_SYSLOG);
1155 + set_const("LOG_USER", LOG_USER);
1156 + set_const("LOG_UUCP", LOG_UUCP);
1158 + set_const("LOG_EMERG", LOG_EMERG);
1159 + set_const("LOG_ALERT", LOG_ALERT);
1160 + set_const("LOG_CRIT", LOG_CRIT);
1161 + set_const("LOG_ERR", LOG_ERR);
1162 + set_const("LOG_WARNING", LOG_WARNING);
1163 + set_const("LOG_NOTICE", LOG_NOTICE);
1164 + set_const("LOG_INFO", LOG_INFO);
1165 + set_const("LOG_DEBUG", LOG_DEBUG);
1175 @@ -39,6 +39,9 @@ LUALIB_API int (luaopen_debug) (lua_Stat
1176 #define LUA_LOADLIBNAME "package"
1177 LUALIB_API int (luaopen_package) (lua_State *L);
1179 +#define LUA_POSIXLIBNAME "posix"
1180 +LUALIB_API int (luaopen_posix) (lua_State *L);
1183 /* open all previous libraries */
1184 LUALIB_API void (luaL_openlibs) (lua_State *L);
1186 +++ b/src/modemuncher.c
1189 + Mode Muncher -- modemuncher.c
1190 + 961110 Claudio Terra
1193 + [ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
1194 + :to chew with a crunching sound: eat with relish
1195 + :to chew food with a crunching sound: eat food with relish
1198 + The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
1199 + and Webster's Collegiate Thesaurus
1202 +/* struct for rwx <-> POSIX constant lookup tables */
1209 +typedef struct modeLookup modeLookup;
1211 +static modeLookup modesel[] =
1213 + /* RWX char Posix Constant */
1225 + {0, (mode_t)-1} /* do not delete this line */
1230 +static int rwxrwxrwx(mode_t *mode, const char *p)
1233 + mode_t tmp_mode = *mode;
1235 + tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */
1236 + for (count=0; count<9; count ++)
1238 + if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits; /* set a bit */
1239 + else if (*p == '-') tmp_mode &= ~modesel[count].bits; /* clear a bit */
1240 + else if (*p=='s') switch(count)
1242 + case 2: /* turn on suid flag */
1243 + tmp_mode |= S_ISUID | S_IXUSR;
1246 + case 5: /* turn on sgid flag */
1247 + tmp_mode |= S_ISGID | S_IXGRP;
1251 + return -4; /* failed! -- bad rwxrwxrwx mode change */
1260 +static void modechopper(mode_t mode, char *p)
1262 + /* requires char p[10] */
1268 + for (count=0; count<9; count ++)
1270 + if (mode & modesel[count].bits) *p = modesel[count].rwx;
1275 + *p=0; /* to finish the string */
1277 + /* dealing with suid and sgid flags */
1278 + if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S';
1279 + if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S';
1283 +static int mode_munch(mode_t *mode, const char* p)
1287 + mode_t affected_bits, ch_mode;
1294 +modechopper(*mode, tmp);
1295 +printf("modemuncher: got base mode = %s\n", tmp);
1300 + /* step 0 -- clear temporary variables */
1304 + /* step 1 -- who's affected? */
1307 +printf("modemuncher step 1\n");
1310 + /* mode string given in rwxrwxrwx format */
1311 + if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
1313 + /* mode string given in ugoa+-=rwx format */
1318 + affected_bits |= 04700;
1322 + affected_bits |= 02070;
1326 + affected_bits |= 01007;
1330 + affected_bits |= 07777;
1333 + /* ignore spaces */
1339 + goto no_more_affected;
1343 + /* If none specified, affect all bits. */
1344 + if (affected_bits == 0) affected_bits = 07777;
1346 + /* step 2 -- how is it changed? */
1349 +printf("modemuncher step 2 (*p='%c')\n", *p);
1360 + /* ignore spaces */
1365 + return -1; /* failed! -- bad operator */
1369 + /* step 3 -- what are the changes? */
1372 +printf("modemuncher step 3\n");
1375 + for (p++ ; *p!=0 ; p++)
1391 + /* Set the setuid/gid bits if `u' or `g' is selected. */
1395 + /* ignore spaces */
1404 + /* step 4 -- apply the changes */
1407 + printf("modemuncher step 4\n");
1409 + if (*p != ',') doneFlag = 1;
1410 + if (*p != 0 && *p != ' ' && *p != ',')
1414 +printf("modemuncher: comma error!\n");
1415 +printf("modemuncher: doneflag = %u\n", doneFlag);
1417 + return -2; /* failed! -- bad mode change */
1421 + /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
1422 + if (ch_mode) switch (op)
1425 + *mode = *mode |= ch_mode & affected_bits;
1429 + *mode = *mode &= ~(ch_mode & affected_bits);
1433 + *mode = ch_mode & affected_bits;
1437 + return -3; /* failed! -- unknown error */
1441 +modechopper(*mode, tmp);
1442 +printf("modemuncher: returning mode = %s\n", tmp);
1445 + return 0; /* successful call */