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 const char *filetype(mode_t m)
47 if (S_ISREG(m)) return "regular";
48 else if (S_ISLNK(m)) return "link";
49 else if (S_ISDIR(m)) return "directory";
50 else if (S_ISCHR(m)) return "character device";
51 else if (S_ISBLK(m)) return "block device";
52 else if (S_ISFIFO(m)) return "fifo";
53 else if (S_ISSOCK(m)) return "socket";
57 typedef int (*Selector)(lua_State *L, int i, const void *data);
59 static int doselection(lua_State *L, int i, const char *const S[], Selector F, const void *data)
64 for (i=0; S[i]!=NULL; i++)
66 lua_pushstring(L, S[i]);
74 int j=luaL_checkoption(L, i, NULL, S);
75 if (j==-1) luaL_argerror(L, i, "unknown selector");
80 static void storeindex(lua_State *L, int i, const char *value)
82 lua_pushstring(L, value);
83 lua_rawseti(L, -2, i);
86 static void storestring(lua_State *L, const char *name, const char *value)
88 lua_pushstring(L, name);
89 lua_pushstring(L, value);
93 static void storenumber(lua_State *L, const char *name, lua_Number value)
95 lua_pushstring(L, name);
96 lua_pushnumber(L, value);
100 static int pusherror(lua_State *L, const char *info)
104 lua_pushstring(L, strerror(errno));
106 lua_pushfstring(L, "%s: %s", info, strerror(errno));
107 lua_pushnumber(L, errno);
111 static int pushresult(lua_State *L, int i, const char *info)
115 lua_pushnumber(L, i);
119 return pusherror(L, info);
122 static void badoption(lua_State *L, int i, const char *what, int option)
125 lua_pushfstring(L, "unknown %s option `%c'", what, option));
128 static uid_t mygetuid(lua_State *L, int i)
130 if (lua_isnone(L, i))
132 else if (lua_isnumber(L, i))
133 return (uid_t) lua_tonumber(L, i);
134 else if (lua_isstring(L, i))
136 struct passwd *p=getpwnam(lua_tostring(L, i));
137 return (p==NULL) ? -1 : p->pw_uid;
140 return luaL_typerror(L, i, "string or number");
143 static gid_t mygetgid(lua_State *L, int i)
145 if (lua_isnone(L, i))
147 else if (lua_isnumber(L, i))
148 return (gid_t) lua_tonumber(L, i);
149 else if (lua_isstring(L, i))
151 struct group *g=getgrnam(lua_tostring(L, i));
152 return (g==NULL) ? -1 : g->gr_gid;
155 return luaL_typerror(L, i, "string or number");
160 static int Perrno(lua_State *L) /** errno() */
162 lua_pushstring(L, strerror(errno));
163 lua_pushnumber(L, errno);
168 static int Pdir(lua_State *L) /** dir([path]) */
170 const char *path = luaL_optstring(L, 1, ".");
171 DIR *d = opendir(path);
173 return pusherror(L, path);
177 struct dirent *entry;
179 for (i=1; (entry = readdir(d)) != NULL; i++)
180 storeindex(L, i, entry->d_name);
187 static int aux_files(lua_State *L)
189 DIR *d = lua_touserdata(L, lua_upvalueindex(1));
190 struct dirent *entry;
191 if (d == NULL) return luaL_error(L, "attempt to use closed dir");
197 lua_replace(L, lua_upvalueindex(1));
202 lua_pushstring(L, entry->d_name);
204 #ifdef _DIRENT_HAVE_D_TYPE
205 lua_pushstring(L, filetype(DTTOIF(entry->d_type)));
213 static int Pfiles(lua_State *L) /** files([path]) */
215 const char *path = luaL_optstring(L, 1, ".");
216 DIR *d = opendir(path);
218 return pusherror(L, path);
221 lua_pushlightuserdata(L, d);
222 lua_pushcclosure(L, aux_files, 1);
228 static int Pgetcwd(lua_State *L) /** getcwd() */
231 if (getcwd(buf, sizeof(buf)) == NULL)
232 return pusherror(L, ".");
235 lua_pushstring(L, buf);
241 static int Pmkdir(lua_State *L) /** mkdir(path) */
243 const char *path = luaL_checkstring(L, 1);
244 return pushresult(L, mkdir(path, 0777), path);
248 static int Pchdir(lua_State *L) /** chdir(path) */
250 const char *path = luaL_checkstring(L, 1);
251 return pushresult(L, chdir(path), path);
255 static int Prmdir(lua_State *L) /** rmdir(path) */
257 const char *path = luaL_checkstring(L, 1);
258 return pushresult(L, rmdir(path), path);
262 static int Punlink(lua_State *L) /** unlink(path) */
264 const char *path = luaL_checkstring(L, 1);
265 return pushresult(L, unlink(path), path);
269 static int Plink(lua_State *L) /** link(oldpath,newpath) */
271 const char *oldpath = luaL_checkstring(L, 1);
272 const char *newpath = luaL_checkstring(L, 2);
273 return pushresult(L, link(oldpath, newpath), NULL);
277 static int Psymlink(lua_State *L) /** symlink(oldpath,newpath) */
279 const char *oldpath = luaL_checkstring(L, 1);
280 const char *newpath = luaL_checkstring(L, 2);
281 return pushresult(L, symlink(oldpath, newpath), NULL);
285 static int Preadlink(lua_State *L) /** readlink(path) */
288 const char *path = luaL_checkstring(L, 1);
289 int n = readlink(path, buf, sizeof(buf));
290 if (n==-1) return pusherror(L, path);
291 lua_pushlstring(L, buf, n);
296 static int Paccess(lua_State *L) /** access(path,[mode]) */
299 const char *path=luaL_checkstring(L, 1);
301 for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
305 case 'r': mode |= R_OK; break;
306 case 'w': mode |= W_OK; break;
307 case 'x': mode |= X_OK; break;
308 case 'f': mode |= F_OK; break;
309 default: badoption(L, 2, "mode", *s); break;
311 return pushresult(L, access(path, mode), path);
315 static int Pmkfifo(lua_State *L) /** mkfifo(path) */
317 const char *path = luaL_checkstring(L, 1);
318 return pushresult(L, mkfifo(path, 0777), path);
322 static int Pexec(lua_State *L) /** exec(path,[args]) */
324 const char *path = luaL_checkstring(L, 1);
325 int i,n=lua_gettop(L);
326 char **argv = malloc((n+1)*sizeof(char*));
327 if (argv==NULL) return luaL_error(L,"not enough memory");
328 argv[0] = (char*)path;
329 for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
332 return pusherror(L, path);
336 static int Pfork(lua_State *L) /** fork() */
338 return pushresult(L, fork(), NULL);
342 static int Pwait(lua_State *L) /** wait([pid]) */
344 pid_t pid = luaL_optint(L, 1, -1);
345 return pushresult(L, waitpid(pid, NULL, 0), NULL);
349 static int Pkill(lua_State *L) /** kill(pid,[sig]) */
351 pid_t pid = luaL_checkint(L, 1);
352 int sig = luaL_optint(L, 2, SIGTERM);
353 return pushresult(L, kill(pid, sig), NULL);
357 static int Psleep(lua_State *L) /** sleep(seconds) */
359 unsigned int seconds = luaL_checkint(L, 1);
360 lua_pushnumber(L, sleep(seconds));
365 static int Pputenv(lua_State *L) /** putenv(string) */
369 const char *s=luaL_checklstring(L, 1, &l);
371 return pushresult(L, (e==NULL) ? -1 : putenv(memcpy(e,s,l)), s);
378 static int Psetenv(lua_State *L) /** setenv(name,value,[over]) */
380 const char *name=luaL_checkstring(L, 1);
381 const char *value=luaL_checkstring(L, 2);
382 int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
383 return pushresult(L, setenv(name,value,overwrite), name);
387 static int Punsetenv(lua_State *L) /** unsetenv(name) */
389 const char *name=luaL_checkstring(L, 1);
394 static int Pgetenv(lua_State *L) /** getenv([name]) */
396 if (lua_isnone(L, 1))
399 #include <crt_externs.h>
400 #define environ (*_NSGetEnviron())
402 extern char **environ;
403 #endif /* __APPLE__ */
405 if (*environ==NULL) lua_pushnil(L); else lua_newtable(L);
406 for (e=environ; *e!=NULL; e++)
409 char *eq=strchr(s, '=');
410 if (eq==NULL) /* will this ever happen? */
413 lua_pushboolean(L,0);
417 lua_pushlstring(L,s,eq-s);
418 lua_pushstring(L,eq+1);
424 lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
429 static int Pumask(lua_State *L) /** umask([mode]) */
433 umask(mode=umask(0));
435 if (!lua_isnone(L, 1))
437 if (mode_munch(&mode, luaL_checkstring(L, 1)))
445 modechopper(mode, m);
446 lua_pushstring(L, m);
451 static int Pchmod(lua_State *L) /** chmod(path,mode) */
455 const char *path = luaL_checkstring(L, 1);
456 const char *modestr = luaL_checkstring(L, 2);
457 if (stat(path, &s)) return pusherror(L, path);
459 if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
460 return pushresult(L, chmod(path, mode), path);
464 static int Pchown(lua_State *L) /** chown(path,uid,gid) */
466 const char *path = luaL_checkstring(L, 1);
467 uid_t uid = mygetuid(L, 2);
468 gid_t gid = mygetgid(L, 3);
469 return pushresult(L, chown(path, uid, gid), path);
473 static int Putime(lua_State *L) /** utime(path,[mtime,atime]) */
475 struct utimbuf times;
476 time_t currtime = time(NULL);
477 const char *path = luaL_checkstring(L, 1);
478 times.modtime = luaL_optnumber(L, 2, currtime);
479 times.actime = luaL_optnumber(L, 3, currtime);
480 return pushresult(L, utime(path, ×), path);
484 static int FgetID(lua_State *L, int i, const void *data)
488 case 0: lua_pushnumber(L, getegid()); break;
489 case 1: lua_pushnumber(L, geteuid()); break;
490 case 2: lua_pushnumber(L, getgid()); break;
491 case 3: lua_pushnumber(L, getuid()); break;
492 case 4: lua_pushnumber(L, getpgrp()); break;
493 case 5: lua_pushnumber(L, getpid()); break;
494 case 6: lua_pushnumber(L, getppid()); break;
499 static const char *const SgetID[] =
501 "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
504 static int Pgetprocessid(lua_State *L) /** getprocessid([selector]) */
506 return doselection(L, 1, SgetID, FgetID, NULL);
510 static int Pttyname(lua_State *L) /** ttyname(fd) */
512 int fd=luaL_optint(L, 1, 0);
513 lua_pushstring(L, ttyname(fd));
517 static int Pctermid(lua_State *L) /** ctermid() */
520 lua_pushstring(L, ctermid(b));
525 static int Pgetlogin(lua_State *L) /** getlogin() */
527 lua_pushstring(L, getlogin());
532 static int Fgetpasswd(lua_State *L, int i, const void *data)
534 const struct passwd *p=data;
537 case 0: lua_pushstring(L, p->pw_name); break;
538 case 1: lua_pushnumber(L, p->pw_uid); break;
539 case 2: lua_pushnumber(L, p->pw_gid); break;
540 case 3: lua_pushstring(L, p->pw_dir); break;
541 case 4: lua_pushstring(L, p->pw_shell); break;
542 /* not strictly POSIX */
543 case 5: lua_pushstring(L, p->pw_gecos); break;
544 case 6: lua_pushstring(L, p->pw_passwd); break;
549 static const char *const Sgetpasswd[] =
551 "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
555 static int Pgetpasswd(lua_State *L) /** getpasswd(name or id) */
557 struct passwd *p=NULL;
558 if (lua_isnoneornil(L, 1))
559 p = getpwuid(geteuid());
560 else if (lua_isnumber(L, 1))
561 p = getpwuid((uid_t)lua_tonumber(L, 1));
562 else if (lua_isstring(L, 1))
563 p = getpwnam(lua_tostring(L, 1));
565 luaL_typerror(L, 1, "string or number");
569 doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
574 static int Pgetgroup(lua_State *L) /** getgroup(name or id) */
576 struct group *g=NULL;
577 if (lua_isnumber(L, 1))
578 g = getgrgid((gid_t)lua_tonumber(L, 1));
579 else if (lua_isstring(L, 1))
580 g = getgrnam(lua_tostring(L, 1));
582 luaL_typerror(L, 1, "string or number");
589 storestring(L, "name", g->gr_name);
590 storenumber(L, "gid", g->gr_gid);
591 for (i=0; g->gr_mem[i] != NULL; i++)
592 storeindex(L, i+1, g->gr_mem[i]);
598 static int Psetuid(lua_State *L) /** setuid(name or id) */
600 return pushresult(L, setuid(mygetuid(L, 1)), NULL);
604 static int Psetgid(lua_State *L) /** setgid(name or id) */
606 return pushresult(L, setgid(mygetgid(L, 1)), NULL);
615 #define pushtime(L,x) lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC)
617 static int Ftimes(lua_State *L, int i, const void *data)
619 const struct mytimes *t=data;
622 case 0: pushtime(L, t->t.tms_utime); break;
623 case 1: pushtime(L, t->t.tms_stime); break;
624 case 2: pushtime(L, t->t.tms_cutime); break;
625 case 3: pushtime(L, t->t.tms_cstime); break;
626 case 4: pushtime(L, t->elapsed); break;
631 static const char *const Stimes[] =
633 "utime", "stime", "cutime", "cstime", "elapsed", NULL
636 #define storetime(L,name,x) storenumber(L,name,(lua_Number)x/CLOCKS_PER_SEC)
638 static int Ptimes(lua_State *L) /** times() */
641 t.elapsed = times(&t.t);
642 return doselection(L, 1, Stimes, Ftimes, &t);
653 static int Fstat(lua_State *L, int i, const void *data)
655 const struct mystat *s=data;
658 case 0: lua_pushstring(L, s->mode); break;
659 case 1: lua_pushnumber(L, s->s.st_ino); break;
660 case 2: lua_pushnumber(L, s->s.st_dev); break;
661 case 3: lua_pushnumber(L, s->s.st_nlink); break;
662 case 4: lua_pushnumber(L, s->s.st_uid); break;
663 case 5: lua_pushnumber(L, s->s.st_gid); break;
664 case 6: lua_pushnumber(L, s->s.st_size); break;
665 case 7: lua_pushnumber(L, s->s.st_atime); break;
666 case 8: lua_pushnumber(L, s->s.st_mtime); break;
667 case 9: lua_pushnumber(L, s->s.st_ctime); break;
668 case 10:lua_pushstring(L, s->type); break;
669 case 11:lua_pushnumber(L, s->s.st_mode); break;
674 static const char *const Sstat[] =
676 "mode", "ino", "dev", "nlink", "uid", "gid",
677 "size", "atime", "mtime", "ctime", "type", "_mode",
681 static int Pstat(lua_State *L) /** stat(path,[selector]) */
684 const char *path=luaL_checkstring(L, 1);
685 if (lstat(path,&s.s)==-1) return pusherror(L, path);
686 s.type=filetype(s.s.st_mode);
687 modechopper(s.s.st_mode, s.mode);
688 return doselection(L, 2, Sstat, Fstat, &s);
692 static int Puname(lua_State *L) /** uname([string]) */
697 if (uname(&u) == -1) return pusherror(L, NULL);
698 luaL_buffinit(L, &b);
699 for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
701 luaL_putchar(&b, *s);
704 case '%': luaL_putchar(&b, *s); break;
705 case 'm': luaL_addstring(&b,u.machine); break;
706 case 'n': luaL_addstring(&b,u.nodename); break;
707 case 'r': luaL_addstring(&b,u.release); break;
708 case 's': luaL_addstring(&b,u.sysname); break;
709 case 'v': luaL_addstring(&b,u.version); break;
710 default: badoption(L, 2, "format", *s); break;
717 static const int Kpathconf[] =
719 _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
720 _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
724 static int Fpathconf(lua_State *L, int i, const void *data)
726 const char *path=data;
727 lua_pushnumber(L, pathconf(path, Kpathconf[i]));
731 static const char *const Spathconf[] =
733 "link_max", "max_canon", "max_input", "name_max", "path_max",
734 "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
738 static int Ppathconf(lua_State *L) /** pathconf(path,[selector]) */
740 const char *path=luaL_checkstring(L, 1);
741 return doselection(L, 2, Spathconf, Fpathconf, path);
745 static const int Ksysconf[] =
747 _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
748 _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
752 static int Fsysconf(lua_State *L, int i, const void *data)
754 lua_pushnumber(L, sysconf(Ksysconf[i]));
758 static const char *const Ssysconf[] =
760 "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
761 "tzname_max", "open_max", "job_control", "saved_ids", "version",
765 static int Psysconf(lua_State *L) /** sysconf([selector]) */
767 return doselection(L, 1, Ssysconf, Fsysconf, NULL);
770 static int Pmkstemp(lua_State *L)
777 path = luaL_checkstring(L, 1);
780 dynpath = rstrdup(path);
781 fd = mkstemp(dynpath);
782 f = (FILE**)lua_newuserdata(L, sizeof(FILE*));
788 *f = fdopen(fd, "a+");
789 lua_pushstring(L, dynpath);
791 luaL_getmetatable(L, "FILE*");
792 if (lua_isnil(L, -1)) {
794 return luaL_error(L, "FILE* metatable not available "
797 lua_setmetatable(L, -3);
802 static const luaL_reg R[] =
808 {"ctermid", Pctermid},
816 {"getgroup", Pgetgroup},
817 {"getlogin", Pgetlogin},
818 {"getpasswd", Pgetpasswd},
819 {"getprocessid", Pgetprocessid},
824 {"mkstemp", Pmkstemp},
825 {"pathconf", Ppathconf},
827 {"readlink", Preadlink},
833 {"symlink", Psymlink},
834 {"sysconf", Psysconf},
836 {"ttyname", Pttyname},
843 {"unsetenv", Punsetenv},
847 LUALIB_API int luaopen_posix (lua_State *L)
849 luaL_openlib(L, MYNAME, R, 0);
850 lua_pushliteral(L,"version"); /** version */
851 lua_pushliteral(L,MYVERSION);