package/lua: refresh patches
[openwrt/svn-archive/archive.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 +