diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-04-19 17:22:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-04-19 17:22:32 -0300 |
commit | 79cb336d74697ca38d6d2f2068781086cfaa9076 (patch) | |
tree | 5bc37dc89016027af2262161697142a26fd78df1 | |
parent | 38063345ae050b88c7f7ce1a84c260618123c492 (diff) | |
download | lua-79cb336d74697ca38d6d2f2068781086cfaa9076.tar.gz lua-79cb336d74697ca38d6d2f2068781086cfaa9076.tar.bz2 lua-79cb336d74697ca38d6d2f2068781086cfaa9076.zip |
does not allow standard files to be closed
-rw-r--r-- | liolib.c | 51 |
1 files changed, 36 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.74 2006/06/22 16:12:59 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.75 2006/09/18 14:03:18 roberto Exp roberto $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -93,8 +93,17 @@ static FILE **newfile (lua_State *L) { | |||
93 | 93 | ||
94 | 94 | ||
95 | /* | 95 | /* |
96 | ** this function has a separated environment, which defines the | 96 | ** function to (not) close the standard files stdin, stdout, and stderr |
97 | ** correct __close for 'popen' files | 97 | */ |
98 | static int io_noclose (lua_State *L) { | ||
99 | lua_pushnil(L); | ||
100 | lua_pushliteral(L, "cannot close standard file"); | ||
101 | return 2; | ||
102 | } | ||
103 | |||
104 | |||
105 | /* | ||
106 | ** function to close 'popen' files | ||
98 | */ | 107 | */ |
99 | static int io_pclose (lua_State *L) { | 108 | static int io_pclose (lua_State *L) { |
100 | FILE **p = topfile(L); | 109 | FILE **p = topfile(L); |
@@ -104,6 +113,9 @@ static int io_pclose (lua_State *L) { | |||
104 | } | 113 | } |
105 | 114 | ||
106 | 115 | ||
116 | /* | ||
117 | ** function to close regular files | ||
118 | */ | ||
107 | static int io_fclose (lua_State *L) { | 119 | static int io_fclose (lua_State *L) { |
108 | FILE **p = topfile(L); | 120 | FILE **p = topfile(L); |
109 | int ok = (fclose(*p) == 0); | 121 | int ok = (fclose(*p) == 0); |
@@ -129,8 +141,8 @@ static int io_close (lua_State *L) { | |||
129 | 141 | ||
130 | static int io_gc (lua_State *L) { | 142 | static int io_gc (lua_State *L) { |
131 | FILE *f = *topfile(L); | 143 | FILE *f = *topfile(L); |
132 | /* ignore closed files and standard files */ | 144 | /* ignore closed files */ |
133 | if (f != NULL && f != stdin && f != stdout && f != stderr) | 145 | if (f != NULL) |
134 | aux_close(L); | 146 | aux_close(L); |
135 | return 0; | 147 | return 0; |
136 | } | 148 | } |
@@ -155,6 +167,10 @@ static int io_open (lua_State *L) { | |||
155 | } | 167 | } |
156 | 168 | ||
157 | 169 | ||
170 | /* | ||
171 | ** this function has a separated environment, which defines the | ||
172 | ** correct __close for 'popen' files | ||
173 | */ | ||
158 | static int io_popen (lua_State *L) { | 174 | static int io_popen (lua_State *L) { |
159 | const char *filename = luaL_checkstring(L, 1); | 175 | const char *filename = luaL_checkstring(L, 1); |
160 | const char *mode = luaL_optstring(L, 2, "r"); | 176 | const char *mode = luaL_optstring(L, 2, "r"); |
@@ -502,31 +518,36 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { | |||
502 | lua_pushvalue(L, -1); | 518 | lua_pushvalue(L, -1); |
503 | lua_rawseti(L, LUA_ENVIRONINDEX, k); | 519 | lua_rawseti(L, LUA_ENVIRONINDEX, k); |
504 | } | 520 | } |
505 | lua_setfield(L, -2, fname); | 521 | lua_pushvalue(L, -2); /* copy environment */ |
522 | lua_setfenv(L, -2); /* set it */ | ||
523 | lua_setfield(L, -3, fname); | ||
524 | } | ||
525 | |||
526 | |||
527 | static void newfenv (lua_State *L, lua_CFunction cls) { | ||
528 | lua_createtable(L, 0, 1); | ||
529 | lua_pushcfunction(L, cls); | ||
530 | lua_setfield(L, -2, "__close"); | ||
506 | } | 531 | } |
507 | 532 | ||
508 | 533 | ||
509 | LUALIB_API int luaopen_io (lua_State *L) { | 534 | LUALIB_API int luaopen_io (lua_State *L) { |
510 | createmeta(L); | 535 | createmeta(L); |
511 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ | 536 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ |
512 | lua_createtable(L, 2, 1); | 537 | newfenv(L, io_fclose); |
513 | lua_replace(L, LUA_ENVIRONINDEX); | 538 | lua_replace(L, LUA_ENVIRONINDEX); |
514 | /* open library */ | 539 | /* open library */ |
515 | luaL_register(L, LUA_IOLIBNAME, iolib); | 540 | luaL_register(L, LUA_IOLIBNAME, iolib); |
516 | /* create (and set) default files */ | 541 | /* create (and set) default files */ |
542 | newfenv(L, io_noclose); /* close function for default files */ | ||
517 | createstdfile(L, stdin, IO_INPUT, "stdin"); | 543 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
518 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); | 544 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
519 | createstdfile(L, stderr, 0, "stderr"); | 545 | createstdfile(L, stderr, 0, "stderr"); |
520 | /* create environment for 'popen' */ | 546 | lua_pop(L, 1); /* pop environment for default files */ |
521 | lua_getfield(L, -1, "popen"); | 547 | lua_getfield(L, -1, "popen"); |
522 | lua_createtable(L, 0, 1); | 548 | newfenv(L, io_pclose); /* create environment for 'popen' */ |
523 | lua_pushcfunction(L, io_pclose); | 549 | lua_setfenv(L, -2); /* set fenv for 'popen' */ |
524 | lua_setfield(L, -2, "__close"); | ||
525 | lua_setfenv(L, -2); | ||
526 | lua_pop(L, 1); /* pop 'popen' */ | 550 | lua_pop(L, 1); /* pop 'popen' */ |
527 | /* set default close function */ | ||
528 | lua_pushcfunction(L, io_fclose); | ||
529 | lua_setfield(L, LUA_ENVIRONINDEX, "__close"); | ||
530 | return 1; | 551 | return 1; |
531 | } | 552 | } |
532 | 553 | ||