Bug Summary

File:luaext/lposix.c
Warning:line 360, column 9
Potential leak of memory pointed to by 'argv'

Annotated Source Code

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