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