lua-users home
lua-l archive

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


Hello Lua,

  I was looking for a way to be able to redirect standard input/output
to  a file. As I couldn't find a way to do this from Lua, nor too much
information  on  this list, I thought I'd give it a shot at writing my
first  module.  The  result is attached, and I can't figure out what I
did wrong (because an obvious lack of experience and maybe not reading
enough documentation,  I must admit).
  test.lua  should load the module, redirect stdout to 'test.txt' then
output  some  text.  But  the  actual  behavior  is far from expected:
'text.txt'  is indeed created and output no longer goes to the screen,
but   it  doesn't  go  to  text.txt  either.  And  upon  closing  the
interpreter,  it  crashes  because  of  an access violation (output is
unbuffered,  so this should not be the reason for text.txt being empty
in the end).
  If  anyone  could  give  me  a  hint on this one, it would be highly
appreciated.

-- 
Theodor-Iulian Ciobanu
Virus Researcher

e-mail: tciobanu@bitdefender.com

-----------------------------------------
Secure your every bit
-----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

//** See Copyright Notice in lua.h
static int pushresult (lua_State *L, int i, const char *filename) {
  int en = errno;  /* calls to Lua API may change this value */
  if (i) {
    lua_pushboolean(L, 1);
    return 1;
  }
  else {
    lua_pushnil(L);
    if (filename)
      lua_pushfstring(L, "%s: %s", filename, strerror(en));
    else
      lua_pushfstring(L, "%s", strerror(en));
    lua_pushinteger(L, en);
    return 3;
  }
}

//** See Copyright Notice in lua.h
static FILE **newfile (lua_State *L) {
  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
  *pf = NULL;  /* file handle is currently `closed' */
  luaL_getmetatable(L, LUA_FILEHANDLE);
  lua_setmetatable(L, -2);
  return pf;
}

static int lredirectstd(lua_State *L, FILE *stdfile, char *defmode)
{
  const char *path = luaL_checklstring(L,1,NULL);
  const char *mode = luaL_optstring(L,2,defmode);
  FILE **pf;

  if (!path||!mode)
    lua_pushnil(L);

  **pf=newfile(L);
  *pf=freopen(path,mode,stdfile);
  if (*pf==NULL)
    return pushresult(L,0,path);
  else if (setvbuf(*pf,NULL,_IONBF,0)!=0)
	return pushresult(L,0,path);

  return 1;
}

static int lredirectin(lua_State *L)
{
  return lredirectstd(L,stdin,"r");
}

static int lredirectout(lua_State *L)
{
  return lredirectstd(L,stdout,"w");
}

static int lredirecterr(lua_State *L)
{
  return lredirectstd(L,stderr,"w");
}

static void set_info(lua_State *L)
{
  lua_pushliteral(L,"_VERSION");
  lua_pushliteral(L,"0.1");
  lua_settable(L,-3);
}

static struct luaL_reg stdredirlib[] = {
  {"in", lredirectin},
  {"out", lredirectout},
  {"err", lredirecterr},
  {NULL, NULL}
};

LUALIB_API int luaopen_stdredir(lua_State *L)
{
  luaL_register(L,"stdredir",stdredirlib);
  set_info(L);
  return 1;
}

Attachment: test.lua
Description: Binary data