73d8eb03badad4ba4a31e06f1f5cb49f7f14b724
[openwrt.git] / package / lua / patches / 400-luaposix_5.1.4-embedded.patch
1 Index: lua-5.1.4/src/Makefile
2 ===================================================================
3 --- lua-5.1.4.orig/src/Makefile 2008-09-25 12:19:44.000000000 +0200
4 +++ lua-5.1.4/src/Makefile      2008-09-25 12:20:03.000000000 +0200
5 @@ -12,7 +12,7 @@
6  AR= ar rcu
7  RANLIB= ranlib
8  RM= rm -f
9 -LIBS= -lm $(MYLIBS)
10 +LIBS= -lm -lcrypt $(MYLIBS)
11  
12  MYCFLAGS=
13  MYLDFLAGS=
14 @@ -29,7 +29,7 @@
15         lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
16         lundump.o lvm.o lzio.o lnum.o
17  LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
18 -       lstrlib.o loadlib.o linit.o
19 +       lstrlib.o loadlib.o linit.o lposix.o
20  
21  LUA_T= lua
22  LUA_O= lua.o
23 Index: lua-5.1.4/src/linit.c
24 ===================================================================
25 --- lua-5.1.4.orig/src/linit.c  2008-09-25 12:19:02.000000000 +0200
26 +++ lua-5.1.4/src/linit.c       2008-09-25 12:19:32.000000000 +0200
27 @@ -23,6 +23,7 @@
28    {LUA_STRLIBNAME, luaopen_string},
29    {LUA_MATHLIBNAME, luaopen_math},
30    {LUA_DBLIBNAME, luaopen_debug},
31 +  {LUA_POSIXLIBNAME, luaopen_posix},
32    {NULL, NULL}
33  };
34  
35 Index: lua-5.1.4/src/lposix.c
36 ===================================================================
37 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
38 +++ lua-5.1.4/src/lposix.c      2008-09-25 12:16:29.000000000 +0200
39 @@ -0,0 +1,1139 @@
40 +/*
41 +* lposix.c
42 +* POSIX library for Lua 5.1.
43 +* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
44 +* 07 Apr 2006 23:17:49
45 +* Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11 <!LR> 
46 +* Based on original by Claudio Terra for Lua 3.x.
47 +* With contributions by Roberto Ierusalimschy.
48 +*/
49 +
50 +#include <sys/stat.h>
51 +#include <sys/times.h>
52 +#include <sys/types.h>
53 +#include <sys/utsname.h>
54 +#include <sys/wait.h>
55 +
56 +#include <dirent.h>
57 +#include <errno.h>
58 +#include <fcntl.h>
59 +#include <glob.h>
60 +#include <grp.h>
61 +#include <libgen.h>
62 +#include <limits.h>
63 +#include <poll.h>
64 +#include <pwd.h>
65 +#include <signal.h>
66 +#include <stdio.h>
67 +#include <stdlib.h>
68 +#include <string.h>
69 +#include <syslog.h>
70 +#include <time.h>
71 +#include <unistd.h>
72 +#include <utime.h>
73 +
74 +#define MYNAME         "posix"
75 +#define MYVERSION      MYNAME " library for " LUA_VERSION " / Jan 2008"
76 +
77 +#ifndef ENABLE_SYSLOG
78 +#define ENABLE_SYSLOG  1
79 +#endif
80 +
81 +#include "lua.h"
82 +#include "lualib.h"
83 +#include "lauxlib.h"
84 +
85 +#include "modemuncher.c"
86 +
87 +/* compatibility with Lua 5.0 */
88 +#ifndef LUA_VERSION_NUM
89 +static int luaL_checkoption (lua_State *L, int narg, const char *def,
90 +                                 const char *const lst[]) {
91 +  const char *name = (def) ? luaL_optstring(L, narg, def) :
92 +                             luaL_checkstring(L, narg);
93 +  int i = luaL_findstring(name, lst);
94 +  if (i == -1)
95 +       luaL_argerror(L, narg, lua_pushfstring(L, "invalid option '%s'", name));
96 +  return i;
97 +}
98 +#define lua_pushinteger                        lua_pushnumber
99 +#define lua_createtable(L,a,r)         lua_newtable(L)
100 +#define LUA_FILEHANDLE                 "FILE*"
101 +
102 +#define lua_setfield(l,i,k)
103 +#define lua_getfield(l,i,k)
104 +
105 +#endif
106 +
107 +static const struct { char c; mode_t b; } M[] =
108 +{
109 +       {'r', S_IRUSR}, {'w', S_IWUSR}, {'x', S_IXUSR},
110 +       {'r', S_IRGRP}, {'w', S_IWGRP}, {'x', S_IXGRP},
111 +       {'r', S_IROTH}, {'w', S_IWOTH}, {'x', S_IXOTH},
112 +};
113 +
114 +
115 +static void pushmode(lua_State *L, mode_t mode)
116 +{
117 +       char m[9];
118 +       int i;
119 +       for (i=0; i<9; i++) m[i]= (mode & M[i].b) ? M[i].c : '-';
120 +       if (mode & S_ISUID) m[2]= (mode & S_IXUSR) ? 's' : 'S';
121 +       if (mode & S_ISGID) m[5]= (mode & S_IXGRP) ? 's' : 'S';
122 +       lua_pushlstring(L, m, 9);
123 +}
124 +
125 +typedef void (*Selector)(lua_State *L, int i, const void *data);
126 +
127 +static int doselection(lua_State *L, int i, int n, 
128 +                       const char *const S[], 
129 +                       Selector F, 
130 +                       const void *data)
131 +{
132 +       if (lua_isnone(L, i) || lua_istable(L, i))
133 +       {
134 +               int j;
135 +               if (lua_isnone(L, i)) lua_createtable(L,0,n); else lua_settop(L, i);
136 +               for (j=0; S[j]!=NULL; j++)
137 +               {
138 +                       lua_pushstring(L, S[j]);
139 +                       F(L, j, data);
140 +                       lua_settable(L, -3);
141 +               }
142 +               return 1;
143 +       }
144 +       else
145 +       {
146 +               int k,n=lua_gettop(L);
147 +               for (k=i; k<=n; k++)
148 +               {
149 +                       int j=luaL_checkoption(L, k, NULL, S);
150 +                       F(L, j, data);
151 +                       lua_replace(L, k);
152 +               }
153 +               return n-i+1;
154 +       }
155 +}
156 +#define doselection(L,i,S,F,d) (doselection)(L,i,sizeof(S)/sizeof(*S)-1,S,F,d)
157 +
158 +static int pusherror(lua_State *L, const char *info)
159 +{
160 +       lua_pushnil(L);
161 +       if (info==NULL)
162 +               lua_pushstring(L, strerror(errno));
163 +       else
164 +               lua_pushfstring(L, "%s: %s", info, strerror(errno));
165 +       lua_pushinteger(L, errno);
166 +       return 3;
167 +}
168 +
169 +static int pushresult(lua_State *L, int i, const char *info)
170 +{
171 +       if (i==-1) return pusherror(L, info);
172 +       lua_pushinteger(L, i);
173 +               return 1;
174 +}
175 +
176 +static void badoption(lua_State *L, int i, const char *what, int option)
177 +{
178 +       luaL_argerror(L, 2,
179 +               lua_pushfstring(L, "unknown %s option '%c'", what, option));
180 +}
181 +
182 +static uid_t mygetuid(lua_State *L, int i)
183 +{
184 +       if (lua_isnone(L, i))
185 +               return -1;
186 +       else if (lua_isnumber(L, i))
187 +               return (uid_t) lua_tonumber(L, i);
188 +       else if (lua_isstring(L, i))
189 +       {
190 +               struct passwd *p=getpwnam(lua_tostring(L, i));
191 +               return (p==NULL) ? -1 : p->pw_uid;
192 +       }
193 +       else
194 +               return luaL_typerror(L, i, "string or number");
195 +}
196 +
197 +static gid_t mygetgid(lua_State *L, int i)
198 +{
199 +       if (lua_isnone(L, i))
200 +               return -1;
201 +       else if (lua_isnumber(L, i))
202 +               return (gid_t) lua_tonumber(L, i);
203 +       else if (lua_isstring(L, i))
204 +       {
205 +               struct group *g=getgrnam(lua_tostring(L, i));
206 +               return (g==NULL) ? -1 : g->gr_gid;
207 +       }
208 +       else
209 +               return luaL_typerror(L, i, "string or number");
210 +}
211 +
212 +
213 +static int Perrno(lua_State *L)                        /** errno([n]) */
214 +{
215 +       int n = luaL_optint(L, 1, errno);
216 +       lua_pushstring(L, strerror(n));
217 +       lua_pushinteger(L, n);
218 +       return 2;
219 +}
220 +
221 +
222 +static int Pbasename(lua_State *L)             /** basename(path) */
223 +{
224 +       char b[PATH_MAX];
225 +       size_t len;
226 +       const char *path = luaL_checklstring(L, 1, &len);
227 +       if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
228 +       lua_pushstring(L, basename(strcpy(b,path)));
229 +       return 1;
230 +}
231 +
232 +
233 +static int Pdirname(lua_State *L)              /** dirname(path) */
234 +{
235 +       char b[PATH_MAX];
236 +       size_t len;
237 +       const char *path = luaL_checklstring(L, 1, &len);
238 +       if (len>=sizeof(b)) luaL_argerror(L, 1, "too long");
239 +       lua_pushstring(L, dirname(strcpy(b,path)));
240 +       return 1;
241 +}
242 +
243 +
244 +static int Pdir(lua_State *L)                  /** dir([path]) */
245 +{
246 +       const char *path = luaL_optstring(L, 1, ".");
247 +       DIR *d = opendir(path);
248 +       if (d == NULL)
249 +               return pusherror(L, path);
250 +       else
251 +       {
252 +               int i;
253 +               struct dirent *entry;
254 +               lua_newtable(L);
255 +               for (i=1; (entry = readdir(d)) != NULL; i++)
256 +               {
257 +                       lua_pushstring(L, entry->d_name);
258 +                       lua_rawseti(L, -2, i);
259 +               }
260 +               closedir(d);
261 +               lua_pushinteger(L, i-1);
262 +               return 2;
263 +       }
264 +}
265 +
266 +static int Pglob(lua_State *L)                  /** glob(pattern) */
267 +{
268 + const char *pattern = luaL_optstring(L, 1, "*");
269 + glob_t globres;
270 +
271 + if (glob(pattern, 0, NULL, &globres))
272 +   return pusherror(L, pattern);
273 + else
274 +   {
275 +     int i;
276 +     lua_newtable(L);
277 +     for (i=1; i<=globres.gl_pathc; i++) {
278 +       lua_pushstring(L, globres.gl_pathv[i-1]);
279 +       lua_rawseti(L, -2, i);
280 +     }
281 +     globfree(&globres);
282 +     return 1;
283 +   }
284 +}
285 +
286 +static int aux_files(lua_State *L)
287 +{
288 +       DIR **p = (DIR **)lua_touserdata(L, lua_upvalueindex(1));
289 +       DIR *d = *p;
290 +       struct dirent *entry;
291 +       if (d == NULL) return 0;
292 +       entry = readdir(d);
293 +       if (entry == NULL)
294 +       {
295 +               closedir(d);
296 +               *p=NULL;
297 +               return 0;
298 +       }
299 +       else
300 +       {
301 +               lua_pushstring(L, entry->d_name);
302 +       return 1;
303 +       }
304 +}
305 +
306 +static int dir_gc (lua_State *L)
307 +{
308 +       DIR *d = *(DIR **)lua_touserdata(L, 1);
309 +       if (d!=NULL) closedir(d);
310 +       return 0;
311 +}
312 +
313 +static int Pfiles(lua_State *L)                        /** files([path]) */
314 +{
315 +       const char *path = luaL_optstring(L, 1, ".");
316 +       DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *));
317 +       if (luaL_newmetatable(L, MYNAME " dir handle"))
318 +       {
319 +               lua_pushliteral(L, "__gc");
320 +               lua_pushcfunction(L, dir_gc);
321 +               lua_settable(L, -3);
322 +       }
323 +       lua_setmetatable(L, -2);
324 +       *d = opendir(path);
325 +       if (*d == NULL) return pusherror(L, path);
326 +               lua_pushcclosure(L, aux_files, 1);
327 +               return 1;
328 +}
329 +
330 +
331 +static int Pgetcwd(lua_State *L)               /** getcwd() */
332 +{
333 +       char b[PATH_MAX];
334 +       if (getcwd(b, sizeof(b)) == NULL) return pusherror(L, ".");
335 +       lua_pushstring(L, b);
336 +               return 1;
337 +}
338 +
339 +
340 +static int Pmkdir(lua_State *L)                        /** mkdir(path) */
341 +{
342 +       const char *path = luaL_checkstring(L, 1);
343 +       return pushresult(L, mkdir(path, 0777), path);
344 +}
345 +
346 +
347 +static int Pchdir(lua_State *L)                        /** chdir(path) */
348 +{
349 +       const char *path = luaL_checkstring(L, 1);
350 +       return pushresult(L, chdir(path), path);
351 +}
352 +
353 +static int Prmdir(lua_State *L)                        /** rmdir(path) */
354 +{
355 +       const char *path = luaL_checkstring(L, 1);
356 +       return pushresult(L, rmdir(path), path);
357 +}
358 +
359 +
360 +static int Punlink(lua_State *L)               /** unlink(path) */
361 +{
362 +       const char *path = luaL_checkstring(L, 1);
363 +       return pushresult(L, unlink(path), path);
364 +}
365 +
366 +static int Plink(lua_State *L)                 /** link(old,new,[symbolic]) */
367 +{
368 +       const char *oldpath = luaL_checkstring(L, 1);
369 +       const char *newpath = luaL_checkstring(L, 2);
370 +       return pushresult(L,
371 +               (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
372 +}
373 +
374 +
375 +static int Preadlink(lua_State *L)             /** readlink(path) */
376 +{
377 +       char b[PATH_MAX];
378 +       const char *path = luaL_checkstring(L, 1);
379 +       int n = readlink(path, b, sizeof(b));
380 +       if (n==-1) return pusherror(L, path);
381 +       lua_pushlstring(L, b, n);
382 +       return 1;
383 +}
384 +
385 +
386 +static int Paccess(lua_State *L)               /** access(path,[mode]) */
387 +{
388 +       int mode=F_OK;
389 +       const char *path=luaL_checkstring(L, 1);
390 +       const char *s;
391 +       for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++)
392 +               switch (*s)
393 +               {
394 +                       case ' ': break;
395 +                       case 'r': mode |= R_OK; break;
396 +                       case 'w': mode |= W_OK; break;
397 +                       case 'x': mode |= X_OK; break;
398 +                       case 'f': mode |= F_OK; break;
399 +                       default: badoption(L, 2, "mode", *s); break;
400 +               }
401 +       return pushresult(L, access(path, mode), path);
402 +}
403 +
404 +
405 +static int myfclose (lua_State *L) {
406 +  FILE **p = (FILE **)lua_touserdata(L, 1);
407 +  int rc = fclose(*p);
408 +  if (rc == 0) *p = NULL;
409 +  return pushresult(L, rc, NULL);
410 +} 
411 +
412 +static int pushfile (lua_State *L, int id, const char *mode) {
413 +  FILE **f = (FILE **)lua_newuserdata(L, sizeof(FILE *));
414 +  *f = NULL;
415 +  luaL_getmetatable(L, LUA_FILEHANDLE);
416 +  lua_setmetatable(L, -2);
417 +  lua_getfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
418 +  if (lua_isnil(L, -1)) {
419 +    lua_pop(L, 1);
420 +    lua_newtable(L);
421 +    lua_pushvalue(L, -1);
422 +    lua_pushcfunction(L, myfclose);
423 +    lua_setfield(L, -2, "__close");
424 +    lua_setfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE");
425 +  }
426 +  lua_setfenv(L, -2);
427 +  *f = fdopen(id, mode);
428 +  return (*f != NULL);
429 +}
430 +
431 +static int Ppipe(lua_State *L)                 /** pipe() */
432 +{
433 +       int fd[2];
434 +       if (pipe(fd)==-1) return pusherror(L, NULL);
435 +       if (!pushfile(L, fd[0], "r") || !pushfile(L, fd[1], "w"))
436 +               return pusherror(L, "pipe");
437 +       return 2;
438 +}
439 +
440 +
441 +static int Pfileno(lua_State *L)       /** fileno(filehandle) */
442 +{
443 +       FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
444 +       return pushresult(L, fileno(f), NULL);
445 +}
446 +
447 +
448 +static int Pfdopen(lua_State *L)       /** fdopen(fd, mode) */
449 +{
450 +       int fd = luaL_checkint(L, 1);
451 +       const char *mode = luaL_checkstring(L, 2);
452 +       if (!pushfile(L, fd, mode))
453 +               return pusherror(L, "fdpoen");
454 +       return 1;
455 +}
456 +
457 +
458 +/* helper func for Pdup */
459 +static const char *filemode(int fd)
460 +{
461 +       const char *m;
462 +       int mode = fcntl(fd, F_GETFL);
463 +       if (mode < 0)
464 +               return NULL;
465 +       switch (mode & O_ACCMODE) {
466 +               case O_RDONLY:  m = "r"; break;
467 +               case O_WRONLY:  m = "w"; break;
468 +               default:        m = "rw"; break;
469 +       }
470 +       return m;
471 +}
472 +
473 +static int Pdup(lua_State *L)                  /** dup(old,[new]) */
474 +{
475 +       FILE **oldf = (FILE**)luaL_checkudata(L, 1, LUA_FILEHANDLE);
476 +       FILE **newf = (FILE **)lua_touserdata(L, 2);
477 +       int fd;
478 +       const char *msg = "dup2";
479 +       fflush(*newf);
480 +       if (newf == NULL) {
481 +               fd = dup(fileno(*oldf));
482 +               msg = "dup";
483 +       } else {
484 +               fflush(*newf);
485 +               fd = dup2(fileno(*oldf), fileno(*newf));
486 +       }
487 +
488 +       if ((fd < 0) || !pushfile(L, fd, filemode(fd)))
489 +               return pusherror(L, msg);
490 +       return 1;
491 +}
492 +
493 +
494 +static int Pmkfifo(lua_State *L)               /** mkfifo(path) */
495 +{
496 +       const char *path = luaL_checkstring(L, 1);
497 +       return pushresult(L, mkfifo(path, 0777), path);
498 +}
499 +
500 +
501 +static int runexec(lua_State *L, int use_shell)
502 +{
503 +       const char *path = luaL_checkstring(L, 1);
504 +       int i,n=lua_gettop(L);
505 +       char **argv = lua_newuserdata(L,(n+1)*sizeof(char*));
506 +       argv[0] = (char*)path;
507 +       for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
508 +       argv[n] = NULL;
509 +       if (use_shell) {
510 +               execvp(path, argv);
511 +       } else {
512 +               execv(path, argv);
513 +       }
514 +       return pusherror(L, path);
515 +}
516 +
517 +
518 +static int Pexec(lua_State *L)                 /** exec(path,[args]) */
519 +{
520 +       return runexec(L, 0);
521 +}
522 +
523 +
524 +static int Pexecp(lua_State *L)                        /** execp(path,[args]) */
525 +{
526 +       return runexec(L, 1);
527 +}
528 +
529 +
530 +static int Pfork(lua_State *L)                 /** fork() */
531 +{
532 +       return pushresult(L, fork(), NULL);
533 +}
534 +
535 +/* from http://lua-users.org/lists/lua-l/2007-11/msg00346.html */
536 +static int Ppoll(lua_State *L)   /** poll(filehandle, timeout) */
537 +{
538 +       struct pollfd fds;
539 +       FILE* file = *(FILE**)luaL_checkudata(L,1,LUA_FILEHANDLE);
540 +       int timeout = luaL_checkint(L,2);
541 +       fds.fd = fileno(file);
542 +       fds.events = POLLIN;
543 +       return pushresult(L, poll(&fds,1,timeout), NULL);
544 +}
545 +
546 +static int Pwait(lua_State *L)                 /** wait([pid]) */
547 +{
548 +       int status;
549 +       pid_t pid = luaL_optint(L, 1, -1);
550 +       pid = waitpid(pid, &status, 0);
551 +       if (pid == -1) return pusherror(L, NULL);
552 +       lua_pushinteger(L, pid);
553 +       if (WIFEXITED(status))
554 +       {
555 +               lua_pushliteral(L,"exited");
556 +               lua_pushinteger(L, WEXITSTATUS(status));
557 +               return 3;
558 +       }
559 +       else if (WIFSIGNALED(status))
560 +       {
561 +               lua_pushliteral(L,"killed");
562 +               lua_pushinteger(L, WTERMSIG(status));
563 +               return 3;
564 +       }
565 +       else if (WIFSTOPPED(status))
566 +       {
567 +               lua_pushliteral(L,"stopped");
568 +               lua_pushinteger(L, WSTOPSIG(status));
569 +               return 3;
570 +       }
571 +       return 1;
572 +}
573 +
574 +
575 +static int Pkill(lua_State *L)                 /** kill(pid,[sig]) */
576 +{
577 +       pid_t pid = luaL_checkint(L, 1);
578 +       int sig = luaL_optint(L, 2, SIGTERM);
579 +       return pushresult(L, kill(pid, sig), NULL);
580 +}
581 +
582 +static int Psetpid(lua_State *L)               /** setpid(option,...) */
583 +{
584 +       const char *what=luaL_checkstring(L, 1);
585 +       switch (*what)
586 +       {
587 +               case 'U':
588 +                       return pushresult(L, seteuid(mygetuid(L, 2)), NULL);
589 +               case 'u':
590 +                       return pushresult(L, setuid(mygetuid(L, 2)), NULL);
591 +               case 'G':
592 +                       return pushresult(L, setegid(mygetgid(L, 2)), NULL);
593 +               case 'g':
594 +                       return pushresult(L, setgid(mygetgid(L, 2)), NULL);
595 +               case 's':
596 +                       return pushresult(L, setsid(), NULL);
597 +               case 'p':
598 +               {
599 +                       pid_t pid  = luaL_checkint(L, 2);
600 +                       pid_t pgid = luaL_checkint(L, 3);
601 +                       return pushresult(L, setpgid(pid,pgid), NULL);
602 +               }
603 +               default:
604 +                       badoption(L, 2, "id", *what);
605 +                       return 0;
606 +       }
607 +}
608 +
609 +
610 +static int Psleep(lua_State *L)                        /** sleep(seconds) */
611 +{
612 +       unsigned int seconds = luaL_checkint(L, 1);
613 +       lua_pushinteger(L, sleep(seconds));
614 +       return 1;
615 +}
616 +
617 +
618 +static int Psetenv(lua_State *L)               /** setenv(name,value,[over]) */
619 +{
620 +       const char *name=luaL_checkstring(L, 1);
621 +       const char *value=luaL_optstring(L, 2, NULL);
622 +       if (value==NULL)
623 +       {
624 +       unsetenv(name);
625 +               return pushresult(L, 0, NULL);
626 +       }
627 +       else
628 +       {
629 +               int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
630 +               return pushresult(L, setenv(name,value,overwrite), NULL);
631 +       }
632 +}
633 +
634 +
635 +static int Pgetenv(lua_State *L)               /** getenv([name]) */
636 +{
637 +       if (lua_isnone(L, 1))
638 +       {
639 +               extern char **environ;
640 +               char **e;
641 +               lua_newtable(L);
642 +               for (e=environ; *e!=NULL; e++)
643 +               {
644 +                       char *s=*e;
645 +                       char *eq=strchr(s, '=');
646 +                       if (eq==NULL)           /* will this ever happen? */
647 +                       {
648 +                               lua_pushstring(L,s);
649 +                               lua_pushboolean(L,1);
650 +                       }
651 +                       else
652 +                       {
653 +                               lua_pushlstring(L,s,eq-s);
654 +                               lua_pushstring(L,eq+1);
655 +                       }
656 +                       lua_settable(L,-3);
657 +               }
658 +       }
659 +       else
660 +               lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
661 +       return 1;
662 +}
663 +
664 +static int Pumask(lua_State *L)                        /** umask([mode]) */
665 +{/* <!LR> from old lposix-5.0 version */
666 +       char m[10];
667 +       mode_t mode;
668 +       umask(mode=umask(0));
669 +       mode=(~mode)&0777;
670 +       if (!lua_isnone(L, 1))
671 +       {
672 +               if (mode_munch(&mode, luaL_checkstring(L, 1)))
673 +               {
674 +                       lua_pushnil(L);
675 +                       return 1;
676 +               }
677 +               mode&=0777;
678 +               umask(~mode);
679 +       }
680 +       modechopper(mode, m);
681 +       lua_pushstring(L, m);
682 +       return 1;
683 +}
684 +
685 +
686 +static int Pchmod(lua_State *L)                        /** chmod(path,mode) */
687 +{
688 +       mode_t mode;
689 +       struct stat s;
690 +       const char *path = luaL_checkstring(L, 1);
691 +       const char *modestr = luaL_checkstring(L, 2);
692 +       if (stat(path, &s)) return pusherror(L, path);
693 +       mode = s.st_mode;
694 +       if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
695 +       return pushresult(L, chmod(path, mode), path);
696 +}
697 +
698 +
699 +static int Pchown(lua_State *L)                        /** chown(path,uid,gid) */
700 +{
701 +       const char *path = luaL_checkstring(L, 1);
702 +       uid_t uid = mygetuid(L, 2);
703 +       gid_t gid = mygetgid(L, 3);
704 +       return pushresult(L, chown(path, uid, gid), path);
705 +}
706 +
707 +
708 +static int Putime(lua_State *L)                        /** utime(path,[mtime,atime]) */
709 +{
710 +       struct utimbuf times;
711 +       time_t currtime = time(NULL);
712 +       const char *path = luaL_checkstring(L, 1);
713 +       times.modtime = luaL_optnumber(L, 2, currtime);
714 +       times.actime  = luaL_optnumber(L, 3, currtime);
715 +       return pushresult(L, utime(path, &times), path);
716 +}
717 +
718 +
719 +static void FgetID(lua_State *L, int i, const void *data)
720 +{
721 +       switch (i)
722 +       {
723 +               case 0: lua_pushinteger(L, getegid());  break;
724 +               case 1: lua_pushinteger(L, geteuid());  break;
725 +               case 2: lua_pushinteger(L, getgid());   break;
726 +               case 3: lua_pushinteger(L, getuid());   break;
727 +               case 4: lua_pushinteger(L, getpgrp());  break;
728 +               case 5: lua_pushinteger(L, getpid());   break;
729 +               case 6: lua_pushinteger(L, getppid());  break;
730 +       }
731 +}
732 +
733 +static const char *const SgetID[] =
734 +{
735 +       "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
736 +};
737 +
738 +static int Pgetpid(lua_State *L)               /** getpid([options]) */
739 +{
740 +       return doselection(L, 1, SgetID, FgetID, NULL);
741 +}
742 +
743 +
744 +static int Phostid(lua_State *L)               /** hostid() */
745 +{
746 +       char b[32];
747 +       sprintf(b,"%ld",gethostid());
748 +       lua_pushstring(L, b);
749 +       return 1;
750 +}
751 +
752 +
753 +static int Pttyname(lua_State *L)              /** ttyname([fd]) */
754 +{
755 +       int fd=luaL_optint(L, 1, 0);
756 +       lua_pushstring(L, ttyname(fd));
757 +       return 1;
758 +}
759 +
760 +
761 +static int Pctermid(lua_State *L)              /** ctermid() */
762 +{
763 +       char b[L_ctermid];
764 +       lua_pushstring(L, ctermid(b));
765 +       return 1;
766 +}
767 +
768 +
769 +static int Pgetlogin(lua_State *L)             /** getlogin() */
770 +{
771 +       lua_pushstring(L, getlogin());
772 +       return 1;
773 +}
774 +
775 +
776 +static void Fgetpasswd(lua_State *L, int i, const void *data)
777 +{
778 +       const struct passwd *p=data;
779 +       switch (i)
780 +       {
781 +               case 0: lua_pushstring(L, p->pw_name); break;
782 +               case 1: lua_pushinteger(L, p->pw_uid); break;
783 +               case 2: lua_pushinteger(L, p->pw_gid); break;
784 +               case 3: lua_pushstring(L, p->pw_dir); break;
785 +               case 4: lua_pushstring(L, p->pw_shell); break;
786 +/* not strictly POSIX */
787 +               case 5: lua_pushstring(L, p->pw_gecos); break;
788 +               case 6: lua_pushstring(L, p->pw_passwd); break;
789 +       }
790 +}
791 +
792 +static const char *const Sgetpasswd[] =
793 +{
794 +       "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
795 +};
796 +
797 +
798 +static int Pgetpasswd(lua_State *L)            /** getpasswd(name|id,[sel]) */
799 +{
800 +       struct passwd *p=NULL;
801 +       if (lua_isnoneornil(L, 1))
802 +               p = getpwuid(geteuid());
803 +       else if (lua_isnumber(L, 1))
804 +               p = getpwuid((uid_t)lua_tonumber(L, 1));
805 +       else if (lua_isstring(L, 1))
806 +               p = getpwnam(lua_tostring(L, 1));
807 +       else
808 +               luaL_typerror(L, 1, "string or number");
809 +       if (p==NULL)
810 +               lua_pushnil(L);
811 +       else
812 +               return doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
813 +       return 1;
814 +}
815 +
816 +
817 +static int Pgetgroup(lua_State *L)             /** getgroup(name|id) */
818 +{
819 +       struct group *g=NULL;
820 +       if (lua_isnumber(L, 1))
821 +               g = getgrgid((gid_t)lua_tonumber(L, 1));
822 +       else if (lua_isstring(L, 1))
823 +               g = getgrnam(lua_tostring(L, 1));
824 +       else
825 +               luaL_typerror(L, 1, "string or number");
826 +       if (g==NULL)
827 +               lua_pushnil(L);
828 +       else
829 +       {
830 +               int i;
831 +               lua_newtable(L);
832 +               lua_pushliteral(L, "name");
833 +               lua_pushstring(L, g->gr_name);
834 +               lua_settable(L, -3);
835 +               lua_pushliteral(L, "gid");
836 +               lua_pushinteger(L, g->gr_gid);
837 +               lua_settable(L, -3);
838 +               for (i=0; g->gr_mem[i]!=NULL; i++)
839 +               {
840 +                       lua_pushstring(L, g->gr_mem[i]);
841 +                       lua_rawseti(L, -2, i);
842 +               }
843 +       }
844 +       return 1;
845 +}
846 +
847 +
848 +struct mytimes
849 +{
850 + struct tms t;
851 + clock_t elapsed;
852 +};
853 +
854 +/* #define pushtime(L,x)       lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC) */
855 +#define pushtime(L,x)  lua_pushnumber(L, ((lua_Number)x)/clk_tck)
856 +
857 +static void Ftimes(lua_State *L, int i, const void *data)
858 +{
859 +    static long clk_tck = 0; 
860 +       const struct mytimes *t=data;
861 +
862 +    if( !clk_tck){ clk_tck= sysconf(_SC_CLK_TCK);}
863 +       switch (i)
864 +       {
865 +               case 0: pushtime(L, t->t.tms_utime); break;
866 +               case 1: pushtime(L, t->t.tms_stime); break;
867 +               case 2: pushtime(L, t->t.tms_cutime); break;
868 +               case 3: pushtime(L, t->t.tms_cstime); break;
869 +               case 4: pushtime(L, t->elapsed); break;
870 +       }
871 +}
872 +
873 +static const char *const Stimes[] =
874 +{
875 +       "utime", "stime", "cutime", "cstime", "elapsed", NULL
876 +};
877 +
878 +static int Ptimes(lua_State *L)                        /** times([options]) */
879 +{
880 +       struct mytimes t;
881 +       t.elapsed = times(&t.t);
882 +       return doselection(L, 1, Stimes, Ftimes, &t);
883 +}
884 +
885 +
886 +static const char *filetype(mode_t m)
887 +{
888 +       if (S_ISREG(m))         return "regular";
889 +       else if (S_ISLNK(m))    return "link";
890 +       else if (S_ISDIR(m))    return "directory";
891 +       else if (S_ISCHR(m))    return "character device";
892 +       else if (S_ISBLK(m))    return "block device";
893 +       else if (S_ISFIFO(m))   return "fifo";
894 +       else if (S_ISSOCK(m))   return "socket";
895 +       else                    return "?";
896 +}
897 +
898 +static void Fstat(lua_State *L, int i, const void *data)
899 +{
900 +       const struct stat *s=data;
901 +       switch (i)
902 +       {
903 +               case 0: pushmode(L, s->st_mode); break;
904 +               case 1: lua_pushinteger(L, s->st_ino); break;
905 +               case 2: lua_pushinteger(L, s->st_dev); break;
906 +               case 3: lua_pushinteger(L, s->st_nlink); break;
907 +               case 4: lua_pushinteger(L, s->st_uid); break;
908 +               case 5: lua_pushinteger(L, s->st_gid); break;
909 +               case 6: lua_pushinteger(L, s->st_size); break;
910 +               case 7: lua_pushinteger(L, s->st_atime); break;
911 +               case 8: lua_pushinteger(L, s->st_mtime); break;
912 +               case 9: lua_pushinteger(L, s->st_ctime); break;
913 +               case 10:lua_pushstring(L, filetype(s->st_mode)); break;
914 +       }
915 +}
916 +
917 +static const char *const Sstat[] =
918 +{
919 +       "mode", "ino", "dev", "nlink", "uid", "gid",
920 +       "size", "atime", "mtime", "ctime", "type",
921 +       NULL
922 +};
923 +
924 +static int Pstat(lua_State *L)                 /** stat(path,[options]) */
925 +{
926 +       struct stat s;
927 +       const char *path=luaL_checkstring(L, 1);
928 +       if (lstat(path,&s)==-1) return pusherror(L, path);
929 +       return doselection(L, 2, Sstat, Fstat, &s);
930 +}
931 +
932 +
933 +static int Puname(lua_State *L)                        /** uname([string]) */
934 +{
935 +       struct utsname u;
936 +       luaL_Buffer b;
937 +       const char *s;
938 +       if (uname(&u)==-1) return pusherror(L, NULL);
939 +       luaL_buffinit(L, &b);
940 +       for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
941 +               if (*s!='%')
942 +                       luaL_putchar(&b, *s);
943 +               else switch (*++s)
944 +               {
945 +                       case '%': luaL_putchar(&b, *s); break;
946 +                       case 'm': luaL_addstring(&b,u.machine); break;
947 +                       case 'n': luaL_addstring(&b,u.nodename); break;
948 +                       case 'r': luaL_addstring(&b,u.release); break;
949 +                       case 's': luaL_addstring(&b,u.sysname); break;
950 +                       case 'v': luaL_addstring(&b,u.version); break;
951 +                       default: badoption(L, 2, "format", *s); break;
952 +               }
953 +       luaL_pushresult(&b);
954 +       return 1;
955 +}
956 +
957 +
958 +static const int Kpathconf[] =
959 +{
960 +       _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
961 +       _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
962 +       -1
963 +};
964 +
965 +static void Fpathconf(lua_State *L, int i, const void *data)
966 +{
967 +       const char *path=data;
968 +       lua_pushinteger(L, pathconf(path, Kpathconf[i]));
969 +}
970 +
971 +static const char *const Spathconf[] =
972 +{
973 +       "link_max", "max_canon", "max_input", "name_max", "path_max",
974 +       "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
975 +       NULL
976 +};
977 +
978 +static int Ppathconf(lua_State *L)             /** pathconf([path,options]) */
979 +{
980 +       const char *path = luaL_optstring(L, 1, ".");
981 +       return doselection(L, 2, Spathconf, Fpathconf, path);
982 +}
983 +
984 +
985 +static const int Ksysconf[] =
986 +{
987 +       _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
988 +       _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
989 +       -1
990 +};
991 +
992 +static void Fsysconf(lua_State *L, int i, const void *data)
993 +{
994 +       lua_pushinteger(L, sysconf(Ksysconf[i]));
995 +}
996 +
997 +static const char *const Ssysconf[] =
998 +{
999 +       "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
1000 +       "tzname_max", "open_max", "job_control", "saved_ids", "version",
1001 +       NULL
1002 +};
1003 +
1004 +static int Psysconf(lua_State *L)              /** sysconf([options]) */
1005 +{
1006 +       return doselection(L, 1, Ssysconf, Fsysconf, NULL);
1007 +}
1008 +
1009 +#if ENABLE_SYSLOG
1010 +/* syslog funcs */
1011 +static int Popenlog(lua_State *L)      /** openlog(ident, [option], [facility]) */
1012 +{
1013 +       const char *ident = luaL_checkstring(L, 1);
1014 +       int option = 0;
1015 +       int facility = luaL_optint(L, 3, LOG_USER);
1016 +       const char *s = luaL_optstring(L, 2, "");
1017 +       while (*s) {
1018 +               switch (*s) {
1019 +                       case ' ': break;
1020 +                       case 'c': option |= LOG_CONS; break;
1021 +                       case 'n': option |= LOG_NDELAY; break;
1022 +                       case 'e': option |= LOG_PERROR; break;
1023 +                       case 'p': option |= LOG_PID; break;
1024 +                       default: badoption(L, 2, "option", *s); break;
1025 +               }
1026 +               s++;
1027 +       }
1028 +       openlog(ident, option, facility);
1029 +       return 0;
1030 +}
1031 +
1032 +
1033 +static int Psyslog(lua_State *L)               /** syslog(priority, message) */
1034 +{
1035 +       int priority = luaL_checkint(L, 1);
1036 +       const char *msg = luaL_checkstring(L, 2);
1037 +       syslog(priority, "%s", msg);
1038 +       return 0;
1039 +}
1040 +
1041 +
1042 +static int Pcloselog(lua_State *L)             /** closelog() */
1043 +{
1044 +       closelog();
1045 +       return 0;
1046 +}
1047 +#endif
1048 +
1049 +/*
1050 + * XXX: GNU and BSD handle the forward declaration of crypt() in different
1051 + * and annoying ways (especially GNU). Declare it here just to make sure
1052 + * that it's there
1053 + */
1054 +char *crypt(const char *, const char *);
1055 +
1056 +static int Pcrypt(lua_State *L)
1057 +{
1058 +       const char *str, *salt;
1059 +       char *res;
1060 +
1061 +       str = luaL_checkstring(L, 1);
1062 +       salt = luaL_checkstring(L, 2);
1063 +       if (strlen(salt) < 2)
1064 +               luaL_error(L, "not enough salt");
1065 +
1066 +       res = crypt(str, salt);
1067 +       lua_pushstring(L, res);
1068 +
1069 +       return 1;
1070 +}
1071 +
1072 +static const luaL_reg R[] =
1073 +{
1074 +       {"access",              Paccess},
1075 +       {"basename",            Pbasename},
1076 +       {"chdir",               Pchdir},
1077 +       {"chmod",               Pchmod},
1078 +       {"chown",               Pchown},
1079 +       {"crypt",               Pcrypt},
1080 +       {"ctermid",             Pctermid},
1081 +       {"dirname",             Pdirname},
1082 +       {"dir",                 Pdir},
1083 +       {"dup",                 Pdup},
1084 +       {"errno",               Perrno},
1085 +       {"exec",                Pexec},
1086 +       {"execp",               Pexecp},
1087 +       {"fdopen",              Pfdopen},
1088 +       {"fileno",              Pfileno},
1089 +       {"files",               Pfiles},
1090 +       {"fork",                Pfork},
1091 +       {"getcwd",              Pgetcwd},
1092 +       {"getenv",              Pgetenv},
1093 +       {"getgroup",            Pgetgroup},
1094 +       {"getlogin",            Pgetlogin},
1095 +       {"getpasswd",           Pgetpasswd},
1096 +       {"getpid",              Pgetpid},
1097 +       {"glob",                Pglob},
1098 +       {"hostid",              Phostid},
1099 +       {"kill",                Pkill},
1100 +       {"link",                Plink},
1101 +       {"mkdir",               Pmkdir},
1102 +       {"mkfifo",              Pmkfifo},
1103 +       {"pathconf",            Ppathconf},
1104 +       {"pipe",                Ppipe},
1105 +       {"readlink",            Preadlink},
1106 +       {"rmdir",               Prmdir},
1107 +       {"rpoll",               Ppoll},
1108 +       {"setenv",              Psetenv},
1109 +       {"setpid",              Psetpid},
1110 +       {"sleep",               Psleep},
1111 +       {"stat",                Pstat},
1112 +       {"sysconf",             Psysconf},
1113 +       {"times",               Ptimes},
1114 +       {"ttyname",             Pttyname},
1115 +       {"unlink",              Punlink},
1116 +       {"umask",               Pumask},
1117 +       {"uname",               Puname},
1118 +       {"utime",               Putime},
1119 +       {"wait",                Pwait},
1120 +
1121 +#if ENABLE_SYSLOG
1122 +       {"openlog",             Popenlog},
1123 +       {"syslog",              Psyslog},
1124 +       {"closelog",            Pcloselog},
1125 +#endif
1126 +
1127 +       {NULL,                  NULL}
1128 +};
1129 +
1130 +#define set_const(key, value)          \
1131 +       lua_pushliteral(L, key);        \
1132 +       lua_pushnumber(L, value);       \
1133 +       lua_settable(L, -3)
1134 +
1135 +LUALIB_API int luaopen_posix (lua_State *L)
1136 +{
1137 +       luaL_register(L,MYNAME,R);
1138 +       lua_pushliteral(L,"version");           /** version */
1139 +       lua_pushliteral(L,MYVERSION);
1140 +       lua_settable(L,-3);
1141 +
1142 +#if ENABLE_SYSLOG
1143 +       set_const("LOG_AUTH", LOG_AUTH);
1144 +       set_const("LOG_AUTHPRIV", LOG_AUTHPRIV);
1145 +       set_const("LOG_CRON", LOG_CRON);
1146 +       set_const("LOG_DAEMON", LOG_DAEMON);
1147 +       set_const("LOG_FTP", LOG_FTP);
1148 +       set_const("LOG_KERN", LOG_KERN);
1149 +       set_const("LOG_LOCAL0", LOG_LOCAL0);
1150 +       set_const("LOG_LOCAL1", LOG_LOCAL1);
1151 +       set_const("LOG_LOCAL2", LOG_LOCAL2);
1152 +       set_const("LOG_LOCAL3", LOG_LOCAL3);
1153 +       set_const("LOG_LOCAL4", LOG_LOCAL4);
1154 +       set_const("LOG_LOCAL5", LOG_LOCAL5);
1155 +       set_const("LOG_LOCAL6", LOG_LOCAL6);
1156 +       set_const("LOG_LOCAL7", LOG_LOCAL7);
1157 +       set_const("LOG_LPR", LOG_LPR);
1158 +       set_const("LOG_MAIL", LOG_MAIL);
1159 +       set_const("LOG_NEWS", LOG_NEWS);
1160 +       set_const("LOG_SYSLOG", LOG_SYSLOG);
1161 +       set_const("LOG_USER", LOG_USER);
1162 +       set_const("LOG_UUCP", LOG_UUCP);
1163 +
1164 +       set_const("LOG_EMERG", LOG_EMERG);
1165 +       set_const("LOG_ALERT", LOG_ALERT);
1166 +       set_const("LOG_CRIT", LOG_CRIT);
1167 +       set_const("LOG_ERR", LOG_ERR);
1168 +       set_const("LOG_WARNING", LOG_WARNING);
1169 +       set_const("LOG_NOTICE", LOG_NOTICE);
1170 +       set_const("LOG_INFO", LOG_INFO);
1171 +       set_const("LOG_DEBUG", LOG_DEBUG);
1172 +#endif
1173 +
1174 +
1175 +       return 1;
1176 +}
1177 +
1178 +/*EOF*/
1179 Index: lua-5.1.4/src/lualib.h
1180 ===================================================================
1181 --- lua-5.1.4.orig/src/lualib.h 2008-09-25 12:18:14.000000000 +0200
1182 +++ lua-5.1.4/src/lualib.h      2008-09-25 12:18:53.000000000 +0200
1183 @@ -39,6 +39,9 @@
1184  #define LUA_LOADLIBNAME        "package"
1185  LUALIB_API int (luaopen_package) (lua_State *L);
1186  
1187 +#define LUA_POSIXLIBNAME "posix"
1188 +LUALIB_API int (luaopen_posix) (lua_State *L);
1189 +
1190  
1191  /* open all previous libraries */
1192  LUALIB_API void (luaL_openlibs) (lua_State *L); 
1193 Index: lua-5.1.4/src/modemuncher.c
1194 ===================================================================
1195 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1196 +++ lua-5.1.4/src/modemuncher.c 2008-09-25 12:16:29.000000000 +0200
1197 @@ -0,0 +1,261 @@
1198 +/* 
1199 +       Mode Muncher -- modemuncher.c
1200 +       961110 Claudio Terra
1201 +
1202 +       munch vb
1203 +       [ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
1204 +       :to chew with a crunching sound: eat with relish
1205 +       :to chew food with a crunching sound: eat food with relish
1206 +       --munch-er n
1207 +               
1208 +       The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
1209 +       and Webster's Collegiate Thesaurus
1210 +*/
1211 +
1212 +/* struct for rwx <-> POSIX constant lookup tables */
1213 +struct modeLookup
1214 +{
1215 +       char rwx;
1216 +       mode_t bits;
1217 +};
1218 +
1219 +typedef struct modeLookup modeLookup;
1220 +
1221 +static modeLookup modesel[] =
1222 +{
1223 +       /* RWX char                             Posix Constant */
1224 +       {'r',                                   S_IRUSR},
1225 +       {'w',                                   S_IWUSR},
1226 +       {'x',                                   S_IXUSR},
1227 +       
1228 +       {'r',                                   S_IRGRP},
1229 +       {'w',                                   S_IWGRP},
1230 +       {'x',                                   S_IXGRP},
1231 +       
1232 +       {'r',                                   S_IROTH},
1233 +       {'w',                                   S_IWOTH},
1234 +       {'x',                                   S_IXOTH},
1235 +       {0,                                     (mode_t)-1} /* do not delete this line */
1236 +};
1237 +
1238 +
1239 +
1240 +static int rwxrwxrwx(mode_t *mode, const char *p)
1241 +{
1242 +       int count;
1243 +       mode_t tmp_mode = *mode;
1244 +       
1245 +       tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */
1246 +       for (count=0; count<9; count ++)
1247 +       {
1248 +               if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits;  /* set a bit */
1249 +               else if (*p == '-') tmp_mode &= ~modesel[count].bits;                   /* clear a bit */
1250 +               else if (*p=='s') switch(count)
1251 +               {
1252 +                       case 2: /* turn on suid flag */
1253 +                       tmp_mode |= S_ISUID | S_IXUSR;
1254 +                       break;
1255 +                       
1256 +                       case 5: /* turn on sgid flag */
1257 +                       tmp_mode |= S_ISGID | S_IXGRP;
1258 +                       break;
1259 +
1260 +                       default:
1261 +                       return -4; /* failed! -- bad rwxrwxrwx mode change */
1262 +                       break;
1263 +               }
1264 +               p++;
1265 +       }
1266 +       *mode = tmp_mode;
1267 +       return 0;
1268 +}
1269 +
1270 +static void modechopper(mode_t mode, char *p)
1271 +{
1272 +       /* requires char p[10] */
1273 +       int count;
1274 +       char *pp;
1275 +       
1276 +       pp=p;
1277 +       
1278 +       for (count=0; count<9; count ++)
1279 +       {
1280 +               if (mode & modesel[count].bits) *p = modesel[count].rwx;
1281 +               else *p='-';
1282 +               
1283 +               p++;
1284 +       }
1285 +       *p=0; /* to finish the string */
1286 +       
1287 +       /* dealing with suid and sgid flags */
1288 +       if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S';
1289 +       if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S';
1290 +
1291 +}
1292 +
1293 +static int mode_munch(mode_t *mode, const char* p)
1294 +{
1295 +
1296 +       char op=0;
1297 +       mode_t affected_bits, ch_mode;
1298 +       int doneFlag = 0;
1299 +#ifdef DEBUG
1300 +char tmp[10];
1301 +#endif
1302 +
1303 +#ifdef DEBUG
1304 +modechopper(*mode, tmp);
1305 +printf("modemuncher: got base mode = %s\n", tmp);
1306 +#endif
1307 +
1308 +       while (!doneFlag)
1309 +       {
1310 +               /* step 0 -- clear temporary variables */
1311 +               affected_bits=0;
1312 +               ch_mode=0;
1313 +               
1314 +               /* step 1 -- who's affected? */
1315 +
1316 +#ifdef DEBUG
1317 +printf("modemuncher step 1\n");
1318 +#endif
1319 +               
1320 +               /* mode string given in rwxrwxrwx format */
1321 +               if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
1322 +               
1323 +               /* mode string given in ugoa+-=rwx format */
1324 +               for ( ; ; p++)
1325 +                       switch (*p)
1326 +                       {
1327 +                               case 'u':
1328 +                               affected_bits |= 04700;
1329 +                               break;
1330 +                               
1331 +                               case 'g':
1332 +                               affected_bits |= 02070;
1333 +                               break;
1334 +                               
1335 +                               case 'o':
1336 +                               affected_bits |= 01007;
1337 +                               break;
1338 +                               
1339 +                               case 'a':
1340 +                               affected_bits |= 07777;
1341 +                               break;
1342 +                               
1343 +                               /* ignore spaces */
1344 +                               case ' ':
1345 +                               break;
1346 +                               
1347 +                               
1348 +                               default:
1349 +                               goto no_more_affected;
1350 +                       }
1351 +
1352 +               no_more_affected:
1353 +               /* If none specified, affect all bits. */
1354 +               if (affected_bits == 0) affected_bits = 07777;
1355 +
1356 +               /* step 2 -- how is it changed? */
1357 +               
1358 +#ifdef DEBUG
1359 +printf("modemuncher step 2 (*p='%c')\n", *p);
1360 +#endif
1361 +
1362 +               switch (*p)
1363 +               {
1364 +                       case '+':
1365 +                       case '-':
1366 +                       case '=':
1367 +                       op = *p;
1368 +                       break;
1369 +                       
1370 +                       /* ignore spaces */
1371 +                       case ' ':
1372 +                       break;
1373 +                       
1374 +                       default:
1375 +                       return -1; /* failed! -- bad operator */
1376 +               }
1377 +               
1378 +               
1379 +               /* step 3 -- what are the changes? */
1380 +               
1381 +#ifdef DEBUG
1382 +printf("modemuncher step 3\n");
1383 +#endif
1384 +
1385 +               for (p++ ; *p!=0 ; p++)
1386 +                       switch (*p)
1387 +                       {
1388 +                               case 'r':
1389 +                               ch_mode |= 00444;
1390 +                               break;
1391 +                               
1392 +                               case 'w':
1393 +                               ch_mode |= 00222;
1394 +                               break;
1395 +                               
1396 +                               case 'x':
1397 +                               ch_mode |= 00111;
1398 +                               break;
1399 +                               
1400 +                               case 's':
1401 +                               /* Set the setuid/gid bits if `u' or `g' is selected. */
1402 +                               ch_mode |= 06000;
1403 +                               break;
1404 +                       
1405 +                               /* ignore spaces */
1406 +                               case ' ':
1407 +                               break;
1408 +                               
1409 +                               default:
1410 +                               goto specs_done;
1411 +                       }
1412 +
1413 +               specs_done:
1414 +               /* step 4 -- apply the changes */
1415 +
1416 +#ifdef DEBUG
1417 +               printf("modemuncher step 4\n");
1418 +#endif
1419 +               if (*p != ',') doneFlag = 1;
1420 +               if (*p != 0 && *p != ' ' && *p != ',')
1421 +               {
1422 +               
1423 +#ifdef DEBUG
1424 +printf("modemuncher: comma error!\n");
1425 +printf("modemuncher: doneflag = %u\n", doneFlag);
1426 +#endif
1427 +                       return -2; /* failed! -- bad mode change */
1428 +               
1429 +               }
1430 +               p++;
1431 +               /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
1432 +               if (ch_mode) switch (op)
1433 +               {
1434 +                       case '+':
1435 +                       *mode = *mode |= ch_mode & affected_bits;
1436 +                       break;
1437 +
1438 +                       case '-':
1439 +                       *mode = *mode &= ~(ch_mode & affected_bits);
1440 +                       break;
1441 +
1442 +                       case '=':
1443 +                       *mode = ch_mode & affected_bits;
1444 +                       break;
1445 +               
1446 +                       default:
1447 +                       return -3; /* failed! -- unknown error */
1448 +               }
1449 +       }
1450 +#ifdef DEBUG
1451 +modechopper(*mode, tmp);
1452 +printf("modemuncher: returning mode = %s\n", tmp);
1453 +#endif
1454 +
1455 +       return 0; /* successful call */
1456 +}
1457 +
1458 +