diff options
author | niemeyer <devnull@localhost> | 2004-03-16 21:58:25 +0000 |
---|---|---|
committer | niemeyer <devnull@localhost> | 2004-03-16 21:58:25 +0000 |
commit | 73260d956c54a3d95aa7d367c09ed3e2cb2a2a00 (patch) | |
tree | 420516b3d6568f1e09364f6fd59c6c1849da0b43 /lua/local | |
parent | 55f77d61d72a3993436db9a8eefec9eaa7fb61ae (diff) | |
download | rpm-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.tar.gz rpm-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.tar.bz2 rpm-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.zip |
- Implemented support for internal Lua scripts.
- Implemented %pretrans and %posttrans script slots.
Changed files:
Makefile.am configure.ac build/pack.c build/parseScript.c
build/parseSpec.c build/rpmbuild.h build/rpmspec.h
lib/Makefile.am lib/psm.c lib/rpmlib.h lib/rpmlibprov.c
lib/rpmts.c lib/rpmts.h lib/transaction.c
Added files:
lib/rpmlua.c lib/rpmlua.h lua/*
CVS patchset: 7175
CVS date: 2004/03/16 21:58:25
Diffstat (limited to 'lua/local')
-rw-r--r-- | lua/local/linit.c | 7 | ||||
-rw-r--r-- | lua/local/linit.h | 6 | ||||
-rw-r--r-- | lua/local/linit.lch | 45 | ||||
-rw-r--r-- | lua/local/linit.lua | 39 | ||||
-rw-r--r-- | lua/local/lposix.c | 812 | ||||
-rw-r--r-- | lua/local/lposix.h | 6 | ||||
-rw-r--r-- | lua/local/lrexlib.c | 332 | ||||
-rw-r--r-- | lua/local/lrexlib.h | 6 | ||||
-rw-r--r-- | lua/local/modemuncher.c | 271 | ||||
-rw-r--r-- | lua/local/userconfig.c | 55 |
10 files changed, 1579 insertions, 0 deletions
diff --git a/lua/local/linit.c b/lua/local/linit.c new file mode 100644 index 000000000..79bfeac07 --- /dev/null +++ b/lua/local/linit.c @@ -0,0 +1,7 @@ +#include "lua.h" +#include "lauxlib.h" + +LUA_API int luaopen_init(lua_State *L) +{ +#include "linit.lch" +} diff --git a/lua/local/linit.h b/lua/local/linit.h new file mode 100644 index 000000000..04cbb2dd6 --- /dev/null +++ b/lua/local/linit.h @@ -0,0 +1,6 @@ +#ifndef LINIT_H +#define LINIT_H + +int luaopen_init(lua_State *L); + +#endif diff --git a/lua/local/linit.lch b/lua/local/linit.lch new file mode 100644 index 000000000..862d04efd --- /dev/null +++ b/lua/local/linit.lch @@ -0,0 +1,45 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + lua_dofile(L,"local/linit.lua"); +*/ +/* local/linit.lua */ +static const unsigned char B1[]={ + 10,114,101,120, 46,110,101,119, 32, 61, 32,114,101,120, 46,110,101,119, 80, 79, + 83, 73, 88, 10, 10,102,117,110, 99,116,105,111,110, 32,114,101,120, 46,103,114, +101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101,120,112,114, 41, 10, 9, +105,102, 32,110,111,116, 32,112,111,115,105,120, 46,115,116, 97,116, 40,102,105, +108,101,110, 97,109,101, 44, 32, 34,109,111,100,101, 34, 41, 32,116,104,101,110, + 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, 10, 9,101,110,100, 10, 9, +108,111, 99, 97,108, 32,108,105,110,101,115, 32, 61, 32,123,125, 10, 9,108,111, + 99, 97,108, 32,112, 97,116, 32, 61, 32,114,101,120, 46,110,101,119, 40,101,120, +112,114, 41, 10, 9,108,111, 99, 97,108, 32,112,111,115, 32, 61, 32, 49, 10, 9, +102,111,114, 32,108,105,110,101, 32,105,110, 32,105,111, 46,108,105,110,101,115, + 40,102,105,108,101,110, 97,109,101, 41, 32,100,111, 10, 9, 9,105,102, 32,112, + 97,116, 58,109, 97,116, 99,104, 40,108,105,110,101, 41, 32,116,104,101,110, 10, + 9, 9, 9,116, 97, 98,108,101, 46,105,110,115,101,114,116, 40,108,105,110,101, +115, 44, 32,112,111,115, 44, 32,108,105,110,101, 41, 10, 9, 9,101,110,100, 10, + 9, 9,112,111,115, 32, 61, 32,112,111,115, 32, 43, 32, 49, 10, 9,101,110,100, + 10, 9,105,102, 32,116, 97, 98,108,101, 46,103,101,116,110, 40,108,105,110,101, +115, 41, 32, 61, 61, 32, 48, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114, +110, 32,110,105,108, 10, 9,101,110,100, 10, 9,114,101,116,117,114,110, 32,108, +105,110,101,115, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,114, +101,120, 46,105,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101, +120,112,114, 41, 10, 9,114,101,116,117,114,110, 32,105,112, 97,105,114,115, 40, +114,101,120, 46,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101, +120,112,114, 41, 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, +114,101,120, 46, 98,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32, +101,120,112,114, 41, 10, 9,105,102, 32,110,111,116, 32,112,111,115,105,120, 46, +115,116, 97,116, 40,102,105,108,101,110, 97,109,101, 44, 32, 34,109,111,100,101, + 34, 41, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, + 10, 9,101,110,100, 10, 9,108,111, 99, 97,108, 32,112, 97,116, 32, 61, 32,114, +101,120, 46,110,101,119, 40,101,120,112,114, 41, 10, 9,102,111,114, 32,108,105, +110,101, 32,105,110, 32,105,111, 46,108,105,110,101,115, 40,102,105,108,101,110, + 97,109,101, 41, 32,100,111, 10, 9, 9,105,102, 32,112, 97,116, 58,109, 97,116, + 99,104, 40,108,105,110,101, 41, 32,116,104,101,110, 10, 9, 9, 9,114,101,116, +117,114,110, 32,116,114,117,101, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, + 9,114,101,116,117,114,110, 32,102, 97,108,115,101, 10,101,110,100, 10, 10, +}; + + lua_dobuffer(L,(const char*)B1,sizeof(B1),"local/linit.lua"); +} diff --git a/lua/local/linit.lua b/lua/local/linit.lua new file mode 100644 index 000000000..a63316cd7 --- /dev/null +++ b/lua/local/linit.lua @@ -0,0 +1,39 @@ + +rex.new = rex.newPOSIX + +function rex.grep(filename, expr) + if not posix.stat(filename, "mode") then + return nil + end + local lines = {} + local pat = rex.new(expr) + local pos = 1 + for line in io.lines(filename) do + if pat:match(line) then + table.insert(lines, pos, line) + end + pos = pos + 1 + end + if table.getn(lines) == 0 then + return nil + end + return lines +end + +function rex.igrep(filename, expr) + return ipairs(rex.grep(filename, expr)) +end + +function rex.bgrep(filename, expr) + if not posix.stat(filename, "mode") then + return nil + end + local pat = rex.new(expr) + for line in io.lines(filename) do + if pat:match(line) then + return true + end + end + return false +end + diff --git a/lua/local/lposix.c b/lua/local/lposix.c new file mode 100644 index 000000000..a54d20559 --- /dev/null +++ b/lua/local/lposix.c @@ -0,0 +1,812 @@ +/* +* lposix.c +* POSIX library for Lua 5.0. Based on original by Claudio Terra for Lua 3.x. +* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> +* 05 Nov 2003 22:09:10 +*/ + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/times.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> + +#define MYNAME "posix" +#define MYVERSION MYNAME " library for " LUA_VERSION " / Nov 2003" + +#include "lua.h" +#include "lauxlib.h" + +#ifndef MYBUFSIZ +#define MYBUFSIZ 512 +#endif + +#include "modemuncher.c" + +static const char *filetype(mode_t m) +{ + if (S_ISREG(m)) return "regular"; + else if (S_ISLNK(m)) return "link"; + else if (S_ISDIR(m)) return "directory"; + else if (S_ISCHR(m)) return "character device"; + else if (S_ISBLK(m)) return "block device"; + else if (S_ISFIFO(m)) return "fifo"; + else if (S_ISSOCK(m)) return "socket"; + else return "?"; +} + +typedef int (*Selector)(lua_State *L, int i, const void *data); + +static int doselection(lua_State *L, int i, const char *const S[], Selector F, const void *data) +{ + if (lua_isnone(L, i)) + { + lua_newtable(L); + for (i=0; S[i]!=NULL; i++) + { + lua_pushstring(L, S[i]); + F(L, i, data); + lua_settable(L, -3); + } + return 1; + } + else + { + int j=luaL_findstring(luaL_checkstring(L, i), S); + if (j==-1) luaL_argerror(L, i, "unknown selector"); + return F(L, j, data); + } +} + +static void storeindex(lua_State *L, int i, const char *value) +{ + lua_pushstring(L, value); + lua_rawseti(L, -2, i); +} + +static void storestring(lua_State *L, const char *name, const char *value) +{ + lua_pushstring(L, name); + lua_pushstring(L, value); + lua_settable(L, -3); +} + +static void storenumber(lua_State *L, const char *name, lua_Number value) +{ + lua_pushstring(L, name); + lua_pushnumber(L, value); + lua_settable(L, -3); +} + +static int pusherror(lua_State *L, const char *info) +{ + lua_pushnil(L); + if (info==NULL) + lua_pushstring(L, strerror(errno)); + else + lua_pushfstring(L, "%s: %s", info, strerror(errno)); + lua_pushnumber(L, errno); + return 3; +} + +static int pushresult(lua_State *L, int i, const char *info) +{ + if (i != -1) + { + lua_pushnumber(L, i); + return 1; + } + else + return pusherror(L, info); +} + +static void badoption(lua_State *L, int i, const char *what, int option) +{ + luaL_argerror(L, 2, + lua_pushfstring(L, "unknown %s option `%c'", what, option)); +} + +static uid_t mygetuid(lua_State *L, int i) +{ + if (lua_isnone(L, i)) + return -1; + else if (lua_isnumber(L, i)) + return (uid_t) lua_tonumber(L, i); + else if (lua_isstring(L, i)) + { + struct passwd *p=getpwnam(lua_tostring(L, i)); + return (p==NULL) ? -1 : p->pw_uid; + } + else + return luaL_typerror(L, i, "string or number"); +} + +static gid_t mygetgid(lua_State *L, int i) +{ + if (lua_isnone(L, i)) + return -1; + else if (lua_isnumber(L, i)) + return (gid_t) lua_tonumber(L, i); + else if (lua_isstring(L, i)) + { + struct group *g=getgrnam(lua_tostring(L, i)); + return (g==NULL) ? -1 : g->gr_gid; + } + else + return luaL_typerror(L, i, "string or number"); +} + + + +static int Perrno(lua_State *L) /** errno() */ +{ + lua_pushstring(L, strerror(errno)); + lua_pushnumber(L, errno); + return 2; +} + + +static int Pdir(lua_State *L) /** dir([path]) */ +{ + const char *path = luaL_optstring(L, 1, "."); + DIR *d = opendir(path); + if (d == NULL) + return pusherror(L, path); + else + { + int i; + struct dirent *entry; + lua_newtable(L); + for (i=1; (entry = readdir(d)) != NULL; i++) + storeindex(L, i, entry->d_name); + closedir(d); + return 1; + } +} + + +static int aux_files(lua_State *L) +{ + DIR *d = lua_touserdata(L, lua_upvalueindex(1)); + struct dirent *entry; + if (d == NULL) luaL_error(L, "attempt to use closed dir"); + entry = readdir(d); + if (entry == NULL) + { + closedir(d); + lua_pushnil(L); + lua_replace(L, lua_upvalueindex(1)); + lua_pushnil(L); + } + else + { + lua_pushstring(L, entry->d_name); +#if 0 +#ifdef _DIRENT_HAVE_D_TYPE + lua_pushstring(L, filetype(DTTOIF(entry->d_type))); + return 2; +#endif +#endif + } + return 1; +} + +static int Pfiles(lua_State *L) /** files([path]) */ +{ + const char *path = luaL_optstring(L, 1, "."); + DIR *d = opendir(path); + if (d == NULL) + return pusherror(L, path); + else + { + lua_pushlightuserdata(L, d); + lua_pushcclosure(L, aux_files, 1); + return 1; + } +} + + +static int Pgetcwd(lua_State *L) /** getcwd() */ +{ + char buf[MYBUFSIZ]; + if (getcwd(buf, sizeof(buf)) == NULL) + return pusherror(L, "."); + else + { + lua_pushstring(L, buf); + return 1; + } +} + + +static int Pmkdir(lua_State *L) /** mkdir(path) */ +{ + const char *path = luaL_checkstring(L, 1); + return pushresult(L, mkdir(path, 0777), path); +} + + +static int Pchdir(lua_State *L) /** chdir(path) */ +{ + const char *path = luaL_checkstring(L, 1); + return pushresult(L, chdir(path), path); +} + + +static int Prmdir(lua_State *L) /** rmdir(path) */ +{ + const char *path = luaL_checkstring(L, 1); + return pushresult(L, rmdir(path), path); +} + + +static int Punlink(lua_State *L) /** unlink(path) */ +{ + const char *path = luaL_checkstring(L, 1); + return pushresult(L, unlink(path), path); +} + + +static int Plink(lua_State *L) /** link(oldpath,newpath) */ +{ + const char *oldpath = luaL_checkstring(L, 1); + const char *newpath = luaL_checkstring(L, 2); + return pushresult(L, link(oldpath, newpath), NULL); +} + + +static int Psymlink(lua_State *L) /** symlink(oldpath,newpath) */ +{ + const char *oldpath = luaL_checkstring(L, 1); + const char *newpath = luaL_checkstring(L, 2); + return pushresult(L, symlink(oldpath, newpath), NULL); +} + + +static int Preadlink(lua_State *L) /** readlink(path) */ +{ + char buf[MYBUFSIZ]; + const char *path = luaL_checkstring(L, 1); + int n = readlink(path, buf, sizeof(buf)); + if (n==-1) return pusherror(L, path); + lua_pushlstring(L, buf, n); + return 1; +} + + +static int Paccess(lua_State *L) /** access(path,[mode]) */ +{ + int mode=F_OK; + const char *path=luaL_checkstring(L, 1); + const char *s; + for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++) + switch (*s) + { + case ' ': break; + case 'r': mode |= R_OK; break; + case 'w': mode |= W_OK; break; + case 'x': mode |= X_OK; break; + case 'f': mode |= F_OK; break; + default: badoption(L, 2, "mode", *s); break; + } + return pushresult(L, access(path, mode), path); +} + + +static int Pmkfifo(lua_State *L) /** mkfifo(path) */ +{ + const char *path = luaL_checkstring(L, 1); + return pushresult(L, mkfifo(path, 0777), path); +} + + +static int Pexec(lua_State *L) /** exec(path,[args]) */ +{ + const char *path = luaL_checkstring(L, 1); + int i,n=lua_gettop(L); + char **argv = malloc((n+1)*sizeof(char*)); + if (argv==NULL) luaL_error(L,"not enough memory"); + argv[0] = (char*)path; + for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1); + argv[i] = NULL; + execvp(path,argv); + return pusherror(L, path); +} + + +static int Pfork(lua_State *L) /** fork() */ +{ + return pushresult(L, fork(), NULL); +} + + +static int Pwait(lua_State *L) /** wait([pid]) */ +{ + pid_t pid = luaL_optint(L, 1, -1); + return pushresult(L, waitpid(pid, NULL, 0), NULL); +} + + +static int Pkill(lua_State *L) /** kill(pid,[sig]) */ +{ + pid_t pid = luaL_checkint(L, 1); + int sig = luaL_optint(L, 2, SIGTERM); + return pushresult(L, kill(pid, sig), NULL); +} + + +static int Psleep(lua_State *L) /** sleep(seconds) */ +{ + unsigned int seconds = luaL_checkint(L, 1); + lua_pushnumber(L, sleep(seconds)); + return 1; +} + + +static int Pputenv(lua_State *L) /** putenv(string) */ +{ + size_t l; + const char *s=luaL_checklstring(L, 1, &l); + char *e=malloc(++l); + return pushresult(L, (e==NULL) ? -1 : putenv(memcpy(e,s,l)), s); +} + + +#ifdef linux +static int Psetenv(lua_State *L) /** setenv(name,value,[over]) */ +{ + const char *name=luaL_checkstring(L, 1); + const char *value=luaL_checkstring(L, 2); + int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3); + return pushresult(L, setenv(name,value,overwrite), name); +} + + +static int Punsetenv(lua_State *L) /** unsetenv(name) */ +{ + const char *name=luaL_checkstring(L, 1); + unsetenv(name); + return 0; +} +#endif + + +static int Pgetenv(lua_State *L) /** getenv([name]) */ +{ + if (lua_isnone(L, 1)) + { + extern char **environ; + char **e; + if (*environ==NULL) lua_pushnil(L); else lua_newtable(L); + for (e=environ; *e!=NULL; e++) + { + char *s=*e; + char *eq=strchr(s, '='); + if (eq==NULL) /* will this ever happen? */ + { + lua_pushstring(L,s); + lua_pushboolean(L,0); + } + else + { + lua_pushlstring(L,s,eq-s); + lua_pushstring(L,eq+1); + } + lua_settable(L,-3); + } + } + else + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); + return 1; +} + + +static int Pumask(lua_State *L) /** umask([mode]) */ +{ + char m[10]; + mode_t mode; + umask(mode=umask(0)); + mode=(~mode)&0777; + if (!lua_isnone(L, 1)) + { + if (mode_munch(&mode, luaL_checkstring(L, 1))) + { + lua_pushnil(L); + return 1; + } + mode&=0777; + umask(~mode); + } + modechopper(mode, m); + lua_pushstring(L, m); + return 1; +} + + +static int Pchmod(lua_State *L) /** chmod(path,mode) */ +{ + mode_t mode; + struct stat s; + const char *path = luaL_checkstring(L, 1); + const char *modestr = luaL_checkstring(L, 2); + if (stat(path, &s)) return pusherror(L, path); + mode = s.st_mode; + if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode"); + return pushresult(L, chmod(path, mode), path); +} + + +static int Pchown(lua_State *L) /** chown(path,uid,gid) */ +{ + const char *path = luaL_checkstring(L, 1); + uid_t uid = mygetuid(L, 2); + gid_t gid = mygetgid(L, 3); + return pushresult(L, chown(path, uid, gid), path); +} + + +static int Putime(lua_State *L) /** utime(path,[mtime,atime]) */ +{ + struct utimbuf times; + time_t currtime = time(NULL); + const char *path = luaL_checkstring(L, 1); + times.modtime = luaL_optnumber(L, 2, currtime); + times.actime = luaL_optnumber(L, 3, currtime); + return pushresult(L, utime(path, ×), path); +} + + +static int FgetID(lua_State *L, int i, const void *data) +{ + switch (i) + { + case 0: lua_pushnumber(L, getegid()); break; + case 1: lua_pushnumber(L, geteuid()); break; + case 2: lua_pushnumber(L, getgid()); break; + case 3: lua_pushnumber(L, getuid()); break; + case 4: lua_pushnumber(L, getpgrp()); break; + case 5: lua_pushnumber(L, getpid()); break; + case 6: lua_pushnumber(L, getppid()); break; + } + return 1; +} + +static const char *const SgetID[] = +{ + "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL +}; + +static int Pgetprocessid(lua_State *L) /** getprocessid([selector]) */ +{ + return doselection(L, 1, SgetID, FgetID, NULL); +} + + +static int Pttyname(lua_State *L) /** ttyname(fd) */ +{ + int fd=luaL_optint(L, 1, 0); + lua_pushstring(L, ttyname(fd)); + return 1; +} + +static int Pctermid(lua_State *L) /** ctermid() */ +{ + char b[L_ctermid]; + lua_pushstring(L, ctermid(b)); + return 1; +} + + +static int Pgetlogin(lua_State *L) /** getlogin() */ +{ + lua_pushstring(L, getlogin()); + return 1; +} + + +static int Fgetpasswd(lua_State *L, int i, const void *data) +{ + const struct passwd *p=data; + switch (i) + { + case 0: lua_pushstring(L, p->pw_name); break; + case 1: lua_pushnumber(L, p->pw_uid); break; + case 2: lua_pushnumber(L, p->pw_gid); break; + case 3: lua_pushstring(L, p->pw_dir); break; + case 4: lua_pushstring(L, p->pw_shell); break; +/* not strictly POSIX */ + case 5: lua_pushstring(L, p->pw_gecos); break; + case 6: lua_pushstring(L, p->pw_passwd); break; + } + return 1; +} + +static const char *const Sgetpasswd[] = +{ + "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL +}; + + +static int Pgetpasswd(lua_State *L) /** getpasswd(name or id) */ +{ + struct passwd *p=NULL; + if (lua_isnoneornil(L, 1)) + p = getpwuid(geteuid()); + else if (lua_isnumber(L, 1)) + p = getpwuid((uid_t)lua_tonumber(L, 1)); + else if (lua_isstring(L, 1)) + p = getpwnam(lua_tostring(L, 1)); + else + luaL_typerror(L, 1, "string or number"); + if (p==NULL) + lua_pushnil(L); + else + doselection(L, 2, Sgetpasswd, Fgetpasswd, p); + return 1; +} + + +static int Pgetgroup(lua_State *L) /** getgroup(name or id) */ +{ + struct group *g=NULL; + if (lua_isnumber(L, 1)) + g = getgrgid((gid_t)lua_tonumber(L, 1)); + else if (lua_isstring(L, 1)) + g = getgrnam(lua_tostring(L, 1)); + else + luaL_typerror(L, 1, "string or number"); + if (g==NULL) + lua_pushnil(L); + else + { + int i; + lua_newtable(L); + storestring(L, "name", g->gr_name); + storenumber(L, "gid", g->gr_gid); + for (i=0; g->gr_mem[i] != NULL; i++) + storeindex(L, i+1, g->gr_mem[i]); + } + return 1; +} + + +static int Psetuid(lua_State *L) /** setuid(name or id) */ +{ + return pushresult(L, setuid(mygetuid(L, 1)), NULL); +} + + +static int Psetgid(lua_State *L) /** setgid(name or id) */ +{ + return pushresult(L, setgid(mygetgid(L, 1)), NULL); +} + +struct mytimes +{ + struct tms t; + clock_t elapsed; +}; + +#define pushtime(L,x) lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC) + +static int Ftimes(lua_State *L, int i, const void *data) +{ + const struct mytimes *t=data; + switch (i) + { + case 0: pushtime(L, t->t.tms_utime); break; + case 1: pushtime(L, t->t.tms_stime); break; + case 2: pushtime(L, t->t.tms_cutime); break; + case 3: pushtime(L, t->t.tms_cstime); break; + case 4: pushtime(L, t->elapsed); break; + } + return 1; +} + +static const char *const Stimes[] = +{ + "utime", "stime", "cutime", "cstime", "elapsed", NULL +}; + +#define storetime(L,name,x) storenumber(L,name,(lua_Number)x/CLOCKS_PER_SEC) + +static int Ptimes(lua_State *L) /** times() */ +{ + struct mytimes t; + t.elapsed = times(&t.t); + return doselection(L, 1, Stimes, Ftimes, &t); +} + + +struct mystat +{ + struct stat s; + char mode[10]; + const char *type; +}; + +static int Fstat(lua_State *L, int i, const void *data) +{ + const struct mystat *s=data; + switch (i) + { + case 0: lua_pushstring(L, s->mode); break; + case 1: lua_pushnumber(L, s->s.st_ino); break; + case 2: lua_pushnumber(L, s->s.st_dev); break; + case 3: lua_pushnumber(L, s->s.st_nlink); break; + case 4: lua_pushnumber(L, s->s.st_uid); break; + case 5: lua_pushnumber(L, s->s.st_gid); break; + case 6: lua_pushnumber(L, s->s.st_size); break; + case 7: lua_pushnumber(L, s->s.st_atime); break; + case 8: lua_pushnumber(L, s->s.st_mtime); break; + case 9: lua_pushnumber(L, s->s.st_ctime); break; + case 10:lua_pushstring(L, s->type); break; + case 11:lua_pushnumber(L, s->s.st_mode); break; + } + return 1; +} + +static const char *const Sstat[] = +{ + "mode", "ino", "dev", "nlink", "uid", "gid", + "size", "atime", "mtime", "ctime", "type", "_mode", + NULL +}; + +static int Pstat(lua_State *L) /** stat(path,[selector]) */ +{ + struct mystat s; + const char *path=luaL_checkstring(L, 1); + if (lstat(path,&s.s)==-1) return pusherror(L, path); + s.type=filetype(s.s.st_mode); + modechopper(s.s.st_mode, s.mode); + return doselection(L, 2, Sstat, Fstat, &s); +} + + +static int Puname(lua_State *L) /** uname([string]) */ +{ + struct utsname u; + luaL_Buffer b; + const char *s; + if (uname(&u) == -1) return pusherror(L, NULL); + luaL_buffinit(L, &b); + for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++) + if (*s!='%') + luaL_putchar(&b, *s); + else switch (*++s) + { + case '%': luaL_putchar(&b, *s); break; + case 'm': luaL_addstring(&b,u.machine); break; + case 'n': luaL_addstring(&b,u.nodename); break; + case 'r': luaL_addstring(&b,u.release); break; + case 's': luaL_addstring(&b,u.sysname); break; + case 'v': luaL_addstring(&b,u.version); break; + default: badoption(L, 2, "format", *s); break; + } + luaL_pushresult(&b); + return 1; +} + + +static const int Kpathconf[] = +{ + _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX, + _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE, + -1 +}; + +static int Fpathconf(lua_State *L, int i, const void *data) +{ + const char *path=data; + lua_pushnumber(L, pathconf(path, Kpathconf[i])); + return 1; +} + +static const char *const Spathconf[] = +{ + "link_max", "max_canon", "max_input", "name_max", "path_max", + "pipe_buf", "chown_restricted", "no_trunc", "vdisable", + NULL +}; + +static int Ppathconf(lua_State *L) /** pathconf(path,[selector]) */ +{ + const char *path=luaL_checkstring(L, 1); + return doselection(L, 2, Spathconf, Fpathconf, path); +} + + +static const int Ksysconf[] = +{ + _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX, + _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION, + -1 +}; + +static int Fsysconf(lua_State *L, int i, const void *data) +{ + lua_pushnumber(L, sysconf(Ksysconf[i])); + return 1; +} + +static const char *const Ssysconf[] = +{ + "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max", + "tzname_max", "open_max", "job_control", "saved_ids", "version", + NULL +}; + +static int Psysconf(lua_State *L) /** sysconf([selector]) */ +{ + return doselection(L, 1, Ssysconf, Fsysconf, NULL); +} + + +static const luaL_reg R[] = +{ + {"access", Paccess}, + {"chdir", Pchdir}, + {"chmod", Pchmod}, + {"chown", Pchown}, + {"ctermid", Pctermid}, + {"dir", Pdir}, + {"errno", Perrno}, + {"exec", Pexec}, + {"files", Pfiles}, + {"fork", Pfork}, + {"getcwd", Pgetcwd}, + {"getenv", Pgetenv}, + {"getgroup", Pgetgroup}, + {"getlogin", Pgetlogin}, + {"getpasswd", Pgetpasswd}, + {"getprocessid", Pgetprocessid}, + {"kill", Pkill}, + {"link", Plink}, + {"mkdir", Pmkdir}, + {"mkfifo", Pmkfifo}, + {"pathconf", Ppathconf}, + {"putenv", Pputenv}, + {"readlink", Preadlink}, + {"rmdir", Prmdir}, + {"setgid", Psetgid}, + {"setuid", Psetuid}, + {"sleep", Psleep}, + {"stat", Pstat}, + {"symlink", Psymlink}, + {"sysconf", Psysconf}, + {"times", Ptimes}, + {"ttyname", Pttyname}, + {"umask", Pumask}, + {"uname", Puname}, + {"unlink", Punlink}, + {"utime", Putime}, + {"wait", Pwait}, + +#ifdef linux + {"setenv", Psetenv}, + {"unsetenv", Punsetenv}, +#endif + {NULL, NULL} +}; + +LUALIB_API int luaopen_posix (lua_State *L) +{ + luaL_openlib(L, MYNAME, R, 0); + lua_pushliteral(L,"version"); /** version */ + lua_pushliteral(L,MYVERSION); + lua_settable(L,-3); + return 1; +} diff --git a/lua/local/lposix.h b/lua/local/lposix.h new file mode 100644 index 000000000..e1e819cb3 --- /dev/null +++ b/lua/local/lposix.h @@ -0,0 +1,6 @@ +#ifndef LPOSIX_H +#define LPOSIX_H + +int luaopen_posix (lua_State *L); + +#endif diff --git a/lua/local/lrexlib.c b/lua/local/lrexlib.c new file mode 100644 index 000000000..fe9a73576 --- /dev/null +++ b/lua/local/lrexlib.c @@ -0,0 +1,332 @@ +/* lrexlib.c - POSIX & PCRE regular expression library */ +/* POSIX regexs can use Spencer extensions for matching NULs if available + (REG_BASIC) */ +/* Reuben Thomas nov00-06oct03 */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "lua.h" +#include "lauxlib.h" + +/* Sanity check */ +#if !defined(WITH_POSIX) && !defined(WITH_PCRE) +#error Define WITH_POSIX or WITH_PCRE, otherwise this library is useless! +#endif + + +/* POSIX regex methods */ + +#ifdef WITH_POSIX + +#include <regex.h> + +static int rex_comp(lua_State *L) { + size_t l; + const char *pattern; + int res; + regex_t *pr = (regex_t *)lua_newuserdata(L, sizeof(regex_t)); + pattern = luaL_checklstring(L, 1, &l); +#ifdef REG_BASIC + pr->re_endp = pattern + lua_strlen(L, 1); + res = regcomp(pr, pattern, REG_EXTENDED | REG_PEND); +#else + res = regcomp(pr, pattern, REG_EXTENDED); +#endif + if (res) { + size_t sz = regerror(res, pr, NULL, 0); + char errbuf[sz]; + regerror(res, pr, errbuf, sz); + lua_pushstring(L, errbuf); + lua_error(L); + } + luaL_getmetatable(L, "regex_t"); + lua_setmetatable(L, -2); + return 1; +} + +static void rex_getargs(lua_State *L, size_t *len, size_t *ncapt, + const char **text, regex_t **pr, regmatch_t **match) { + luaL_checkany(L, 1); + *pr = (regex_t *)lua_touserdata(L, 1); +#ifdef REG_BASIC + *text = luaL_checklstring(L, 2, len); +#else + *text = luaL_checklstring(L, 2, NULL); +#endif + *ncapt = (*pr)->re_nsub; + luaL_checkstack(L, *ncapt + 2, "too many captures"); + *match = malloc((*ncapt + 1) * sizeof(regmatch_t)); +} + +static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match, + size_t ncapt) { + size_t i; + lua_newtable(L); + for (i = 1; i <= ncapt; i++) { + if (match[i].rm_so >= 0) { + lua_pushlstring(L, text + match[i].rm_so, + match[i].rm_eo - match[i].rm_so); + lua_rawseti(L, -2, i); + } + } +} + +static int rex_match(lua_State *L) { + int res; +#ifdef REG_BASIC + size_t len; +#endif + size_t ncapt; + const char *text; + regex_t *pr; + regmatch_t *match; + rex_getargs(L, +#ifdef REG_BASIC + &len, +#else + NULL, +#endif + &ncapt, &text, &pr, &match); +#ifdef REG_BASIC + match[0].rm_so = 0; + match[0].rm_eo = len; + res = regexec(pr, text, ncapt + 1, match, REG_STARTEND); +#else + res = regexec(pr, text, ncapt + 1, match, 0); +#endif + if (res == 0) { + lua_pushnumber(L, match[0].rm_so + 1); + lua_pushnumber(L, match[0].rm_eo); + rex_push_matches(L, text, match, ncapt); + lua_pushstring(L, "n"); + lua_pushnumber(L, ncapt); + lua_rawset(L, -3); + return 3; + } else + return 0; +} + +static int rex_gmatch(lua_State *L) { + int res; +#ifdef REG_BASIC + size_t len; +#endif + size_t ncapt, nmatch = 0, maxmatch, limit = 0; + const char *text; + regex_t *pr; + regmatch_t *match; + rex_getargs(L, +#ifdef REG_BASIC + &len, +#else + NULL, +#endif + &ncapt, &text, &pr, &match); + luaL_checktype(L, 3, LUA_TFUNCTION); + if (lua_gettop(L) > 3) { + maxmatch = (size_t)luaL_checknumber(L, 4); + limit = 1; + } + while (!limit || nmatch < maxmatch) { +#ifdef REG_BASIC + match[0].rm_so = 0; + match[0].rm_eo = len; + res = regexec(pr, text, ncapt + 1, match, REG_STARTEND); +#else + res = regexec(pr, text, ncapt + 1, match, 0); +#endif + if (res == 0) { + lua_pushvalue(L, 3); + lua_pushlstring(L, text + match[0].rm_so, match[0].rm_eo - match[0].rm_so); + rex_push_matches(L, text, match, ncapt); + lua_call(L, 2, 0); + text += match[0].rm_eo; +#ifdef REG_BASIC + len -= match[0].rm_eo; +#endif + nmatch++; + } else + break; + } + lua_pushnumber(L, nmatch); + return 1; +} + +static int rex_gc (lua_State *L) { + regex_t *r = (regex_t *)luaL_checkudata(L, 1, "regex_t"); + if (r) + regfree(r); + return 0; +} + +static const luaL_reg rexmeta[] = { + {"match", rex_match}, + {"gmatch", rex_gmatch}, + {"__gc", rex_gc}, + {NULL, NULL} +}; + +#endif /* WITH_POSIX */ + + +/* PCRE methods */ + +#ifdef WITH_PCRE + +#include <pcre/pcre.h> + +static int pcre_comp(lua_State *L) +{ + size_t l; + const char *pattern; + const char *error; + int erroffset; + pcre **ppr = (pcre **)lua_newuserdata(L, sizeof(pcre **)); + pcre *pr; + pattern = luaL_checklstring(L, 1, &l); + pr = pcre_compile(pattern, 0, &error, &erroffset, NULL); + if (!pr) { + lua_pushstring(L, error); + lua_error(L); + } + *ppr = pr; + luaL_getmetatable(L, "pcre"); + lua_setmetatable(L, -2); + return 1; +} + +static void pcre_getargs(lua_State *L, int *len, int *ncapt, const char **text, + pcre ***ppr, int **match) +{ + luaL_checkany(L, 1); + *ppr = (pcre **)lua_touserdata(L, 1); + *text = luaL_checklstring(L, 2, len); + pcre_fullinfo(**ppr, NULL, PCRE_INFO_CAPTURECOUNT, ncapt); + luaL_checkstack(L, *ncapt + 2, "too many captures"); + /* need (2 ints per capture, plus one for substring match) * 3/2 */ + *match = malloc((*ncapt + 1) * 3 * sizeof(int)); +} + +static void pcre_push_matches(lua_State *L, const char *text, int *match, + int ncapt) +{ + int i; + lua_newtable(L); + for (i = 1; i <= ncapt; i++) { + if (match[i * 2] >= 0) { + lua_pushlstring(L, text + match[i * 2], + match[i * 2 + 1] - match[i * 2]); + lua_rawseti(L, -2, i); + } + } +} + +static int pcre_match(lua_State *L) +{ + int res; + const char *text; + pcre **ppr; + int *match; + int ncapt; + int len; + pcre_getargs(L, &len, &ncapt, &text, &ppr, &match); + res = pcre_exec(*ppr, NULL, text, len, 0, 0, match, (ncapt + 1) * 3); + if (res >= 0) { + lua_pushnumber(L, match[0] + 1); + lua_pushnumber(L, match[1]); + pcre_push_matches(L, text, match, ncapt); + lua_pushstring(L, "n"); + lua_pushnumber(L, ncapt); + lua_rawset(L, -3); + return 3; + } else + return 0; +} + +static int pcre_gmatch(lua_State *L) +{ + int res; + const char *text; + int limit = 0; + int ncapt, nmatch = 0, maxmatch; + pcre **ppr; + int *match; + int len; + pcre_getargs(L, &len, &ncapt, &text, &ppr, &match); + luaL_checktype(L, 3, LUA_TFUNCTION); + if (lua_gettop(L) > 3) { + maxmatch = (int)luaL_checknumber(L, 4); + limit = 1; + } + while (!limit || nmatch < maxmatch) { + res = pcre_exec(*ppr, NULL, text, len, 0, 0, match, (ncapt + 1) * 3); + if (res == 0) { + lua_pushvalue(L, 3); + lua_pushlstring(L, text + match[0], match[1] - match[0]); + pcre_push_matches(L, text, match, ncapt); + lua_call(L, 2, 0); + text += match[1]; + len -= match[1]; + nmatch++; + } else + break; + } + lua_pushnumber(L, nmatch); + return 1; +} + +static int pcre_gc (lua_State *L) +{ + pcre **ppr = (pcre **)luaL_checkudata(L, 1, "pcre"); + if (ppr) + pcre_free(*ppr); + return 0; +} + +static const luaL_reg pcremeta[] = { + {"match", pcre_match}, + {"gmatch", pcre_gmatch}, + {"__gc", pcre_gc}, + {NULL, NULL} +}; + +#endif /* defined(WITH_PCRE) */ + + +/* Open the library */ + +static const luaL_reg rexlib[] = { +#ifdef WITH_POSIX + {"newPOSIX", rex_comp}, +#endif +#ifdef WITH_PCRE + {"newPCRE", pcre_comp}, +#endif + {NULL, NULL} +}; + +static void createmeta(lua_State *L, const char *name) +{ + luaL_newmetatable(L, name); /* create new metatable */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ +} + +LUALIB_API int luaopen_rex(lua_State *L) +{ +#ifdef WITH_POSIX + createmeta(L, "regex_t"); + luaL_openlib(L, NULL, rexmeta, 0); + lua_pop(L, 1); +#endif +#ifdef WITH_PCRE + createmeta(L, "pcre"); + luaL_openlib(L, NULL, pcremeta, 0); + lua_pop(L, 1); +#endif + luaL_openlib(L, "rex", rexlib, 0); + return 1; +} diff --git a/lua/local/lrexlib.h b/lua/local/lrexlib.h new file mode 100644 index 000000000..663c635ef --- /dev/null +++ b/lua/local/lrexlib.h @@ -0,0 +1,6 @@ +#ifndef LREXLIB_H +#define LREXLIB_H + +int luaopen_rex(lua_State *L); + +#endif diff --git a/lua/local/modemuncher.c b/lua/local/modemuncher.c new file mode 100644 index 000000000..b1e966c9b --- /dev/null +++ b/lua/local/modemuncher.c @@ -0,0 +1,271 @@ +/* + Mode Muncher -- modemuncher.c + 961110 Claudio Terra + + munch vb + [ME monchen, perh. influenced by MF mangier to eat --more at MANGER] + :to chew with a crunching sound: eat with relish + :to chew food with a crunching sound: eat food with relish + --munch-er n + + The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary + and Webster's Collegiate Thesaurus +*/ + +/* struct for rwx <-> POSIX constant lookup tables */ +struct modeLookup +{ + char rwx; + mode_t bits; +}; + +typedef struct modeLookup modeLookup; + +static modeLookup modesel[] = +{ + /* RWX char Posix Constant */ + {'r', S_IRUSR}, + {'w', S_IWUSR}, + {'x', S_IXUSR}, + + {'r', S_IRGRP}, + {'w', S_IWGRP}, + {'x', S_IXGRP}, + + {'r', S_IROTH}, + {'w', S_IWOTH}, + {'x', S_IXOTH}, + {(char)NULL, (mode_t)-1} /* do not delete this line */ +}; + + + +static int rwxrwxrwx(mode_t *mode, const char *p) +{ + int count; + mode_t tmp_mode = *mode; + + tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */ + for (count=0; count<9; count ++) + { + if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits; /* set a bit */ + else if (*p == '-') tmp_mode &= ~modesel[count].bits; /* clear a bit */ + else if (*p=='s') switch(count) + { + case 2: /* turn on suid flag */ + tmp_mode |= S_ISUID | S_IXUSR; + break; + + case 5: /* turn on sgid flag */ + tmp_mode |= S_ISGID | S_IXGRP; + break; + + default: + return -4; /* failed! -- bad rwxrwxrwx mode change */ + break; + } + p++; + } + *mode = tmp_mode; + return 0; +} + +static void modechopper(mode_t mode, char *p) +{ + /* requires char p[10] */ + int count; + char *pp; + + pp=p; + + for (count=0; count<9; count ++) + { + if (mode & modesel[count].bits) *p = modesel[count].rwx; + else *p='-'; + + p++; + } + *p=0; /* to finish the string */ + + /* dealing with suid and sgid flags */ + if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S'; + if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S'; + +} + +static int mode_munch(mode_t *mode, const char* p) +{ + + char op=0; + mode_t affected_bits, ch_mode; + int doneFlag = 0; +#ifdef DEBUG +char tmp[10]; +#endif + +#ifdef DEBUG +modechopper(*mode, tmp); +printf("modemuncher: got base mode = %s\n", tmp); +#endif + + while (!doneFlag) + { + /* step 0 -- clear temporary variables */ + affected_bits=0; + ch_mode=0; + + /* step 1 -- who's affected? */ + +#ifdef DEBUG +printf("modemuncher step 1\n"); +#endif + + /* mode string given in rwxrwxrwx format */ + if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p); + + /* mode string given in 0644 format */ + if (*p >= '0' && *p <= '7') { + char *e; + mode_t tmp_mode = strtol(p, &e, 8); + if (*p == 0 || *e != 0) + return -5; + *mode = tmp_mode; + return 0; + } + + /* mode string given in ugoa+-=rwx format */ + for ( ; ; p++) + switch (*p) + { + case 'u': + affected_bits |= 04700; + break; + + case 'g': + affected_bits |= 02070; + break; + + case 'o': + affected_bits |= 01007; + break; + + case 'a': + affected_bits |= 07777; + break; + + /* ignore spaces */ + case ' ': + break; + + + default: + goto no_more_affected; + } + + no_more_affected: + /* If none specified, affect all bits. */ + if (affected_bits == 0) affected_bits = 07777; + + /* step 2 -- how is it changed? */ + +#ifdef DEBUG +printf("modemuncher step 2 (*p='%c')\n", *p); +#endif + + switch (*p) + { + case '+': + case '-': + case '=': + op = *p; + break; + + /* ignore spaces */ + case ' ': + break; + + default: + return -1; /* failed! -- bad operator */ + } + + + /* step 3 -- what are the changes? */ + +#ifdef DEBUG +printf("modemuncher step 3\n"); +#endif + + for (p++ ; *p!=0 ; p++) + switch (*p) + { + case 'r': + ch_mode |= 00444; + break; + + case 'w': + ch_mode |= 00222; + break; + + case 'x': + ch_mode |= 00111; + break; + + case 's': + /* Set the setuid/gid bits if `u' or `g' is selected. */ + ch_mode |= 06000; + break; + + /* ignore spaces */ + case ' ': + break; + + default: + goto specs_done; + } + + specs_done: + /* step 4 -- apply the changes */ + +#ifdef DEBUG + printf("modemuncher step 4\n"); +#endif + if (*p != ',') doneFlag = 1; + if (*p != 0 && *p != ' ' && *p != ',') + { + +#ifdef DEBUG +printf("modemuncher: comma error!\n"); +printf("modemuncher: doneflag = %u\n", doneFlag); +#endif + return -2; /* failed! -- bad mode change */ + + } + p++; + /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */ + if (ch_mode) switch (op) + { + case '+': + *mode = *mode |= ch_mode & affected_bits; + break; + + case '-': + *mode = *mode &= ~(ch_mode & affected_bits); + break; + + case '=': + *mode = ch_mode & affected_bits; + break; + + default: + return -3; /* failed! -- unknown error */ + } + } +#ifdef DEBUG +modechopper(*mode, tmp); +printf("modemuncher: returning mode = %s\n", tmp); +#endif + + return 0; /* successful call */ +} + + diff --git a/lua/local/userconfig.c b/lua/local/userconfig.c new file mode 100644 index 000000000..dfd2598d7 --- /dev/null +++ b/lua/local/userconfig.c @@ -0,0 +1,55 @@ + +#include "config.h" + +#include "lposix.h" +#include "lrexlib.h" + +#define LUA_EXTRALIBS \ + {"posix", luaopen_posix}, \ + {"rex", luaopen_rex}, \ + {"luapath", luapath}, + +#define lua_readline myreadline +#define lua_saveline mysaveline + +#include <ctype.h> +#include <readline/readline.h> +#include <readline/history.h> + +static int myreadline (lua_State *L, const char *prompt) { + char *s=readline(prompt); + if (s==NULL) + return 0; + else { + lua_pushstring(L,s); + lua_pushliteral(L,"\n"); + lua_concat(L,2); + free(s); + return 1; + } +} + +static void mysaveline (lua_State *L, const char *s) { + const char *p; + for (p=s; isspace(*p); p++) + ; + if (*p!=0) { + size_t n=strlen(s)-1; + if (s[n]!='\n') + add_history(s); + else { + lua_pushlstring(L,s,n); + s=lua_tostring(L,-1); + add_history(s); + lua_remove(L,-1); + } + } +} + +static int luapath(lua_State *L) +{ + lua_pushstring(L, "LUA_PATH"); + lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua;?.lua"); + lua_rawset(L, LUA_GLOBALSINDEX); + return 0; +} |