400-luaposix_5.1.4-embedded.patch 32 KB

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