3 * POSIX library for Lua 5.0. Based on original by Claudio Terra for Lua 3.x.
4 * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
22 #include <sys/times.h>
23 #include <sys/types.h>
24 #include <sys/utsname.h>
29 #include <rpm/rpmutil.h>
31 #define MYNAME "posix"
32 #define MYVERSION MYNAME " library for " LUA_VERSION " / Nov 2003"
43 #include "modemuncher.c"
45 static int have_forked = 0;
47 static const char *filetype(mode_t m)
49 if (S_ISREG(m)) return "regular";
50 else if (S_ISLNK(m)) return "link";
51 else if (S_ISDIR(m)) return "directory";
52 else if (S_ISCHR(m)) return "character device";
53 else if (S_ISBLK(m)) return "block device";
54 else if (S_ISFIFO(m)) return "fifo";
55 else if (S_ISSOCK(m)) return "socket";
59 typedef int (*Selector)(lua_State *L, int i, const void *data);
61 /* implemented as luaL_typerror until lua 5.1, dropped in 5.2
62 * (C) 1994-2012 Lua.org, PUC-Rio. MIT license
64 static int typerror (lua_State *L, int narg, const char *tname) {
65 const char *msg = lua_pushfstring(L, "%s expected, got %s",
66 tname, luaL_typename(L, narg));
67 return luaL_argerror(L, narg, msg);
70 static int doselection(lua_State *L, int i, const char *const S[], Selector F, const void *data)
75 for (i=0; S[i]!=NULL; i++)
77 lua_pushstring(L, S[i]);
85 int j=luaL_checkoption(L, i, NULL, S);
86 if (j==-1) luaL_argerror(L, i, "unknown selector");
91 static void storeindex(lua_State *L, int i, const char *value)
93 lua_pushstring(L, value);
94 lua_rawseti(L, -2, i);
97 static void storestring(lua_State *L, const char *name, const char *value)
99 lua_pushstring(L, name);
100 lua_pushstring(L, value);
104 static void storenumber(lua_State *L, const char *name, lua_Number value)
106 lua_pushstring(L, name);
107 lua_pushnumber(L, value);
111 static int pusherror(lua_State *L, const char *info)
115 lua_pushstring(L, strerror(errno));
117 lua_pushfstring(L, "%s: %s", info, strerror(errno));
118 lua_pushnumber(L, errno);
122 static int pushresult(lua_State *L, int i, const char *info)
126 lua_pushnumber(L, i);
130 return pusherror(L, info);
133 static void badoption(lua_State *L, int i, const char *what, int option)
136 lua_pushfstring(L, "unknown %s option `%c'", what, option));
139 static uid_t mygetuid(lua_State *L, int i)
141 if (lua_isnone(L, i))
143 else if (lua_isnumber(L, i))
144 return (uid_t) lua_tonumber(L, i);
145 else if (lua_isstring(L, i))
147 struct passwd *p=getpwnam(lua_tostring(L, i));
148 return (p==NULL) ? -1 : p->pw_uid;
151 return typerror(L, i, "string or number");
154 static gid_t mygetgid(lua_State *L, int i)
156 if (lua_isnone(L, i))
158 else if (lua_isnumber(L, i))
159 return (gid_t) lua_tonumber(L, i);
160 else if (lua_isstring(L, i))
162 struct group *g=getgrnam(lua_tostring(L, i));
163 return (g==NULL) ? -1 : g->gr_gid;
166 return typerror(L, i, "string or number");
171 static int Perrno(lua_State *L) /** errno() */
173 lua_pushstring(L, strerror(errno));
174 lua_pushnumber(L, errno);
179 static int Pdir(lua_State *L) /** dir([path]) */
181 const char *path = luaL_optstring(L, 1, ".");
182 DIR *d = opendir(path);
184 return pusherror(L, path);
188 struct dirent *entry;
190 for (i=1; (entry = readdir(d)) != NULL; i++)
191 storeindex(L, i, entry->d_name);
198 static int aux_files(lua_State *L)
200 DIR *d = lua_touserdata(L, lua_upvalueindex(1));
201 struct dirent *entry;
202 if (d == NULL) return luaL_error(L, "attempt to use closed dir");
208 lua_replace(L, lua_upvalueindex(1));
213 lua_pushstring(L, entry->d_name);
215 #ifdef _DIRENT_HAVE_D_TYPE
216 lua_pushstring(L, filetype(DTTOIF(entry->d_type)));
224 static int Pfiles(lua_State *L) /** files([path]) */
226 const char *path = luaL_optstring(L, 1, ".");
227 DIR *d = opendir(path);
229 return pusherror(L, path);
232 lua_pushlightuserdata(L, d);
233 lua_pushcclosure(L, aux_files, 1);
239 static int Pgetcwd(lua_State *L) /** getcwd() */
242 if (getcwd(buf, sizeof(buf)) == NULL)
243 return pusherror(L, ".");
246 lua_pushstring(L, buf);
252 static int Pmkdir(lua_State *L) /** mkdir(path) */
254 const char *path = luaL_checkstring(L, 1);
255 return pushresult(L, mkdir(path, 0777), path);
259 static int Pchdir(lua_State *L) /** chdir(path) */
261 const char *path = luaL_checkstring(L, 1);
262 return pushresult(L, chdir(path), path);
266 static int Prmdir(lua_State *L) /** rmdir(path) */
268 const char *path = luaL_checkstring(L, 1);
269 return pushresult(L, rmdir(path), path);
273 static int Punlink(lua_State *L) /** unlink(path) */
275 const char *path = luaL_checkstring(L, 1);
276 return pushresult(L, unlink(path), path);
280 static int Plink(lua_State *L) /** link(oldpath,newpath) */
282 const char *oldpath = luaL_checkstring(L, 1);
283 const char *newpath = luaL_checkstring(L, 2);
284 return pushresult(L, link(oldpath, newpath), NULL);
288 static int Psymlink(lua_State *L) /** symlink(oldpath,newpath) */
290 const char *oldpath = luaL_checkstring(L, 1);
291 const char *newpath = luaL_checkstring(L, 2);
292 return pushresult(L, symlink(oldpath, newpath), NULL);
296 static int Preadlink(lua_State *L) /** readlink(path) */
299 const char *path = luaL_checkstring(L, 1);
300 int n = readlink(path, buf, sizeof(buf));
301 if (n==-1) return pusherror(L, path);
302 lua_pushlstring(L, buf, n);
307 static int Paccess(lua_State *L) /** access(path,[mode]) */
310 const char *path=luaL_checkstring(L, 1);
312 for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
316 case 'r': mode |= R_OK; break;
317 case 'w': mode |= W_OK; break;
318 case 'x': mode |= X_OK; break;
319 case 'f': mode |= F_OK; break;
320 default: badoption(L, 2, "mode", *s); break;
322 return pushresult(L, access(path, mode), path);
326 static int Pmkfifo(lua_State *L) /** mkfifo(path) */
328 const char *path = luaL_checkstring(L, 1);
329 return pushresult(L, mkfifo(path, 0777), path);
333 static int Pexec(lua_State *L) /** exec(path,[args]) */
335 const char *path = luaL_checkstring(L, 1);
336 int i,n=lua_gettop(L);
338 int flag, fdno, open_max;
341 return luaL_error(L, "exec not permitted in this context");
343 open_max = sysconf(_SC_OPEN_MAX);
344 if (open_max == -1) {
347 for (fdno = 3; fdno < open_max; fdno++) {
348 flag = fcntl(fdno, F_GETFD);
349 if (flag == -1 || (flag & FD_CLOEXEC))
351 fcntl(fdno, F_SETFD, FD_CLOEXEC);
354 argv = malloc((n+1)*sizeof(char*));
355 if (argv==NULL) return luaL_error(L,"not enough memory");
356 argv[0] = (char*)path;
357 for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
360 return pusherror(L, path);
364 static int Pfork(lua_State *L) /** fork() */
370 return pushresult(L, pid, NULL);
374 static int Pwait(lua_State *L) /** wait([pid]) */
376 pid_t pid = luaL_optinteger(L, 1, -1);
377 return pushresult(L, waitpid(pid, NULL, 0), NULL);
381 static int Pkill(lua_State *L) /** kill(pid,[sig]) */
383 pid_t pid = luaL_checkinteger(L, 1);
384 int sig = luaL_optinteger(L, 2, SIGTERM);
385 return pushresult(L, kill(pid, sig), NULL);
389 static int Psleep(lua_State *L) /** sleep(seconds) */
391 unsigned int seconds = luaL_checkinteger(L, 1);
392 lua_pushnumber(L, sleep(seconds));
397 static int Pputenv(lua_State *L) /** putenv(string) */
401 const char *s=luaL_checklstring(L, 1, &l);
403 return pushresult(L, (e==NULL) ? -1 : putenv(memcpy(e,s,l)), s);
410 static int Psetenv(lua_State *L) /** setenv(name,value,[over]) */
412 const char *name=luaL_checkstring(L, 1);
413 const char *value=luaL_checkstring(L, 2);
414 int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
415 return pushresult(L, setenv(name,value,overwrite), name);
419 static int Punsetenv(lua_State *L) /** unsetenv(name) */
421 const char *name=luaL_checkstring(L, 1);
426 static int Pgetenv(lua_State *L) /** getenv([name]) */
428 if (lua_isnone(L, 1))
431 #include <crt_externs.h>
432 #define environ (*_NSGetEnviron())
434 extern char **environ;
435 #endif /* __APPLE__ */
437 if (*environ==NULL) lua_pushnil(L); else lua_newtable(L);
438 for (e=environ; *e!=NULL; e++)
441 char *eq=strchr(s, '=');
442 if (eq==NULL) /* will this ever happen? */
445 lua_pushboolean(L,0);
449 lua_pushlstring(L,s,eq-s);
450 lua_pushstring(L,eq+1);
456 lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
461 static int Pumask(lua_State *L) /** umask([mode]) */
465 umask(mode=umask(0));
467 if (!lua_isnone(L, 1))
469 if (mode_munch(&mode, luaL_checkstring(L, 1)))
477 modechopper(mode, m);
478 lua_pushstring(L, m);
483 static int Pchmod(lua_State *L) /** chmod(path,mode) */
487 const char *path = luaL_checkstring(L, 1);
488 const char *modestr = luaL_checkstring(L, 2);
489 if (stat(path, &s)) return pusherror(L, path);
491 if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
492 return pushresult(L, chmod(path, mode), path);
496 static int Pchown(lua_State *L) /** chown(path,uid,gid) */
498 const char *path = luaL_checkstring(L, 1);
499 uid_t uid = mygetuid(L, 2);
500 gid_t gid = mygetgid(L, 3);
501 return pushresult(L, chown(path, uid, gid), path);
505 static int Putime(lua_State *L) /** utime(path,[mtime,atime]) */
507 struct utimbuf times;
508 time_t currtime = time(NULL);
509 const char *path = luaL_checkstring(L, 1);
510 times.modtime = luaL_optnumber(L, 2, currtime);
511 times.actime = luaL_optnumber(L, 3, currtime);
512 return pushresult(L, utime(path, ×), path);
516 static int FgetID(lua_State *L, int i, const void *data)
520 case 0: lua_pushnumber(L, getegid()); break;
521 case 1: lua_pushnumber(L, geteuid()); break;
522 case 2: lua_pushnumber(L, getgid()); break;
523 case 3: lua_pushnumber(L, getuid()); break;
524 case 4: lua_pushnumber(L, getpgrp()); break;
525 case 5: lua_pushnumber(L, getpid()); break;
526 case 6: lua_pushnumber(L, getppid()); break;
531 static const char *const SgetID[] =
533 "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
536 static int Pgetprocessid(lua_State *L) /** getprocessid([selector]) */
538 return doselection(L, 1, SgetID, FgetID, NULL);
542 static int Pttyname(lua_State *L) /** ttyname(fd) */
544 int fd=luaL_optinteger(L, 1, 0);
545 lua_pushstring(L, ttyname(fd));
549 static int Pctermid(lua_State *L) /** ctermid() */
552 lua_pushstring(L, ctermid(b));
557 static int Pgetlogin(lua_State *L) /** getlogin() */
559 lua_pushstring(L, getlogin());
564 static int Fgetpasswd(lua_State *L, int i, const void *data)
566 const struct passwd *p=data;
569 case 0: lua_pushstring(L, p->pw_name); break;
570 case 1: lua_pushnumber(L, p->pw_uid); break;
571 case 2: lua_pushnumber(L, p->pw_gid); break;
572 case 3: lua_pushstring(L, p->pw_dir); break;
573 case 4: lua_pushstring(L, p->pw_shell); break;
574 /* not strictly POSIX */
575 case 5: lua_pushstring(L, p->pw_gecos); break;
576 case 6: lua_pushstring(L, p->pw_passwd); break;
581 static const char *const Sgetpasswd[] =
583 "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
587 static int Pgetpasswd(lua_State *L) /** getpasswd(name or id) */
589 struct passwd *p=NULL;
590 if (lua_isnoneornil(L, 1))
591 p = getpwuid(geteuid());
592 else if (lua_isnumber(L, 1))
593 p = getpwuid((uid_t)lua_tonumber(L, 1));
594 else if (lua_isstring(L, 1))
595 p = getpwnam(lua_tostring(L, 1));
597 typerror(L, 1, "string or number");
601 doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
606 static int Pgetgroup(lua_State *L) /** getgroup(name or id) */
608 struct group *g=NULL;
609 if (lua_isnumber(L, 1))
610 g = getgrgid((gid_t)lua_tonumber(L, 1));
611 else if (lua_isstring(L, 1))
612 g = getgrnam(lua_tostring(L, 1));
614 typerror(L, 1, "string or number");
621 storestring(L, "name", g->gr_name);
622 storenumber(L, "gid", g->gr_gid);
623 for (i=0; g->gr_mem[i] != NULL; i++)
624 storeindex(L, i+1, g->gr_mem[i]);
630 static int Psetuid(lua_State *L) /** setuid(name or id) */
632 return pushresult(L, setuid(mygetuid(L, 1)), NULL);
636 static int Psetgid(lua_State *L) /** setgid(name or id) */
638 return pushresult(L, setgid(mygetgid(L, 1)), NULL);
647 #define pushtime(L,x) lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC)
649 static int Ftimes(lua_State *L, int i, const void *data)
651 const struct mytimes *t=data;
654 case 0: pushtime(L, t->t.tms_utime); break;
655 case 1: pushtime(L, t->t.tms_stime); break;
656 case 2: pushtime(L, t->t.tms_cutime); break;
657 case 3: pushtime(L, t->t.tms_cstime); break;
658 case 4: pushtime(L, t->elapsed); break;
663 static const char *const Stimes[] =
665 "utime", "stime", "cutime", "cstime", "elapsed", NULL
668 #define storetime(L,name,x) storenumber(L,name,(lua_Number)x/CLOCKS_PER_SEC)
670 static int Ptimes(lua_State *L) /** times() */
673 t.elapsed = times(&t.t);
674 return doselection(L, 1, Stimes, Ftimes, &t);
685 static int Fstat(lua_State *L, int i, const void *data)
687 const struct mystat *s=data;
690 case 0: lua_pushstring(L, s->mode); break;
691 case 1: lua_pushnumber(L, s->s.st_ino); break;
692 case 2: lua_pushnumber(L, s->s.st_dev); break;
693 case 3: lua_pushnumber(L, s->s.st_nlink); break;
694 case 4: lua_pushnumber(L, s->s.st_uid); break;
695 case 5: lua_pushnumber(L, s->s.st_gid); break;
696 case 6: lua_pushnumber(L, s->s.st_size); break;
697 case 7: lua_pushnumber(L, s->s.st_atime); break;
698 case 8: lua_pushnumber(L, s->s.st_mtime); break;
699 case 9: lua_pushnumber(L, s->s.st_ctime); break;
700 case 10:lua_pushstring(L, s->type); break;
701 case 11:lua_pushnumber(L, s->s.st_mode); break;
706 static const char *const Sstat[] =
708 "mode", "ino", "dev", "nlink", "uid", "gid",
709 "size", "atime", "mtime", "ctime", "type", "_mode",
713 static int Pstat(lua_State *L) /** stat(path,[selector]) */
716 const char *path=luaL_checkstring(L, 1);
717 if (lstat(path,&s.s)==-1) return pusherror(L, path);
718 s.type=filetype(s.s.st_mode);
719 modechopper(s.s.st_mode, s.mode);
720 return doselection(L, 2, Sstat, Fstat, &s);
724 static int Puname(lua_State *L) /** uname([string]) */
729 if (uname(&u) == -1) return pusherror(L, NULL);
730 luaL_buffinit(L, &b);
731 for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
733 luaL_addchar(&b, *s);
736 case '%': luaL_addchar(&b, *s); break;
737 case 'm': luaL_addstring(&b,u.machine); break;
738 case 'n': luaL_addstring(&b,u.nodename); break;
739 case 'r': luaL_addstring(&b,u.release); break;
740 case 's': luaL_addstring(&b,u.sysname); break;
741 case 'v': luaL_addstring(&b,u.version); break;
742 default: badoption(L, 2, "format", *s); break;
749 static const int Kpathconf[] =
751 _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
752 _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
756 static int Fpathconf(lua_State *L, int i, const void *data)
758 const char *path=data;
759 lua_pushnumber(L, pathconf(path, Kpathconf[i]));
763 static const char *const Spathconf[] =
765 "link_max", "max_canon", "max_input", "name_max", "path_max",
766 "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
770 static int Ppathconf(lua_State *L) /** pathconf(path,[selector]) */
772 const char *path=luaL_checkstring(L, 1);
773 return doselection(L, 2, Spathconf, Fpathconf, path);
777 static const int Ksysconf[] =
779 _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
780 _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
784 static int Fsysconf(lua_State *L, int i, const void *data)
786 lua_pushnumber(L, sysconf(Ksysconf[i]));
790 static const char *const Ssysconf[] =
792 "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
793 "tzname_max", "open_max", "job_control", "saved_ids", "version",
797 static int Psysconf(lua_State *L) /** sysconf([selector]) */
799 return doselection(L, 1, Ssysconf, Fsysconf, NULL);
802 static int Pmkstemp(lua_State *L)
809 path = luaL_checkstring(L, 1);
812 dynpath = rstrdup(path);
813 fd = mkstemp(dynpath);
814 f = (FILE**)lua_newuserdata(L, sizeof(FILE*));
820 *f = fdopen(fd, "a+");
821 lua_pushstring(L, dynpath);
823 luaL_getmetatable(L, "FILE*");
824 if (lua_isnil(L, -1)) {
826 return luaL_error(L, "FILE* metatable not available "
829 lua_setmetatable(L, -3);
834 static int Predirect2null(lua_State *L)
836 int target_fd, fd, r, e;
839 return luaL_error(L, "silence_file_descriptor not permitted in this context");
841 target_fd = luaL_checkinteger(L, 1);
843 r = fd = open("/dev/null", O_WRONLY);
844 if (fd >= 0 && fd != target_fd) {
845 r = dup2(fd, target_fd);
850 return pushresult(L, r, NULL);
853 static const luaL_Reg R[] =
859 {"ctermid", Pctermid},
867 {"getgroup", Pgetgroup},
868 {"getlogin", Pgetlogin},
869 {"getpasswd", Pgetpasswd},
870 {"getprocessid", Pgetprocessid},
875 {"mkstemp", Pmkstemp},
876 {"pathconf", Ppathconf},
878 {"readlink", Preadlink},
884 {"symlink", Psymlink},
885 {"sysconf", Psysconf},
887 {"ttyname", Pttyname},
894 {"unsetenv", Punsetenv},
895 {"redirect2null", Predirect2null},
899 LUALIB_API int luaopen_posix (lua_State *L)
901 luaL_openlib(L, MYNAME, R, 0);
902 lua_pushliteral(L,"version"); /** version */
903 lua_pushliteral(L,MYVERSION);
908 /* RPM specific overrides for Lua standard library */
910 static int exit_override(lua_State *L)
913 return luaL_error(L, "exit not permitted in this context");
915 exit(luaL_optinteger(L, 1, EXIT_SUCCESS));
918 static const luaL_Reg os_overrides[] =
920 {"exit", exit_override},
924 #ifndef lua_pushglobaltable
925 #define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
928 int luaopen_rpm_os(lua_State *L)
930 lua_pushglobaltable(L);
931 luaL_openlib(L, "os", os_overrides, 0);