/*
BOIL (Brunni's Own Interpreter Language)
(c) 1998 netEstate (http://www.netestate.de/, info@netestate.de),
Michael Brunnbauer & Markus Hendel, Gesellschaft fuer Netzwerkkommunikation bR
Am Bluetenanger 8, 80995 Muenchen, Germany

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "general.h"
#include "handles.cc"
#include "boil.h"
#include "boil.tab.h"
#include "libs.h"
#ifdef WITH_RPC
#include "rpc.h"
#endif

/* some basic things */

libfunc::libfunc(string a,
		 int b,
		 flowctrl (*c) (type_block*,
				opt* options,
				joined_list<type_value>*),
		 int* d)
{
  name=a;
  returntype=b;
  ptr=c;
  argtypes=d;
  return;
}

void instlibfunc()
{
  type_function func;
  type_arg_list_entry arg;
  type_arg_list* args;
  func.type=TYPE_FUNCTION_LIBRARY;
  unsigned long i=0,u;

  while (defined(functions[i].name))
    {
      func.name=functions[i].name;
      func.returntype=functions[i].returntype;
      func.library_ptr=functions[i].ptr;
      args=new type_arg_list();
      if (!args)
        { log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
      func.args=args;
      
      u=0;
      while (functions[i].argtypes[u])
        {
          arg.argtype=functions[i].argtypes[u];
          args->args.insert_listelem(arg,args->args.length());
          u++;
        };

      libfunctions.insert_listelem(func,func.name);
      i++;
    };

  return;
}

void handle_cleanup(opt_h* ptr_h)
{
  while (ptr_h->streams.handles.length())
    {
      /*
      signal 11 bei falschem close !!!
      if (ptr_h->streams.cleanup[0])
        {
	  fclose(ptr_h->streams.values[0]);
	  pclose(ptr_h->streams.values[0]);
        };
      */
      ptr_h->streams.cleanup.remove_listelem(0);
      ptr_h->streams.handles.remove_listelem(0);
      ptr_h->streams.values.remove_listelem(0);
    };

#ifdef WITH_POSTGRES

  while (ptr_h->pg_querys.handles.length())
    {
      if (ptr_h->pg_querys.cleanup[0])
        {
          PQclear(ptr_h->pg_querys.values[0]);
        };
      ptr_h->pg_querys.cleanup.remove_listelem(0);
      ptr_h->pg_querys.handles.remove_listelem(0);
      ptr_h->pg_querys.values.remove_listelem(0);
    };

  while (ptr_h->pg_connections.handles.length())
    {
      if (ptr_h->pg_connections.cleanup[0])
        {
          PQfinish(ptr_h->pg_connections.values[0]);
        };
      ptr_h->pg_connections.cleanup.remove_listelem(0);
      ptr_h->pg_connections.handles.remove_listelem(0);
      ptr_h->pg_connections.values.remove_listelem(0);
    };

#endif

#ifdef WITH_MSQL

  while (ptr_h->msql_querys.handles.length())
    {
      if (ptr_h->msql_querys.cleanup[0])
        {
	  if (ptr_h->msql_querys.values[0])
	    {
	      msqlFreeResult(ptr_h->msql_querys.values[0]);
	    };
        };
      ptr_h->msql_querys.cleanup.remove_listelem(0);
      ptr_h->msql_querys.handles.remove_listelem(0);
      ptr_h->msql_querys.values.remove_listelem(0);
    };

  while (ptr_h->msql_connections.handles.length())
    {
      if (ptr_h->msql_connections.cleanup[0])
        {
          msqlClose(ptr_h->msql_connections.values[0]);
        };
      ptr_h->msql_connections.cleanup.remove_listelem(0);
      ptr_h->msql_connections.handles.remove_listelem(0);
      ptr_h->msql_connections.values.remove_listelem(0);
    };

#endif

#ifdef WITH_MYSQL

  while (ptr_h->mysql_querys.handles.length())
    {
      if (ptr_h->mysql_querys.cleanup[0])
        {
          if (ptr_h->mysql_querys.values[0])
            {
              mysql_free_result(ptr_h->mysql_querys.values[0]);
            };
        };
      ptr_h->mysql_querys.cleanup.remove_listelem(0);
      ptr_h->mysql_querys.handles.remove_listelem(0);
      ptr_h->mysql_querys.values.remove_listelem(0);
    };

  while (ptr_h->mysql_connections.handles.length())
    {
      if (ptr_h->mysql_connections.cleanup[0])
        {
          mysql_close(ptr_h->mysql_connections.values[0]);
        };
      ptr_h->mysql_connections.cleanup.remove_listelem(0);
      ptr_h->mysql_connections.handles.remove_listelem(0);
      ptr_h->mysql_connections.values.remove_listelem(0);
    };
  
#endif

#ifdef WITH_RPC
  while (ptr_h->rpc_transports.handles.length())
    {
      if (ptr_h->rpc_transports.cleanup[0])
        {
          svc_unregister(ptr_h->rpc_transports.values[0].program,
                         ptr_h->rpc_transports.values[0].version);
          svc_destroy(ptr_h->rpc_transports.values[0].transport);
        };
      ptr_h->rpc_transports.cleanup.remove_listelem(0);
      ptr_h->rpc_transports.handles.remove_listelem(0);
      ptr_h->rpc_transports.values.remove_listelem(0);
    };

  while (ptr_h->rpc_clients.handles.length())
    {
      if (ptr_h->rpc_clients.cleanup[0])
        {
          clnt_destroy(ptr_h->rpc_clients.values[0]);
        };
      ptr_h->rpc_clients.cleanup.remove_listelem(0);
      ptr_h->rpc_clients.handles.remove_listelem(0);
      ptr_h->rpc_clients.values.remove_listelem(0);
    };
#endif

  while (ptr_h->sockets.handles.length())
    {
      if (ptr_h->sockets.cleanup[0])
        {
	  close(ptr_h->sockets.values[0]);
        };
      ptr_h->sockets.cleanup.remove_listelem(0);
      ptr_h->sockets.handles.remove_listelem(0);
      ptr_h->sockets.values.remove_listelem(0);
    };

  while (ptr_h->dirs.handles.length())
    {
      if (ptr_h->dirs.cleanup[0])
        {
          closedir(ptr_h->dirs.values[0]);
        };
      ptr_h->dirs.cleanup.remove_listelem(0);
      ptr_h->dirs.handles.remove_listelem(0);
      ptr_h->dirs.values.remove_listelem(0);
    };
  
  return;
}

libfunc functions[]= {

  /* standard functions */
  libfunc("printf",TYPE_VALUE_ULONG,&func_printf,args_printf),
  libfunc("sleep",TYPE_VALUE_VOID,&func_sleep,args_sleep),
  libfunc("getenv",TYPE_VALUE_STRING,&func_getenv,args_getenv),
  libfunc("setenv",TYPE_VALUE_ULONG,&func_setenv,args_setenv),
  libfunc("srandom",TYPE_VALUE_VOID,&func_srandom,args_srandom),
  libfunc("random",TYPE_VALUE_LONG,&func_random,args_random),
  libfunc("crypt",TYPE_VALUE_STRING,&func_crypt,args_crypt),
  libfunc("waitpid",TYPE_VALUE_LONG,&func_waitpid,args_waitpid),
  libfunc("sigcld",TYPE_VALUE_VOID,&func_sigcld,args_sigcld),
  libfunc("getpid",TYPE_VALUE_LONG,&func_getpid,args_getpid),
  libfunc("system",TYPE_VALUE_LONG,&func_system,args_system),

  /* time */
  libfunc("time",TYPE_VALUE_ULONG,&func_time,args_time),
  libfunc("mktime",TYPE_VALUE_ULONG,&func_mktime,args_mktime),
  libfunc("strftime",TYPE_VALUE_STRING,&func_strftime,args_strftime),

  /* files and directorys */
  libfunc("fileatime",TYPE_VALUE_ULONG,&func_fileatime,args_fileatime),
  libfunc("filemtime",TYPE_VALUE_ULONG,&func_filemtime,args_filemtime),
  libfunc("unlink",TYPE_VALUE_ULONG,&func_unlink,args_unlink),
  libfunc("tmpnam",TYPE_VALUE_STRING,&func_tmpnam,args_tmpnam),
  libfunc("opendir",TYPE_VALUE_LONG,&func_opendir,args_opendir),
  libfunc("readdir",TYPE_VALUE_STRING,&func_readdir,args_readdir),
  libfunc("closedir",TYPE_VALUE_ULONG,&func_closedir,args_closedir),
  libfunc("mkdir",TYPE_VALUE_ULONG,&func_mkdir,args_mkdir),
  libfunc("rmdir",TYPE_VALUE_ULONG,&func_rmdir,args_rmdir),
  libfunc("rename",TYPE_VALUE_ULONG,&func_rename,args_rename),

  /* CGI */
  libfunc("cgiwrap",TYPE_VALUE_ULONG,&func_cgiwrap,args_cgiwrap),
  libfunc("getpost",TYPE_VALUE_ULONG,&func_getpost,args_getpost),
  libfunc("postdata",TYPE_VALUE_ULONG,&func_postdata,args_postdata),
  libfunc("file_upload",TYPE_VALUE_STRING,&func_file_upload,args_file_upload),
  libfunc("htmlenc",TYPE_VALUE_STRING,&func_htmlenc,args_htmlenc),
  libfunc("phtmlenc",TYPE_VALUE_ULONG,&func_phtmlenc,args_phtmlenc),
  libfunc("fullhtmlenc",TYPE_VALUE_STRING,&func_fullhtmlenc,args_fullhtmlenc),

  /* functions that affect internal things */
  libfunc("exit",TYPE_VALUE_VOID,&func_exit,args_exit),
  libfunc("isset",TYPE_VALUE_ULONG,&func_isset,args_isset),
  libfunc("isfunc",TYPE_VALUE_ULONG,&func_isfunc,args_isfunc),
  libfunc("deletefunc",TYPE_VALUE_ULONG,&func_deletefunc,args_deletefunc),
  libfunc("deletevar",TYPE_VALUE_ULONG,&func_deletevar,args_deletevar),
  libfunc("parse",TYPE_VALUE_ULONG,&func_parse,args_parse),

  /* locking */
  libfunc("do_lock",TYPE_VALUE_LONG,&func_do_lock,args_do_lock),
  libfunc("do_unlock",TYPE_VALUE_LONG,&func_do_unlock,args_do_unlock),

  /* strings */
  libfunc("defined",TYPE_VALUE_ULONG,&func_defined,args_defined),
  libfunc("strstr",TYPE_VALUE_STRING,&func_strstr,args_strstr),
  libfunc("strtok",TYPE_VALUE_STRING,&func_strtok,args_strtok),
  libfunc("token",TYPE_VALUE_STRING,&func_token,args_token),
  libfunc("strtok_esc",TYPE_VALUE_STRING,&func_strtok_esc,args_strtok_esc),
  libfunc("token_esc",TYPE_VALUE_STRING,&func_token_esc,args_token_esc),
  libfunc("strtolower",TYPE_VALUE_STRING,&func_strtolower,args_strtolower),
  libfunc("strtoupper",TYPE_VALUE_STRING,&func_strtoupper,args_strtoupper),
  libfunc("substr",TYPE_VALUE_STRING,&func_substr,args_substr),
  libfunc("strlen",TYPE_VALUE_ULONG,&func_strlen,args_strlen),
  libfunc("escape",TYPE_VALUE_STRING,&func_escape,args_escape),
  libfunc("unescape",TYPE_VALUE_STRING,&func_unescape,args_unescape),
  libfunc("escape1",TYPE_VALUE_STRING,&func_escape1,args_escape1),
  libfunc("unescape1",TYPE_VALUE_STRING,&func_unescape1,args_unescape1),
  libfunc("textfile",TYPE_VALUE_STRING,&func_textfile,args_textfile),
  libfunc("getchar",TYPE_VALUE_ULONG,&func_getchar,args_getchar),
  libfunc("sql_escape",TYPE_VALUE_STRING,&func_sql_escape,args_sql_escape),

  /* streams */
  libfunc("fopen",TYPE_VALUE_LONG,&func_fopen,args_fopen),
  libfunc("popen",TYPE_VALUE_LONG,&func_popen,args_popen),
  libfunc("exec",TYPE_VALUE_ULONG,&func_exec,args_exec),
  libfunc("feof",TYPE_VALUE_LONG,&func_feof,args_feof),
  libfunc("fgets",TYPE_VALUE_STRING,&func_fgets,args_fgets),
  libfunc("fputs",TYPE_VALUE_ULONG,&func_fputs,args_fputs),
  libfunc("fclose",TYPE_VALUE_ULONG,&func_fclose,args_fclose),
  libfunc("pclose",TYPE_VALUE_LONG,&func_pclose,args_pclose),
  libfunc("fflush",TYPE_VALUE_ULONG,&func_fflush,args_fflush),
  libfunc("setoutstream",TYPE_VALUE_ULONG,&func_setoutstream,
	  args_setoutstream),

#ifdef WITH_POSTGRES

  /* postgres */
  libfunc("pg_close",TYPE_VALUE_ULONG,&func_pg_close,args_pg_close),
  libfunc("pg_connect",TYPE_VALUE_LONG,&func_pg_connect,args_pg_connect),
  libfunc("pg_exec",TYPE_VALUE_LONG,&func_pg_exec,args_pg_exec),
  libfunc("pg_freeresult",TYPE_VALUE_ULONG,&func_pg_freeresult,
	  args_pg_freeresult),
  libfunc("pg_numfields",TYPE_VALUE_ULONG,&func_pg_numfields,
	  args_pg_numfields),
  libfunc("pg_numrows",TYPE_VALUE_ULONG,&func_pg_numrows,args_pg_numrows),
  libfunc("pg_fieldname",TYPE_VALUE_STRING,&func_pg_fieldname,
	  args_pg_fieldname),
  libfunc("pg_fieldtype",TYPE_VALUE_STRING,&func_pg_fieldtype,
	  args_pg_fieldtype),
  libfunc("pg_result",TYPE_VALUE_STRING,&func_pg_result,args_pg_result),

#endif

#ifdef WITH_MSQL

  /* msql */
  libfunc("msql_close",TYPE_VALUE_ULONG,&func_msql_close,args_msql_close),
  libfunc("msql_connect",TYPE_VALUE_LONG,&func_msql_connect,args_msql_connect),
  libfunc("msql_selectdb",TYPE_VALUE_LONG,&func_msql_selectdb,
	  args_msql_selectdb),
  libfunc("msql_exec",TYPE_VALUE_LONG,&func_msql_exec,args_msql_exec),
  libfunc("msql_freeresult",TYPE_VALUE_ULONG,&func_msql_freeresult,
          args_msql_freeresult),
  libfunc("msql_numfields",TYPE_VALUE_ULONG,&func_msql_numfields,
          args_msql_numfields),
  libfunc("msql_numrows",TYPE_VALUE_ULONG,&func_msql_numrows,
	  args_msql_numrows),
  libfunc("msql_result",TYPE_VALUE_STRING,&func_msql_result,args_msql_result),
  libfunc("msql_fieldtype",TYPE_VALUE_LONG,&func_msql_fieldtype,
	  args_msql_fieldtype),
  libfunc("msql_fieldname",TYPE_VALUE_STRING,&func_msql_fieldname,
          args_msql_fieldname),

#endif

#ifdef WITH_MYSQL

  /* mysql */
  libfunc("mysql_close",TYPE_VALUE_ULONG,&func_mysql_close,args_mysql_close),
  libfunc("mysql_connect",TYPE_VALUE_LONG,&func_mysql_connect,
	  args_mysql_connect),
  libfunc("mysql_selectdb",TYPE_VALUE_LONG,&func_mysql_selectdb,
          args_mysql_selectdb),
  libfunc("mysql_exec",TYPE_VALUE_LONG,&func_mysql_exec,args_mysql_exec),
  libfunc("mysql_freeresult",TYPE_VALUE_ULONG,&func_mysql_freeresult,
          args_mysql_freeresult),
  libfunc("mysql_numfields",TYPE_VALUE_ULONG,&func_mysql_numfields,
          args_mysql_numfields),
  libfunc("mysql_numrows",TYPE_VALUE_ULONG,&func_mysql_numrows,
          args_mysql_numrows),
  libfunc("mysql_result",TYPE_VALUE_STRING,&func_mysql_result,
	  args_mysql_result),
  libfunc("mysql_fieldtype",TYPE_VALUE_LONG,&func_mysql_fieldtype,
          args_mysql_fieldtype),
  libfunc("mysql_fieldname",TYPE_VALUE_STRING,&func_mysql_fieldname,
          args_mysql_fieldname),

#endif

  /* sockets */
  libfunc("makesock",TYPE_VALUE_LONG,&func_makesock,args_makesock),
  libfunc("closesock",TYPE_VALUE_ULONG,&func_closesock,args_closesock),

#ifdef WITH_RPC

  /* RPC */
  libfunc("clnt_create",TYPE_VALUE_LONG,&func_clnt_create,args_clnt_create),
  libfunc("clnt_timeout",TYPE_VALUE_ULONG,&func_clnt_timeout,
	  args_clnt_timeout),
  libfunc("clnt_udp_retry",TYPE_VALUE_ULONG,&func_clnt_udp_retry,
          args_clnt_udp_retry),
  libfunc("clnt_destroy",TYPE_VALUE_ULONG,
	  &func_clnt_destroy,args_clnt_destroy),
  libfunc("svc_register",TYPE_VALUE_LONG,&func_svc_register,args_svc_register),
  libfunc("svc_run",TYPE_VALUE_LONG,&func_svc_run,args_svc_run),
  libfunc("svc_unregister",TYPE_VALUE_ULONG,&func_svc_unregister,
	  args_svc_unregister),

#endif

  /* userdefined functions */
  libfunc("tcache_get",TYPE_VALUE_STRING,&func_tcache_get,args_tcache_get),
  libfunc("tcache_set",TYPE_VALUE_VOID,&func_tcache_set,args_tcache_set),
  libfunc("tcache_del",TYPE_VALUE_VOID,&func_tcache_del,args_tcache_del),
  libfunc("tcache_setsize",TYPE_VALUE_VOID,&func_tcache_setsize,
	  args_tcache_setsize),
  libfunc("tcache_getsize",TYPE_VALUE_ULONG,&func_tcache_getsize,
          args_tcache_getsize),

  libfunc(NULL,0,NULL,NULL)
};
