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>
18 #include <sys/times.h>
19 #include <sys/types.h>
20 #include <sys/utsname.h>
27 #define MYNAME "posix"
28 #define MYVERSION MYNAME " library for " LUA_VERSION " / Nov 2003"
37 #include "modemuncher.c"
39 static const char *filetype(mode_t m
)
41 if (S_ISREG(m
)) return "regular";
42 else if (S_ISLNK(m
)) return "link";
43 else if (S_ISDIR(m
)) return "directory";
44 else if (S_ISCHR(m
)) return "character device";
45 else if (S_ISBLK(m
)) return "block device";
46 else if (S_ISFIFO(m
)) return "fifo";
47 else if (S_ISSOCK(m
)) return "socket";
51 typedef int (*Selector
)(lua_State
*L
, int i
, const void *data
);
53 static int doselection(lua_State
*L
, int i
, const char *const S
[], Selector F
, const void *data
)
58 for (i
=0; S
[i
]!=NULL
; i
++)
60 lua_pushstring(L
, S
[i
]);
68 int j
=luaL_checkoption(L
, i
, NULL
, S
);
69 if (j
==-1) luaL_argerror(L
, i
, "unknown selector");
74 static void storeindex(lua_State
*L
, int i
, const char *value
)
76 lua_pushstring(L
, value
);
77 lua_rawseti(L
, -2, i
);
80 static void storestring(lua_State
*L
, const char *name
, const char *value
)
82 lua_pushstring(L
, name
);
83 lua_pushstring(L
, value
);
87 static void storenumber(lua_State
*L
, const char *name
, lua_Number value
)
89 lua_pushstring(L
, name
);
90 lua_pushnumber(L
, value
);
94 static int pusherror(lua_State
*L
, const char *info
)
98 lua_pushstring(L
, strerror(errno
));
100 lua_pushfstring(L
, "%s: %s", info
, strerror(errno
));
101 lua_pushnumber(L
, errno
);
105 static int pushresult(lua_State
*L
, int i
, const char *info
)
109 lua_pushnumber(L
, i
);
113 return pusherror(L
, info
);
116 static void badoption(lua_State
*L
, int i
, const char *what
, int option
)
119 lua_pushfstring(L
, "unknown %s option `%c'", what
, option
));
122 static uid_t
mygetuid(lua_State
*L
, int i
)
124 if (lua_isnone(L
, i
))
126 else if (lua_isnumber(L
, i
))
127 return (uid_t
) lua_tonumber(L
, i
);
128 else if (lua_isstring(L
, i
))
130 struct passwd
*p
=getpwnam(lua_tostring(L
, i
));
131 return (p
==NULL
) ? -1 : p
->pw_uid
;
134 return luaL_typerror(L
, i
, "string or number");
137 static gid_t
mygetgid(lua_State
*L
, int i
)
139 if (lua_isnone(L
, i
))
141 else if (lua_isnumber(L
, i
))
142 return (gid_t
) lua_tonumber(L
, i
);
143 else if (lua_isstring(L
, i
))
145 struct group
*g
=getgrnam(lua_tostring(L
, i
));
146 return (g
==NULL
) ? -1 : g
->gr_gid
;
149 return luaL_typerror(L
, i
, "string or number");
154 static int Perrno(lua_State
*L
) /** errno() */
156 lua_pushstring(L
, strerror(errno
));
157 lua_pushnumber(L
, errno
);
162 static int Pdir(lua_State
*L
) /** dir([path]) */
164 const char *path
= luaL_optstring(L
, 1, ".");
165 DIR *d
= opendir(path
);
167 return pusherror(L
, path
);
171 struct dirent
*entry
;
173 for (i
=1; (entry
= readdir(d
)) != NULL
; i
++)
174 storeindex(L
, i
, entry
->d_name
);
181 static int Pglob(lua_State
*L
) /** glob(pattern) */
183 const char *pattern
= luaL_optstring(L
, 1, ".");
186 if (glob(pattern
, 0, NULL
, &globres
))
187 return pusherror(L
, pattern
);
192 for (i
=1; i
<=globres
.gl_pathc
; i
++)
193 storeindex(L
, i
, globres
.gl_pathv
[i
-1]);
200 static int aux_files(lua_State
*L
)
202 DIR *d
= lua_touserdata(L
, lua_upvalueindex(1));
203 struct dirent
*entry
;
204 if (d
== NULL
) luaL_error(L
, "attempt to use closed dir");
210 lua_replace(L
, lua_upvalueindex(1));
215 lua_pushstring(L
, entry
->d_name
);
217 #ifdef _DIRENT_HAVE_D_TYPE
218 lua_pushstring(L
, filetype(DTTOIF(entry
->d_type
)));
226 static int Pfiles(lua_State
*L
) /** files([path]) */
228 const char *path
= luaL_optstring(L
, 1, ".");
229 DIR *d
= opendir(path
);
231 return pusherror(L
, path
);
234 lua_pushlightuserdata(L
, d
);
235 lua_pushcclosure(L
, aux_files
, 1);
241 static int Pgetcwd(lua_State
*L
) /** getcwd() */
244 if (getcwd(buf
, sizeof(buf
)) == NULL
)
245 return pusherror(L
, ".");
248 lua_pushstring(L
, buf
);
254 static int Pmkdir(lua_State
*L
) /** mkdir(path) */
256 const char *path
= luaL_checkstring(L
, 1);
257 return pushresult(L
, mkdir(path
, 0777), path
);
261 static int Pchdir(lua_State
*L
) /** chdir(path) */
263 const char *path
= luaL_checkstring(L
, 1);
264 return pushresult(L
, chdir(path
), path
);
268 static int Prmdir(lua_State
*L
) /** rmdir(path) */
270 const char *path
= luaL_checkstring(L
, 1);
271 return pushresult(L
, rmdir(path
), path
);
275 static int Punlink(lua_State
*L
) /** unlink(path) */
277 const char *path
= luaL_checkstring(L
, 1);
278 return pushresult(L
, unlink(path
), path
);
282 static int Plink(lua_State
*L
) /** link(oldpath,newpath) */
284 const char *oldpath
= luaL_checkstring(L
, 1);
285 const char *newpath
= luaL_checkstring(L
, 2);
286 return pushresult(L
, link(oldpath
, newpath
), NULL
);
290 static int Psymlink(lua_State
*L
) /** symlink(oldpath,newpath) */
292 const char *oldpath
= luaL_checkstring(L
, 1);
293 const char *newpath
= luaL_checkstring(L
, 2);
294 return pushresult(L
, symlink(oldpath
, newpath
), NULL
);
298 static int Preadlink(lua_State
*L
) /** readlink(path) */
301 const char *path
= luaL_checkstring(L
, 1);
302 int n
= readlink(path
, buf
, sizeof(buf
));
303 if (n
==-1) return pusherror(L
, path
);
304 lua_pushlstring(L
, buf
, n
);
309 static int Paccess(lua_State
*L
) /** access(path,[mode]) */
312 const char *path
=luaL_checkstring(L
, 1);
314 for (s
=luaL_optstring(L
, 2, "f"); *s
!=0 ; s
++)
318 case 'r': mode
|= R_OK
; break;
319 case 'w': mode
|= W_OK
; break;
320 case 'x': mode
|= X_OK
; break;
321 case 'f': mode
|= F_OK
; break;
322 default: badoption(L
, 2, "mode", *s
); break;
324 return pushresult(L
, access(path
, mode
), path
);
328 static int Pmkfifo(lua_State
*L
) /** mkfifo(path) */
330 const char *path
= luaL_checkstring(L
, 1);
331 return pushresult(L
, mkfifo(path
, 0777), path
);
335 static int Pexec(lua_State
*L
) /** exec(path,[args]) */
337 const char *path
= luaL_checkstring(L
, 1);
338 int i
,n
=lua_gettop(L
);
339 char **argv
= malloc((n
+1)*sizeof(char*));
340 if (argv
==NULL
) luaL_error(L
,"not enough memory");
341 argv
[0] = (char*)path
;
342 for (i
=1; i
<n
; i
++) argv
[i
] = (char*)luaL_checkstring(L
, i
+1);
345 return pusherror(L
, path
);
349 static int Pfork(lua_State
*L
) /** fork() */
351 return pushresult(L
, fork(), NULL
);
355 static int Pwait(lua_State
*L
) /** wait([pid]) */
357 pid_t pid
= luaL_optint(L
, 1, -1);
358 return pushresult(L
, waitpid(pid
, NULL
, 0), NULL
);
362 static int Pkill(lua_State
*L
) /** kill(pid,[sig]) */
364 pid_t pid
= luaL_checkint(L
, 1);
365 int sig
= luaL_optint(L
, 2, SIGTERM
);
366 return pushresult(L
, kill(pid
, sig
), NULL
);
370 static int Psleep(lua_State
*L
) /** sleep(seconds) */
372 unsigned int seconds
= luaL_checkint(L
, 1);
373 lua_pushnumber(L
, sleep(seconds
));
378 static int Pputenv(lua_State
*L
) /** putenv(string) */
381 const char *s
=luaL_checklstring(L
, 1, &l
);
383 return pushresult(L
, (e
==NULL
) ? -1 : putenv(memcpy(e
,s
,l
)), s
);
388 static int Psetenv(lua_State
*L
) /** setenv(name,value,[over]) */
390 const char *name
=luaL_checkstring(L
, 1);
391 const char *value
=luaL_checkstring(L
, 2);
392 int overwrite
=lua_isnoneornil(L
, 3) || lua_toboolean(L
, 3);
393 return pushresult(L
, setenv(name
,value
,overwrite
), name
);
397 static int Punsetenv(lua_State
*L
) /** unsetenv(name) */
399 const char *name
=luaL_checkstring(L
, 1);
406 static int Pgetenv(lua_State
*L
) /** getenv([name]) */
408 if (lua_isnone(L
, 1))
410 extern char **environ
;
412 if (*environ
==NULL
) lua_pushnil(L
); else lua_newtable(L
);
413 for (e
=environ
; *e
!=NULL
; e
++)
416 char *eq
=strchr(s
, '=');
417 if (eq
==NULL
) /* will this ever happen? */
420 lua_pushboolean(L
,0);
424 lua_pushlstring(L
,s
,eq
-s
);
425 lua_pushstring(L
,eq
+1);
431 lua_pushstring(L
, getenv(luaL_checkstring(L
, 1)));
436 static int Pumask(lua_State
*L
) /** umask([mode]) */
440 umask(mode
=umask(0));
442 if (!lua_isnone(L
, 1))
444 if (mode_munch(&mode
, luaL_checkstring(L
, 1)))
452 modechopper(mode
, m
);
453 lua_pushstring(L
, m
);
458 static int Pchmod(lua_State
*L
) /** chmod(path,mode) */
462 const char *path
= luaL_checkstring(L
, 1);
463 const char *modestr
= luaL_checkstring(L
, 2);
464 if (stat(path
, &s
)) return pusherror(L
, path
);
466 if (mode_munch(&mode
, modestr
)) luaL_argerror(L
, 2, "bad mode");
467 return pushresult(L
, chmod(path
, mode
), path
);
471 static int Pchown(lua_State
*L
) /** chown(path,uid,gid) */
473 const char *path
= luaL_checkstring(L
, 1);
474 uid_t uid
= mygetuid(L
, 2);
475 gid_t gid
= mygetgid(L
, 3);
476 return pushresult(L
, chown(path
, uid
, gid
), path
);
480 static int Putime(lua_State
*L
) /** utime(path,[mtime,atime]) */
482 struct utimbuf times
;
483 time_t currtime
= time(NULL
);
484 const char *path
= luaL_checkstring(L
, 1);
485 times
.modtime
= luaL_optnumber(L
, 2, currtime
);
486 times
.actime
= luaL_optnumber(L
, 3, currtime
);
487 return pushresult(L
, utime(path
, ×
), path
);
491 static int FgetID(lua_State
*L
, int i
, const void *data
)
495 case 0: lua_pushnumber(L
, getegid()); break;
496 case 1: lua_pushnumber(L
, geteuid()); break;
497 case 2: lua_pushnumber(L
, getgid()); break;
498 case 3: lua_pushnumber(L
, getuid()); break;
499 case 4: lua_pushnumber(L
, getpgrp()); break;
500 case 5: lua_pushnumber(L
, getpid()); break;
501 case 6: lua_pushnumber(L
, getppid()); break;
506 static const char *const SgetID
[] =
508 "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
511 static int Pgetprocessid(lua_State
*L
) /** getprocessid([selector]) */
513 return doselection(L
, 1, SgetID
, FgetID
, NULL
);
517 static int Pttyname(lua_State
*L
) /** ttyname(fd) */
519 int fd
=luaL_optint(L
, 1, 0);
520 lua_pushstring(L
, ttyname(fd
));
524 static int Pctermid(lua_State
*L
) /** ctermid() */
527 lua_pushstring(L
, ctermid(b
));
532 static int Pgetlogin(lua_State
*L
) /** getlogin() */
534 lua_pushstring(L
, getlogin());
539 static int Fgetpasswd(lua_State
*L
, int i
, const void *data
)
541 const struct passwd
*p
=data
;
544 case 0: lua_pushstring(L
, p
->pw_name
); break;
545 case 1: lua_pushnumber(L
, p
->pw_uid
); break;
546 case 2: lua_pushnumber(L
, p
->pw_gid
); break;
547 case 3: lua_pushstring(L
, p
->pw_dir
); break;
548 case 4: lua_pushstring(L
, p
->pw_shell
); break;
549 /* not strictly POSIX */
550 case 5: lua_pushstring(L
, p
->pw_gecos
); break;
551 case 6: lua_pushstring(L
, p
->pw_passwd
); break;
556 static const char *const Sgetpasswd
[] =
558 "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
562 static int Pgetpasswd(lua_State
*L
) /** getpasswd(name or id) */
564 struct passwd
*p
=NULL
;
565 if (lua_isnoneornil(L
, 1))
566 p
= getpwuid(geteuid());
567 else if (lua_isnumber(L
, 1))
568 p
= getpwuid((uid_t
)lua_tonumber(L
, 1));
569 else if (lua_isstring(L
, 1))
570 p
= getpwnam(lua_tostring(L
, 1));
572 luaL_typerror(L
, 1, "string or number");
576 doselection(L
, 2, Sgetpasswd
, Fgetpasswd
, p
);
581 static int Pgetgroup(lua_State
*L
) /** getgroup(name or id) */
583 struct group
*g
=NULL
;
584 if (lua_isnumber(L
, 1))
585 g
= getgrgid((gid_t
)lua_tonumber(L
, 1));
586 else if (lua_isstring(L
, 1))
587 g
= getgrnam(lua_tostring(L
, 1));
589 luaL_typerror(L
, 1, "string or number");
596 storestring(L
, "name", g
->gr_name
);
597 storenumber(L
, "gid", g
->gr_gid
);
598 for (i
=0; g
->gr_mem
[i
] != NULL
; i
++)
599 storeindex(L
, i
+1, g
->gr_mem
[i
]);
605 static int Psetuid(lua_State
*L
) /** setuid(name or id) */
607 return pushresult(L
, setuid(mygetuid(L
, 1)), NULL
);
611 static int Psetgid(lua_State
*L
) /** setgid(name or id) */
613 return pushresult(L
, setgid(mygetgid(L
, 1)), NULL
);
622 #define pushtime(L,x) lua_pushnumber(L,((lua_Number)x)/clk_tck)
624 static int Ftimes(lua_State
*L
, int i
, const void *data
)
626 const struct mytimes
*t
=data
;
628 static clock_t clk_tck
= 0;
630 clk_tck
= (clock_t) sysconf(_SC_CLK_TCK
);
635 case 0: pushtime(L
, t
->t
.tms_utime
); break;
636 case 1: pushtime(L
, t
->t
.tms_stime
); break;
637 case 2: pushtime(L
, t
->t
.tms_cutime
); break;
638 case 3: pushtime(L
, t
->t
.tms_cstime
); break;
639 case 4: pushtime(L
, t
->elapsed
); break;
644 static const char *const Stimes
[] =
646 "utime", "stime", "cutime", "cstime", "elapsed", NULL
649 static int Ptimes(lua_State
*L
) /** times() */
652 t
.elapsed
= times(&t
.t
);
653 return doselection(L
, 1, Stimes
, Ftimes
, &t
);
664 static int Fstat(lua_State
*L
, int i
, const void *data
)
666 const struct mystat
*s
=data
;
669 case 0: lua_pushstring(L
, s
->mode
); break;
670 case 1: lua_pushnumber(L
, s
->s
.st_ino
); break;
671 case 2: lua_pushnumber(L
, s
->s
.st_dev
); break;
672 case 3: lua_pushnumber(L
, s
->s
.st_nlink
); break;
673 case 4: lua_pushnumber(L
, s
->s
.st_uid
); break;
674 case 5: lua_pushnumber(L
, s
->s
.st_gid
); break;
675 case 6: lua_pushnumber(L
, s
->s
.st_size
); break;
676 case 7: lua_pushnumber(L
, s
->s
.st_atime
); break;
677 case 8: lua_pushnumber(L
, s
->s
.st_mtime
); break;
678 case 9: lua_pushnumber(L
, s
->s
.st_ctime
); break;
679 case 10:lua_pushstring(L
, s
->type
); break;
680 case 11:lua_pushnumber(L
, s
->s
.st_mode
); break;
685 static const char *const Sstat
[] =
687 "mode", "ino", "dev", "nlink", "uid", "gid",
688 "size", "atime", "mtime", "ctime", "type", "_mode",
692 static int Pstat(lua_State
*L
) /** stat(path,[selector]) */
695 const char *path
=luaL_checkstring(L
, 1);
696 if (lstat(path
,&s
.s
)==-1) return pusherror(L
, path
);
697 s
.type
=filetype(s
.s
.st_mode
);
698 modechopper(s
.s
.st_mode
, s
.mode
);
699 return doselection(L
, 2, Sstat
, Fstat
, &s
);
703 static int Puname(lua_State
*L
) /** uname([string]) */
708 if (uname(&u
) == -1) return pusherror(L
, NULL
);
709 luaL_buffinit(L
, &b
);
710 for (s
=luaL_optstring(L
, 1, "%s %n %r %v %m"); *s
; s
++)
712 luaL_putchar(&b
, *s
);
715 case '%': luaL_putchar(&b
, *s
); break;
716 case 'm': luaL_addstring(&b
,u
.machine
); break;
717 case 'n': luaL_addstring(&b
,u
.nodename
); break;
718 case 'r': luaL_addstring(&b
,u
.release
); break;
719 case 's': luaL_addstring(&b
,u
.sysname
); break;
720 case 'v': luaL_addstring(&b
,u
.version
); break;
721 default: badoption(L
, 2, "format", *s
); break;
728 static const int Kpathconf
[] =
730 _PC_LINK_MAX
, _PC_MAX_CANON
, _PC_MAX_INPUT
, _PC_NAME_MAX
, _PC_PATH_MAX
,
731 _PC_PIPE_BUF
, _PC_CHOWN_RESTRICTED
, _PC_NO_TRUNC
, _PC_VDISABLE
,
735 static int Fpathconf(lua_State
*L
, int i
, const void *data
)
737 const char *path
=data
;
738 lua_pushnumber(L
, pathconf(path
, Kpathconf
[i
]));
742 static const char *const Spathconf
[] =
744 "link_max", "max_canon", "max_input", "name_max", "path_max",
745 "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
749 static int Ppathconf(lua_State
*L
) /** pathconf(path,[selector]) */
751 const char *path
=luaL_checkstring(L
, 1);
752 return doselection(L
, 2, Spathconf
, Fpathconf
, path
);
756 static const int Ksysconf
[] =
758 _SC_ARG_MAX
, _SC_CHILD_MAX
, _SC_CLK_TCK
, _SC_NGROUPS_MAX
, _SC_STREAM_MAX
,
759 _SC_TZNAME_MAX
, _SC_OPEN_MAX
, _SC_JOB_CONTROL
, _SC_SAVED_IDS
, _SC_VERSION
,
763 static int Fsysconf(lua_State
*L
, int i
, const void *data
)
765 lua_pushnumber(L
, sysconf(Ksysconf
[i
]));
769 static const char *const Ssysconf
[] =
771 "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
772 "tzname_max", "open_max", "job_control", "saved_ids", "version",
776 static int Psysconf(lua_State
*L
) /** sysconf([selector]) */
778 return doselection(L
, 1, Ssysconf
, Fsysconf
, NULL
);
782 static const luaL_reg R
[] =
788 {"ctermid", Pctermid
},
796 {"getgroup", Pgetgroup
},
797 {"getlogin", Pgetlogin
},
798 {"getpasswd", Pgetpasswd
},
799 {"getprocessid", Pgetprocessid
},
805 {"pathconf", Ppathconf
},
807 {"readlink", Preadlink
},
813 {"symlink", Psymlink
},
814 {"sysconf", Psysconf
},
816 {"ttyname", Pttyname
},
825 {"unsetenv", Punsetenv
},
830 LUALIB_API
int luaopen_lposix (lua_State
*L
)
832 luaL_openlib(L
, MYNAME
, R
, 0);
833 lua_pushliteral(L
,"version"); /** version */
834 lua_pushliteral(L
,MYVERSION
);