1
/* $Id: luastuff.c,v 1.16 2005/08/10 22:21:53 hahe Exp hahe $ */
3
#include "luatex-api.h"
6
lua_State *Luas[65536];
8
extern char *startup_filename;
9
extern int safer_option;
12
int luastate_bytes = 0;
15
make_table (lua_State *L, char *tab, char *getfunc, char *setfunc) {
16
/* make the table */ /* [{<tex>}] */
17
lua_pushstring(L,tab); /* [{<tex>},"dimen"] */
18
lua_newtable(L); /* [{<tex>},"dimen",{}] */
19
lua_settable(L, -3); /* [{<tex>}] */
21
lua_pushstring(L,tab); /* [{<tex>},"dimen"] */
22
lua_gettable(L, -2); /* [{<tex>},{<dimen>}] */
23
/* make the meta entries */
24
luaL_newmetatable(L,tab); /* [{<tex>},{<dimen>},{<dimen_m>}] */
25
lua_pushstring(L, "__index"); /* [{<tex>},{<dimen>},{<dimen_m>},"__index"] */
26
lua_pushstring(L, getfunc); /* [{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"] */
27
lua_gettable(L, -5); /* [{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>] */
28
lua_settable(L, -3); /* [{<tex>},{<dimen>},{<dimen_m>}] */
29
lua_pushstring(L, "__newindex");/* [{<tex>},{<dimen>},{<dimen_m>},"__newindex"] */
30
lua_pushstring(L, setfunc); /* [{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"] */
31
lua_gettable(L, -5); /* [{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>] */
32
lua_settable(L, -3); /* [{<tex>},{<dimen>},{<dimen_m>}] */
33
lua_setmetatable(L,-2); /* [{<tex>},{<dimen>}] : assign the metatable */
34
lua_pop(L,1); /* [{<tex>}] : clean the stack */
38
const char *getS(lua_State * L, void *ud, size_t * size) {
39
LoadS *ls = (LoadS *) ud;
51
#define exec_command(a,b,c) execvpe(a,(const char* const*)b,(const char* const*)c)
54
#define DEFAULT_PATH "/bin:/usr/bin:."
56
int exec_command(const char *file, char *const *argv, char *const *envp)
59
const char *searchpath, *esp;
60
size_t prefixlen, filelen, totallen;
62
if (strchr(file, '/')) /* Specific path */
63
return execve(file, argv, envp);
65
filelen = strlen(file);
67
searchpath = getenv("PATH");
69
searchpath = DEFAULT_PATH;
71
errno = ENOENT; /* Default errno, if execve() doesn't
75
esp = strchr(searchpath, ':');
77
prefixlen = esp - searchpath;
79
prefixlen = strlen(searchpath);
81
if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') {
82
totallen = prefixlen + filelen;
83
if (totallen >= PATH_MAX)
85
memcpy(path, searchpath, prefixlen);
86
memcpy(path + prefixlen, file, filelen);
88
totallen = prefixlen + filelen + 1;
89
if (totallen >= PATH_MAX)
91
memcpy(path, searchpath, prefixlen);
92
path[prefixlen] = '/';
93
memcpy(path + prefixlen + 1, file, filelen);
95
path[totallen] = '\0';
97
execve(path, argv, envp);
98
if (errno == E2BIG || errno == ENOEXEC ||
99
errno == ENOMEM || errno == ETXTBSY)
100
break; /* Report this as an error, no more search */
102
searchpath = esp + 1;
109
extern char **environ;
112
#define COMMAND_PARTS 20
115
do_split_command(char *maincmd, char **cmdline, char target)
122
if (strlen(maincmd) == 0)
124
cmd = strdup(maincmd);
126
while (cmd[i] == ' ')
129
for (; i <= strlen(maincmd); i++) {
130
if (in_string == 1) {
134
} else if (in_string == 2) {
135
if (cmd[i] == '\'') {
141
} else if (cmd[i] == '\'') {
143
} else if (cmd[i] == target) {
145
if (ret == COMMAND_PARTS) {
146
fprintf(stderr,"os.exec(): Executable command too complex.\n");
148
cmdline[ret++] = strdup(piece);
149
while (i < strlen(maincmd) && cmd[(i + 1)] == ' ')
156
if (ret == COMMAND_PARTS) {
157
fprintf(stderr, "os.exec(): Executable command too complex.\n");
159
cmdline[ret++] = strdup(piece);
164
static int os_exec (lua_State *L) {
168
maincmd = (char *)luaL_optstring(L, 1, NULL);
170
cmdline = malloc(sizeof(char *) * COMMAND_PARTS);
171
for (i = 0; i < COMMAND_PARTS; i++) {
174
i = do_split_command(maincmd, cmdline,' ');
176
exec_command(cmdline[0], cmdline, environ);
182
void make_exec (lua_State *L){
183
lua_getglobal(L,"os");
184
lua_pushcfunction(L, os_exec);
185
lua_setfield(L,-2,"exec");
188
/* Hans wants to set env values */
190
static int os_setenv (lua_State *L) {
191
char *value, *key, *val;
192
key = (char *)luaL_optstring(L, 1, NULL);
193
val = (char *)luaL_optstring(L, 2, NULL);
196
value = xmalloc(strlen(key)+strlen(val)+2);
197
sprintf(value,"%s=%s",key,val);
199
return luaL_error(L, "unable to change environment");
202
#if defined(WIN32) || defined(__sun__)
203
value = xmalloc(strlen(key)+2);
204
sprintf(value,"%s=",key);
206
return luaL_error(L, "unable to change environment");
213
lua_pushboolean (L, 1);
218
void put_env (lua_State *L){
219
lua_getglobal(L,"os");
220
lua_pushcfunction(L, os_setenv);
221
lua_setfield(L,-2,"setenv");
224
void find_env (lua_State *L){
225
char *envitem, *envitem_orig;
228
envpointer = environ;
229
lua_getglobal(L,"os");
230
if (envpointer!=NULL && lua_istable(L,-1)) {
231
luaL_checkstack(L,2,"out of stack space");
232
lua_pushstring(L,"env");
234
while (*envpointer) {
235
/* TODO: perhaps a memory leak here */
236
luaL_checkstack(L,2,"out of stack space");
237
envitem = xstrdup(*envpointer);
238
envitem_orig = envitem;
240
while (*envitem != '=') {
245
lua_pushstring(L,envkey);
246
lua_pushstring(L,envitem);
256
void *my_luaalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
261
ret = realloc(ptr, nsize);
262
luastate_bytes += (nsize-osize);
266
static int my_luapanic (lua_State *L) {
267
(void)L; /* to avoid warnings */
268
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
269
lua_tostring(L, -1));
275
luainterpreter (int n) {
277
L = lua_newstate(my_luaalloc, NULL);
279
fprintf(stderr,"Can't create a new Lua state (%d).",n);
282
lua_atpanic(L, &my_luapanic);
292
/*luaopen_unicode(L);*/
293
lua_pushcfunction(L, luaopen_unicode);
294
lua_pushstring(L, "unicode");
298
lua_pushcfunction(L, luaopen_zip);
299
lua_pushstring(L, "zip");
303
lua_pushcfunction(L, luaopen_lpeg);
304
lua_pushstring(L, "lpeg");
308
lua_pushcfunction(L, luaopen_md5);
309
lua_pushstring(L, "md5");
313
lua_pushcfunction(L, luaopen_lfs);
314
lua_pushstring(L, "lfs");
317
/* zlib. slightly odd calling convention */
319
lua_setglobal(L,"zlib");
332
lua_createtable(L, 0, 0);
333
lua_setglobal(L, "texconfig");
335
luaopen_lua(L,n,startup_filename);
340
/* disable some stuff if --safer */
341
(void)hide_lua_value(L, "os","execute");
342
(void)hide_lua_value(L, "os","rename");
343
(void)hide_lua_value(L, "os","remove");
344
(void)hide_lua_value(L, "io","popen");
345
/* make io.open only read files */
346
luaL_checkstack(L,2,"out of stack space");
347
lua_getglobal(L,"io");
348
lua_getfield(L,-1,"open_ro");
349
lua_setfield(L,-2,"open");
350
(void)hide_lua_value(L, "io","tmpfile");
351
(void)hide_lua_value(L, "io","output");
352
(void)hide_lua_value(L, "lfs","chdir");
353
(void)hide_lua_value(L, "lfs","lock");
354
(void)hide_lua_value(L, "lfs","touch");
355
(void)hide_lua_value(L, "lfs","rmdir");
356
(void)hide_lua_value(L, "lfs","mkdir");
361
int hide_lua_table(lua_State *L, char *name) {
363
lua_getglobal(L,name);
364
if(lua_istable(L,-1)) {
365
r = luaL_ref(L,LUA_REGISTRYINDEX);
367
lua_setglobal(L,name);
372
void unhide_lua_table(lua_State *L, char *name, int r) {
373
lua_rawgeti(L,LUA_REGISTRYINDEX,r);
374
lua_setglobal(L,name);
375
luaL_unref(L,LUA_REGISTRYINDEX,r);
378
int hide_lua_value(lua_State *L, char *name, char *item) {
380
lua_getglobal(L,name);
381
if(lua_istable(L,-1)) {
382
lua_getfield(L,-1,item);
383
r = luaL_ref(L,LUA_REGISTRYINDEX);
385
lua_setfield(L,-2,item);
390
void unhide_lua_value(lua_State *L, char *name, char *item, int r) {
391
lua_getglobal(L,name);
392
if(lua_istable(L,-1)) {
393
lua_rawgeti(L,LUA_REGISTRYINDEX,r);
394
lua_setfield(L,-2,item);
395
luaL_unref(L,LUA_REGISTRYINDEX,r);
401
luacall(int n, int s) {
405
if (Luas[n] == NULL) {
408
luatex_load_init(s,&ls);
410
snprintf((char *)lua_id,12,"luas[%d]",n);
411
i = lua_load(Luas[n], getS, &ls, lua_id);
413
Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1));
415
i = lua_pcall(Luas[n], 0, 0, 0);
417
Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1));
424
luatokencall(int n, int p) {
429
if (Luas[n] == NULL) {
433
s = tokenlist_to_cstring(p,1,&l);
437
snprintf((char *)lua_id,12,"luas[%d]",n);
438
i = lua_load(Luas[n], getS, &ls, lua_id);
441
Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1));
443
i = lua_pcall(Luas[n], 0, 0, 0);
445
Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1));
455
if (n!=0 && Luas[n] != NULL) {
464
luatex_load_init (int s, LoadS *ls) {
465
ls->s = (const char *)&(strpool[strstart[s]]);
466
ls->size = strstart[s + 1] - strstart[s];
470
luatex_error (lua_State * L, int is_fatal) {
475
const char *luaerr = lua_tostring(L, -1);
476
err = (char *)xmalloc(128);
477
len = snprintf(err,128,"%s",luaerr);
479
/* Normally a memory error from lua.
480
The pool may overflow during the maketexstring(), but we
481
are crashing anyway so we may as well abort on the pool size */
482
s = maketexstring(err);
488
return (lua_State *)NULL;
490
/* Here, the pool could be full already, but we can possibly escape from that
491
* condition, since the lua chunk that caused the error is the current string.
493
s = str_ptr-0x200000;
494
// fprintf(stderr,"poolinfo: %d: %d,%d out of %d\n",s,poolptr,strstart[(s-1)],poolsize);
495
poolptr = strstart[(s-1)];
496
strstart[s] = poolptr;
497
if (poolptr+len>=poolsize) {
500
s = maketexstring(err);