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