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