/*
 * Copyright (c) 2004 Chris Pressey <cpressey@catseye.mine.nu>
 *
 * Copyright (c) 2004 The DragonFly Project.
 * All rights reserved.
 *
 * This code is derived from software contributed to The DragonFly Project
 * by Chris Pressey.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. Neither the name of The DragonFly Project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific, prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS, CONTRIBUTORS OR VOICES IN THE AUTHOR'S HEAD
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/* 
 * pipe.c - aura_popen (et al.) bindings for dfuibe_lua
 * $Id: pipe.c,v 1.10 2005/01/17 08:25:50 cpressey Exp $
 */

#include <sys/types.h>

#include <signal.h>

#include <aura/popen.h>

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

#include "dfuibe_lua.h"

LUA_CHECK_FUNCTION(pipe, "Pipe", FILE *)
LUA_PUSH_FUNCTION(pipe, "Pipe", FILE *)

/*** CONSTRUCTOR/DESTRUCTOR ***/

int 
lua_pipe_open(lua_State *L)
{
	FILE *p;
	const char *cmdline;

	cmdline = luaL_checkstring(L, 1);
	p = aura_popen(cmdline, "r");
	lua_push_pipe(L, p);

	return(1);
}

/******* METHODS *******/

int
lua_pipe_close(lua_State *L)
{
	FILE *p;
	int pstat;

	p = lua_check_pipe(L, 1);
	pstat = aura_pclose(p);
	lua_pushnumber(L, pstat);

	return(1);
}

int 
lua_pipe_readline(lua_State *L)
{
	FILE *p = NULL;
	char line[8192];
	size_t len = 0;
	int err = 0;
	long msec = 0;

	line[0] = '\0';

	p = lua_check_pipe(L, 1);
	if (lua_isnumber(L, 2)) {
		msec = lua_tonumber(L, 2);
	} else {
		msec = -1;
	}

	if (aura_pgets(p, line, 8192, msec, &err)) {
		len = strlen(line);
		while (len > 0 && line[len - 1] == '\n') {
			line[--len] = '\0';
		}
		lua_pushstring(L, line);
		lua_pushnil(L);
		return(2);
	} else {
		lua_pushnil(L);
		lua_pushnumber(L, err);
		return(2);
	}
}

int 
lua_pipe_signal(lua_State *L)
{
	FILE *p;
	pid_t pid;
	int signo, result;

	p = lua_check_pipe(L, 1);
	signo = luaL_checkint(L, 2);
	pid = aura_pgetpid(p);
	result = kill(pid, signo);
	lua_pushnumber(L, result);
	
	return(1);
}

/**** Binding Tables ****/

const luaL_reg pipe_methods[] = {
	{"open",	lua_pipe_open },
	{"close",	lua_pipe_close },
	{"readline",	lua_pipe_readline },
	{"signal",	lua_pipe_signal },
	{0, 0}
};

const luaL_reg pipe_meta_methods[] = {
/*	{"__gc", 	lua_pipe_destroy }, */
	{0, 0}
};

/*** REGISTER ***/

LUA_API int
lua_pipe_register(lua_State *L)
{
	int methods_idx;

	luaL_openlib(L, "Pipe", pipe_methods, 0);		/* fill methods table */
        luaL_openlib(L, "PipeMeta", pipe_meta_methods,  0);	/* fill metatable */

	lua_set_instance_handler(L, "Pipe", "PipeMeta");

	/*
	 * Add some symbolic constants.
	 */
	lua_pushstring(L, "Pipe");
	lua_gettable(L, LUA_GLOBALSINDEX);
        methods_idx = lua_gettop(L);

        lua_pushliteral(L, "TIMEOUT");
        lua_pushnumber(L, AURA_PGETS_TIMEOUT);
        lua_settable(L, methods_idx);

        lua_pushliteral(L, "SELECT_ERR");
        lua_pushnumber(L, AURA_PGETS_SELECT_ERR);
        lua_settable(L, methods_idx);

        lua_pushliteral(L, "EOF");
        lua_pushnumber(L, AURA_PGETS_EOF);
        lua_settable(L, methods_idx);

        lua_pushliteral(L, "FGETS_ERR");
        lua_pushnumber(L, AURA_PGETS_FGETS_ERR);
        lua_settable(L, methods_idx);

        lua_pushliteral(L, "SIGTERM");
        lua_pushnumber(L, SIGTERM);
        lua_settable(L, methods_idx);

	lua_pop(L, 1);

	return(1);
}
