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