Remove largely unnecessary putenv() replacement
[platform/upstream/rpm.git] / luaext / lposix.c
1 /*
2 * lposix.c
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>
5 * 05 Nov 2003 22:09:10
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <dirent.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <grp.h>
16 #include <pwd.h>
17 #include <signal.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/times.h>
23 #include <sys/types.h>
24 #include <sys/utsname.h>
25 #include <sys/wait.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include <utime.h>
29 #include <rpm/rpmutil.h>
30
31 #define MYNAME          "posix"
32 #define MYVERSION       MYNAME " library for " LUA_VERSION " / Nov 2003"
33
34 #include "lua.h"
35 #include "lauxlib.h"
36 #include "lposix.h"
37
38
39 #ifndef MYBUFSIZ
40 #define MYBUFSIZ 512
41 #endif
42
43 #include "modemuncher.c"
44
45 static const char *filetype(mode_t m)
46 {
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";
54         else                    return "?";
55 }
56
57 typedef int (*Selector)(lua_State *L, int i, const void *data);
58
59 static int doselection(lua_State *L, int i, const char *const S[], Selector F, const void *data)
60 {
61         if (lua_isnone(L, i))
62         {
63                 lua_newtable(L);
64                 for (i=0; S[i]!=NULL; i++)
65                 {
66                         lua_pushstring(L, S[i]);
67                         F(L, i, data);
68                         lua_settable(L, -3);
69                 }
70                 return 1;
71         }
72         else
73         {
74                 int j=luaL_checkoption(L, i, NULL, S);
75                 if (j==-1) luaL_argerror(L, i, "unknown selector");
76                 return F(L, j, data);
77         }
78 }
79
80 static void storeindex(lua_State *L, int i, const char *value)
81 {
82         lua_pushstring(L, value);
83         lua_rawseti(L, -2, i);
84 }
85
86 static void storestring(lua_State *L, const char *name, const char *value)
87 {
88         lua_pushstring(L, name);
89         lua_pushstring(L, value);
90         lua_settable(L, -3);
91 }
92
93 static void storenumber(lua_State *L, const char *name, lua_Number value)
94 {
95         lua_pushstring(L, name);
96         lua_pushnumber(L, value);
97         lua_settable(L, -3);
98 }
99
100 static int pusherror(lua_State *L, const char *info)
101 {
102         lua_pushnil(L);
103         if (info==NULL)
104                 lua_pushstring(L, strerror(errno));
105         else
106                 lua_pushfstring(L, "%s: %s", info, strerror(errno));
107         lua_pushnumber(L, errno);
108         return 3;
109 }
110
111 static int pushresult(lua_State *L, int i, const char *info)
112 {
113         if (i != -1)
114         {
115                 lua_pushnumber(L, i);
116                 return 1;
117         }
118         else
119                 return pusherror(L, info);
120 }
121
122 static void badoption(lua_State *L, int i, const char *what, int option)
123 {
124         luaL_argerror(L, 2,
125                 lua_pushfstring(L, "unknown %s option `%c'", what, option));
126 }
127
128 static uid_t mygetuid(lua_State *L, int i)
129 {
130         if (lua_isnone(L, i))
131                 return -1;
132         else if (lua_isnumber(L, i))
133                 return (uid_t) lua_tonumber(L, i);
134         else if (lua_isstring(L, i))
135         {
136                 struct passwd *p=getpwnam(lua_tostring(L, i));
137                 return (p==NULL) ? -1 : p->pw_uid;
138         }
139         else
140                 return luaL_typerror(L, i, "string or number");
141 }
142
143 static gid_t mygetgid(lua_State *L, int i)
144 {
145         if (lua_isnone(L, i))
146                 return -1;
147         else if (lua_isnumber(L, i))
148                 return (gid_t) lua_tonumber(L, i);
149         else if (lua_isstring(L, i))
150         {
151                 struct group *g=getgrnam(lua_tostring(L, i));
152                 return (g==NULL) ? -1 : g->gr_gid;
153         }
154         else
155                 return luaL_typerror(L, i, "string or number");
156 }
157
158
159
160 static int Perrno(lua_State *L)                 /** errno() */
161 {
162         lua_pushstring(L, strerror(errno));
163         lua_pushnumber(L, errno);
164         return 2;
165 }
166
167
168 static int Pdir(lua_State *L)                   /** dir([path]) */
169 {
170         const char *path = luaL_optstring(L, 1, ".");
171         DIR *d = opendir(path);
172         if (d == NULL)
173                 return pusherror(L, path);
174         else
175         {
176                 int i;
177                 struct dirent *entry;
178                 lua_newtable(L);
179                 for (i=1; (entry = readdir(d)) != NULL; i++)
180                         storeindex(L, i, entry->d_name);
181                 closedir(d);
182                 return 1;
183         }
184 }
185
186
187 static int aux_files(lua_State *L)
188 {
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");
192         entry = readdir(d);
193         if (entry == NULL)
194         {
195                 closedir(d);
196                 lua_pushnil(L);
197                 lua_replace(L, lua_upvalueindex(1));
198                 lua_pushnil(L);
199         }
200         else
201         {
202                 lua_pushstring(L, entry->d_name);
203 #if 0
204 #ifdef _DIRENT_HAVE_D_TYPE
205                 lua_pushstring(L, filetype(DTTOIF(entry->d_type)));
206                 return 2;
207 #endif
208 #endif
209         }
210         return 1;
211 }
212
213 static int Pfiles(lua_State *L)                 /** files([path]) */
214 {
215         const char *path = luaL_optstring(L, 1, ".");
216         DIR *d = opendir(path);
217         if (d == NULL)
218                 return pusherror(L, path);
219         else
220         {
221                 lua_pushlightuserdata(L, d);
222                 lua_pushcclosure(L, aux_files, 1);
223                 return 1;
224         }
225 }
226
227
228 static int Pgetcwd(lua_State *L)                /** getcwd() */
229 {
230         char buf[MYBUFSIZ];
231         if (getcwd(buf, sizeof(buf)) == NULL)
232                 return pusherror(L, ".");
233         else
234         {
235                 lua_pushstring(L, buf);
236                 return 1;
237         }
238 }
239
240
241 static int Pmkdir(lua_State *L)                 /** mkdir(path) */
242 {
243         const char *path = luaL_checkstring(L, 1);
244         return pushresult(L, mkdir(path, 0777), path);
245 }
246
247
248 static int Pchdir(lua_State *L)                 /** chdir(path) */
249 {
250         const char *path = luaL_checkstring(L, 1);
251         return pushresult(L, chdir(path), path);
252 }
253
254
255 static int Prmdir(lua_State *L)                 /** rmdir(path) */
256 {
257         const char *path = luaL_checkstring(L, 1);
258         return pushresult(L, rmdir(path), path);
259 }
260
261
262 static int Punlink(lua_State *L)                /** unlink(path) */
263 {
264         const char *path = luaL_checkstring(L, 1);
265         return pushresult(L, unlink(path), path);
266 }
267
268
269 static int Plink(lua_State *L)                  /** link(oldpath,newpath) */
270 {
271         const char *oldpath = luaL_checkstring(L, 1);
272         const char *newpath = luaL_checkstring(L, 2);
273         return pushresult(L, link(oldpath, newpath), NULL);
274 }
275
276
277 static int Psymlink(lua_State *L)               /** symlink(oldpath,newpath) */
278 {
279         const char *oldpath = luaL_checkstring(L, 1);
280         const char *newpath = luaL_checkstring(L, 2);
281         return pushresult(L, symlink(oldpath, newpath), NULL);
282 }
283
284
285 static int Preadlink(lua_State *L)              /** readlink(path) */
286 {
287         char buf[MYBUFSIZ];
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);
292         return 1;
293 }
294
295
296 static int Paccess(lua_State *L)                /** access(path,[mode]) */
297 {
298         int mode=F_OK;
299         const char *path=luaL_checkstring(L, 1);
300         const char *s;
301         for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
302                 switch (*s)
303                 {
304                         case ' ': break;
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;
310                 }
311         return pushresult(L, access(path, mode), path);
312 }
313
314
315 static int Pmkfifo(lua_State *L)                /** mkfifo(path) */
316 {
317         const char *path = luaL_checkstring(L, 1);
318         return pushresult(L, mkfifo(path, 0777), path);
319 }
320
321
322 static int Pexec(lua_State *L)                  /** exec(path,[args]) */
323 {
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);
330         argv[i] = NULL;
331         execvp(path,argv);
332         return pusherror(L, path);
333 }
334
335
336 static int Pfork(lua_State *L)                  /** fork() */
337 {
338         return pushresult(L, fork(), NULL);
339 }
340
341
342 static int Pwait(lua_State *L)                  /** wait([pid]) */
343 {
344         pid_t pid = luaL_optint(L, 1, -1);
345         return pushresult(L, waitpid(pid, NULL, 0), NULL);
346 }
347
348
349 static int Pkill(lua_State *L)                  /** kill(pid,[sig]) */
350 {
351         pid_t pid = luaL_checkint(L, 1);
352         int sig = luaL_optint(L, 2, SIGTERM);
353         return pushresult(L, kill(pid, sig), NULL);
354 }
355
356
357 static int Psleep(lua_State *L)                 /** sleep(seconds) */
358 {
359         unsigned int seconds = luaL_checkint(L, 1);
360         lua_pushnumber(L, sleep(seconds));
361         return 1;
362 }
363
364
365 static int Pputenv(lua_State *L)                /** putenv(string) */
366 {
367 #if HAVE_PUTENV
368         size_t l;
369         const char *s=luaL_checklstring(L, 1, &l);
370         char *e=malloc(++l);
371         return pushresult(L, (e==NULL) ? -1 : putenv(memcpy(e,s,l)), s);
372 #else
373         return -1;
374 #endif
375 }
376
377
378 static int Psetenv(lua_State *L)                /** setenv(name,value,[over]) */
379 {
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);
384 }
385
386
387 static int Punsetenv(lua_State *L)              /** unsetenv(name) */
388 {
389         const char *name=luaL_checkstring(L, 1);
390         unsetenv(name);
391         return 0;
392 }
393
394 static int Pgetenv(lua_State *L)                /** getenv([name]) */
395 {
396         if (lua_isnone(L, 1))
397         {
398         #ifdef __APPLE__
399                 #include <crt_externs.h>
400                 #define environ (*_NSGetEnviron())
401         #else
402                 extern char **environ;
403         #endif /* __APPLE__ */
404                 char **e;
405                 if (*environ==NULL) lua_pushnil(L); else lua_newtable(L);
406                 for (e=environ; *e!=NULL; e++)
407                 {
408                         char *s=*e;
409                         char *eq=strchr(s, '=');
410                         if (eq==NULL)           /* will this ever happen? */
411                         {
412                                 lua_pushstring(L,s);
413                                 lua_pushboolean(L,0);
414                         }
415                         else
416                         {
417                                 lua_pushlstring(L,s,eq-s);
418                                 lua_pushstring(L,eq+1);
419                         }
420                         lua_settable(L,-3);
421                 }
422         }
423         else
424                 lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
425         return 1;
426 }
427
428
429 static int Pumask(lua_State *L)                 /** umask([mode]) */
430 {
431         char m[10];
432         mode_t mode;
433         umask(mode=umask(0));
434         mode=(~mode)&0777;
435         if (!lua_isnone(L, 1))
436         {
437                 if (mode_munch(&mode, luaL_checkstring(L, 1)))
438                 {
439                         lua_pushnil(L);
440                         return 1;
441                 }
442                 mode&=0777;
443                 umask(~mode);
444         }
445         modechopper(mode, m);
446         lua_pushstring(L, m);
447         return 1;
448 }
449
450
451 static int Pchmod(lua_State *L)                 /** chmod(path,mode) */
452 {
453         mode_t mode;
454         struct stat s;
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);
458         mode = s.st_mode;
459         if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
460         return pushresult(L, chmod(path, mode), path);
461 }
462
463
464 static int Pchown(lua_State *L)                 /** chown(path,uid,gid) */
465 {
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);
470 }
471
472
473 static int Putime(lua_State *L)                 /** utime(path,[mtime,atime]) */
474 {
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, &times), path);
481 }
482
483
484 static int FgetID(lua_State *L, int i, const void *data)
485 {
486         switch (i)
487         {
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;
495         }
496         return 1;
497 }
498
499 static const char *const SgetID[] =
500 {
501         "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
502 };
503
504 static int Pgetprocessid(lua_State *L)          /** getprocessid([selector]) */
505 {
506         return doselection(L, 1, SgetID, FgetID, NULL);
507 }
508
509
510 static int Pttyname(lua_State *L)               /** ttyname(fd) */
511 {
512         int fd=luaL_optint(L, 1, 0);
513         lua_pushstring(L, ttyname(fd));
514         return 1;
515 }
516
517 static int Pctermid(lua_State *L)               /** ctermid() */
518 {
519         char b[L_ctermid];
520         lua_pushstring(L, ctermid(b));
521         return 1;
522 }
523
524
525 static int Pgetlogin(lua_State *L)              /** getlogin() */
526 {
527         lua_pushstring(L, getlogin());
528         return 1;
529 }
530
531
532 static int Fgetpasswd(lua_State *L, int i, const void *data)
533 {
534         const struct passwd *p=data;
535         switch (i)
536         {
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;
545         }
546         return 1;
547 }
548
549 static const char *const Sgetpasswd[] =
550 {
551         "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
552 };
553
554
555 static int Pgetpasswd(lua_State *L)             /** getpasswd(name or id) */
556 {
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));
564         else
565                 luaL_typerror(L, 1, "string or number");
566         if (p==NULL)
567                 lua_pushnil(L);
568         else
569                 doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
570         return 1;
571 }
572
573
574 static int Pgetgroup(lua_State *L)              /** getgroup(name or id) */
575 {
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));
581         else
582                 luaL_typerror(L, 1, "string or number");
583         if (g==NULL)
584                 lua_pushnil(L);
585         else
586         {
587                 int i;
588                 lua_newtable(L);
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]);
593         }
594         return 1;
595 }
596
597
598 static int Psetuid(lua_State *L)                /** setuid(name or id) */
599 {
600         return pushresult(L, setuid(mygetuid(L, 1)), NULL);
601 }
602
603
604 static int Psetgid(lua_State *L)                /** setgid(name or id) */
605 {
606         return pushresult(L, setgid(mygetgid(L, 1)), NULL);
607 }
608
609 struct mytimes
610 {
611  struct tms t;
612  clock_t elapsed;
613 };
614
615 #define pushtime(L,x)           lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC)
616
617 static int Ftimes(lua_State *L, int i, const void *data)
618 {
619         const struct mytimes *t=data;
620         switch (i)
621         {
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;
627         }
628         return 1;
629 }
630
631 static const char *const Stimes[] =
632 {
633         "utime", "stime", "cutime", "cstime", "elapsed", NULL
634 };
635
636 #define storetime(L,name,x)     storenumber(L,name,(lua_Number)x/CLOCKS_PER_SEC)
637
638 static int Ptimes(lua_State *L)                 /** times() */
639 {
640         struct mytimes t;
641         t.elapsed = times(&t.t);
642         return doselection(L, 1, Stimes, Ftimes, &t);
643 }
644
645
646 struct mystat
647 {
648         struct stat s;
649         char mode[10];
650         const char *type;
651 };
652
653 static int Fstat(lua_State *L, int i, const void *data)
654 {
655         const struct mystat *s=data;
656         switch (i)
657         {
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;
670         }
671         return 1;
672 }
673
674 static const char *const Sstat[] =
675 {
676         "mode", "ino", "dev", "nlink", "uid", "gid",
677         "size", "atime", "mtime", "ctime", "type", "_mode",
678         NULL
679 };
680
681 static int Pstat(lua_State *L)                  /** stat(path,[selector]) */
682 {
683         struct mystat s;
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);
689 }
690
691
692 static int Puname(lua_State *L)                 /** uname([string]) */
693 {
694         struct utsname u;
695         luaL_Buffer b;
696         const char *s;
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++)
700                 if (*s!='%')
701                         luaL_putchar(&b, *s);
702                 else switch (*++s)
703                 {
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;
711                 }
712         luaL_pushresult(&b);
713         return 1;
714 }
715
716
717 static const int Kpathconf[] =
718 {
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,
721         -1
722 };
723
724 static int Fpathconf(lua_State *L, int i, const void *data)
725 {
726         const char *path=data;
727         lua_pushnumber(L, pathconf(path, Kpathconf[i]));
728         return 1;
729 }
730
731 static const char *const Spathconf[] =
732 {
733         "link_max", "max_canon", "max_input", "name_max", "path_max",
734         "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
735         NULL
736 };
737
738 static int Ppathconf(lua_State *L)              /** pathconf(path,[selector]) */
739 {
740         const char *path=luaL_checkstring(L, 1);
741         return doselection(L, 2, Spathconf, Fpathconf, path);
742 }
743
744
745 static const int Ksysconf[] =
746 {
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,
749         -1
750 };
751
752 static int Fsysconf(lua_State *L, int i, const void *data)
753 {
754         lua_pushnumber(L, sysconf(Ksysconf[i]));
755         return 1;
756 }
757
758 static const char *const Ssysconf[] =
759 {
760         "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
761         "tzname_max", "open_max", "job_control", "saved_ids", "version",
762         NULL
763 };
764
765 static int Psysconf(lua_State *L)               /** sysconf([selector]) */
766 {
767         return doselection(L, 1, Ssysconf, Fsysconf, NULL);
768 }
769
770 static int Pmkstemp(lua_State *L)
771 {
772         const char *path;
773         char *dynpath;
774         int fd;
775         FILE **f;
776
777         path = luaL_checkstring(L, 1);
778         if (path == NULL)
779                 return 0;
780         dynpath = rstrdup(path);
781         fd = mkstemp(dynpath);
782         f = (FILE**)lua_newuserdata(L, sizeof(FILE*));
783         if (f == NULL) {
784                 close(fd);
785                 free(dynpath);
786                 return 0;
787         }
788         *f = fdopen(fd, "a+");
789         lua_pushstring(L, dynpath);
790         free(dynpath);
791         luaL_getmetatable(L, "FILE*");
792         if (lua_isnil(L, -1)) {
793                 lua_pop(L, 1);
794                 return luaL_error(L, "FILE* metatable not available "
795                               "(io not loaded?)");
796         } else {
797                 lua_setmetatable(L, -3);
798         }
799         return 2;
800 }
801
802 static const luaL_reg R[] =
803 {
804         {"access",              Paccess},
805         {"chdir",               Pchdir},
806         {"chmod",               Pchmod},
807         {"chown",               Pchown},
808         {"ctermid",             Pctermid},
809         {"dir",                 Pdir},
810         {"errno",               Perrno},
811         {"exec",                Pexec},
812         {"files",               Pfiles},
813         {"fork",                Pfork},
814         {"getcwd",              Pgetcwd},
815         {"getenv",              Pgetenv},
816         {"getgroup",            Pgetgroup},
817         {"getlogin",            Pgetlogin},
818         {"getpasswd",           Pgetpasswd},
819         {"getprocessid",        Pgetprocessid},
820         {"kill",                Pkill},
821         {"link",                Plink},
822         {"mkdir",               Pmkdir},
823         {"mkfifo",              Pmkfifo},
824         {"mkstemp",             Pmkstemp},
825         {"pathconf",            Ppathconf},
826         {"putenv",              Pputenv},
827         {"readlink",            Preadlink},
828         {"rmdir",               Prmdir},
829         {"setgid",              Psetgid},
830         {"setuid",              Psetuid},
831         {"sleep",               Psleep},
832         {"stat",                Pstat},
833         {"symlink",             Psymlink},
834         {"sysconf",             Psysconf},
835         {"times",               Ptimes},
836         {"ttyname",             Pttyname},
837         {"umask",               Pumask},
838         {"uname",               Puname},
839         {"unlink",              Punlink},
840         {"utime",               Putime},
841         {"wait",                Pwait},
842         {"setenv",              Psetenv},
843         {"unsetenv",            Punsetenv},
844         {NULL,                  NULL}
845 };
846
847 LUALIB_API int luaopen_posix (lua_State *L)
848 {
849         luaL_openlib(L, MYNAME, R, 0);
850         lua_pushliteral(L,"version");           /** version */
851         lua_pushliteral(L,MYVERSION);
852         lua_settable(L,-3);
853         return 1;
854 }