lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello,

Processes opened with io.popen(), are closed using io.close(), which is also
used for closing streams associated with a file.  The io.close() actually calls
pclose() and/or fclose() and returns a boolean, depending on whether the
operation was succesful.

The problem is that the pclose() C library function returns the exit status of
the command previously "opened" with popen(), but Lua's io.close() discards
this exit status.  The exit status of the command is quite useful and I was
wondering if something could be done to change this behaviour.

I made some small changes to src/lib/liolib.c, by adding a io.pclose() function
that returns two values: a boolean as io.close() does and additionally a
number, the exit status of the command.  I attach a patch that should be
applied against Lua 5.0.2.

Please let me know what do you think.

diff -ruN lua-5.0.2.orig/src/lib/liolib.c lua-5.0.2/src/lib/liolib.c
--- lua-5.0.2.orig/src/lib/liolib.c	Sat May  1 12:28:03 2004
+++ lua-5.0.2/src/lib/liolib.c	Sat May  1 21:38:44 2004
@@ -149,7 +149,7 @@
   if (f == stdin || f == stdout || f == stderr)
     return 0;  /* file cannot be closed */
   else {
-    int ok = (pclose(f) != -1) || (fclose(f) == 0);
+    int ok = (fclose(f) == 0);
     if (ok)
       *(FILE **)lua_touserdata(L, 1) = NULL;  /* mark file as closed */
     return ok;
@@ -166,6 +166,41 @@
 }
 
 
+static int aux_pclose (lua_State *L) {
+  FILE *f = tofile(L, 1);
+  if (f == stdin || f == stdout || f == stderr)
+    return 0;  /* file cannot be closed */
+  else {
+    int ok = pclose(f);
+    if (ok != -1)
+      *(FILE **)lua_touserdata(L, 1) = NULL;  /* mark file as closed */
+    return ok;
+  }
+}
+
+
+static int io_pclose (lua_State *L) {
+#if !USE_POPEN
+  luaL_error(L, "`pclose' not supported");
+  return 0;
+#else
+  int i;
+  if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) {
+    lua_pushstring(L, IO_OUTPUT);
+    lua_rawget(L, lua_upvalueindex(1));
+  }
+  i = aux_pclose(L) >> 8;
+  if (i == -1)
+    return pushresult(L, 0, NULL);
+  else {
+    pushresult(L, 1, NULL);
+    lua_pushnumber(L, (lua_Number)(i));
+    return 2;
+  }
+#endif
+}
+
+
 static int io_gc (lua_State *L) {
   FILE **f = topfile(L, 1);
   if (*f != NULL)  /* ignore closed files */
@@ -497,6 +532,7 @@
   {"flush", io_flush},
   {"open", io_open},
   {"popen", io_popen},
+  {"pclose", io_pclose},
   {"read", io_read},
   {"tmpfile", io_tmpfile},
   {"type", io_type},