libcon provide the low level functions to deal with memory allocation, strings, sockets, zlib compression, simple XML parsing, and module dynamic loading.

Together with the binary module system, it acts as an abstraction layer for the operating system, allowing to quickly build safe, lightweight, performant and portable distributed applications.

The full source code for libcon is on the github libcon



Memory allocation is based on area that represent application's thread heap, host memory is statically allocated for each thread in the pool when the application initialize, and the internal allocator give the application a reference to a zone in its area, and manage garbage collection.

Each thread have their own heap, and manage it locally, which make the multi thread memory management entierely lockless.

The API to allocate new memory and get a reference to the allocated pointer is found in libcon/base/mem_base.h


libcon/base/mem_base.c

void init_default_mem_area (unsigned int size);

Initalize the default memory area for the current thread to the specified size.

init_default_mem_area (4*1024*1024);


unsigned int allocate_new_zone (unsigned int area_id, mem_size zone_size, mem_zone_ref *zone_ref);

Allocate a new zone with the specified size in the specified area, and return the reference to it in zone_ref.
If 0 is specified for area id, it will allocate the memory from the default memory area for the thread.

mem_zone_ref myref={PTR_NULL};

allocate_new_zone ( get_mem_area_id() ,256, &myref);


mem_ptr get_zone_ptr (mem_zone_ref_const_ptr ref,mem_size ofset);

Get the memory address of the area referenced by the reference.

mem_zone_ref myref={PTR_NULL};
mem_ptr my_ptr;

allocate_new_zone (get_mem_area_id(), 256, &myref);

my_ptr = get_zone_ptr(&myref, 0);


mem_size get_zone_size (mem_zone_ref_const_ptr ref);

Get the allocated size of the memory area referenced by the reference

mem_zone_ref myref={PTR_NULL}; mem_size my_size;

allocate_new_zone (get_mem_area_id(), 256, &myref);

my_size = get_zone_size(&myref);


unsigned int get_zone_numref (mem_zone_ref *zone_ref);

Get the number of reference for this area

mem_zone_ref myref={PTR_NULL}; unsigned int n_refs;

allocate_new_zone (get_mem_area_id(), 256, &myref);

n_refs = get_zone_numref(&myref);


void release_zone_ref (mem_zone_ref_ptr zone_ref);

Release reference to a memory area, free the memory if the reference count reach zero, and set the reference to null. Unused when the heap use Mark and Sweep garbage collection.

mem_zone_ref myref={PTR_NULL};

allocate_new_zone (get_mem_area_id(), 256, &myref);

release_zone_ref(&myref);


int realloc_zone (mem_zone_ref *zone_ref,mem_size new_size);

Reallocate the zone to the specified size. The allocator will always try to allocate adjacent free zone to avoid memory relocation when possible.

mem_zone_ref myref={PTR_NULL};

allocate_new_zone (get_mem_area_id(), 256, &myref);

realloc_zone(&myref, 512);


int expand_zone (mem_zone_ref *ref,mem_size new_size);

Expand the zone to the minimum specified size, and expand logarithmically the memory until it fit the required size.

mem_zone_ref myref={PTR_NULL};

allocate_new_zone (get_mem_area_id(), 256, &myref);

expand_zone(&myref,512);


void copy_zone_ref (mem_zone_ref_ptr dest_zone_ref,mem_zone_ref_const_ptr zone_ref);

Copy the reference to another reference and manage atomic reference count when the heap use reference counting.

mem_zone_ref myref={PTR_NULL}, myrefcopy={PTR_NULL};

allocate_new_zone (get_mem_area_id(), 256, &myref);

copy_zone_ref(&myrefcopy, &myref);

release_zone_ref(&myref); // (myref memory is not freed until the myrefcopy reference is released.)


Equivalent to the standard LIBC API to allocate direct pointer is defined in libcon/base/std_mem.h

LIBC_API mem_ptr C_API_FUNC malloc_c (mem_size sz);

LIBC_API mem_ptr C_API_FUNC calloc_c (mem_size sz,mem_size blk);

LIBC_API mem_ptr C_API_FUNC realloc_c (mem_ptr ptr,mem_size sz);

LIBC_API void C_API_FUNC free_c (mem_ptr ptr);

The base api to manipulate strings is found in libcon/include/strs.h


libcon/strs.c

void init_string (struct string *str);

Initialize string structure

struct string mystring;

init_string(&string); ( equivalent to struct string mystring={PTR_NULL}; )


void free_string (struct string *str);

Free string memory

struct string mystring={PTR_NULL};

make_string(&mystring,"hello world");

free_string(&mystring);


int prepare_new_data (struct string *str, size_t len);

Preallocate string memory

struct string mystring={PTR_NULL};

prepare_new_data(&string, 64);


int make_string (struct string *str, const char *toto);

Create string from C string. Free target string memory if not null.

struct string mystring={PTR_NULL};

make_string(&mystring,"hello world");

log_output(mystring.str); => "hello world"


make_cstring (const struct string *str, char *toto, size_t len);

Output string to C string.

struct string mystring={PTR_NULL}; char mycstring[64];

make_string(&mystring,"hello world");

make_cstring(&mystring,mycstring,64);

log_output(mycstring); => "hello world"


int make_string_l (struct string *str, const char *toto, size_t len);

Create string with max n chars from C string. Free target string memory if not null.

struct string mystring={PTR_NULL};

make_string_l(&mystring,"hello world",4);

log_output(mystring.str); => "hell"


int make_string_url (struct string *str, const char *toto, size_t len);

Create url encoded string with n chars from C string. Free target string memory if not null.

struct string mystring={PTR_NULL};

make_string_url(&mystring,"hello world",8);

log_output(mystring.str); => "hello%wo"


int make_string_from_url (struct string *str, const char *toto, size_t len);

Create string with n chars from url encoded C string. Free target string memory if not null.

struct string mystring={PTR_NULL};

make_string_from_url(&mystring,"hello%world",8);

log_output(mystring.str); => "hello wo"


struct host_def *make_host_def(const char *host, unsigned short port);

Create an host def structure from the host name and port. Return PTR_NULL in case of failure. Returned pointer must be freed by caller.

struct host_def *myhost=PTR_NULL;

myhost=make_host_def("google.com",80);


void free_host_def (struct host_def *host);

free host def structure memory.

struct host_def *myhost=PTR_NULL;

myhost=make_host_def("google.com",80);

free_host_dest(myhost)


int clone_string (struct string *str, const struct string *str1);

Clone input string to target (do not free target string)

struct string mystring={PTR_NULL};

struct string myclonedstring={PTR_NULL};

make_string(&mystring,"hello world");

clone_string(&myclonedstring,&mystring);


int make_string_from_uint(struct string *str, size_t i);

Create base 10 string from unsigned int

struct string mystring={PTR_NULL};

make_string_from_uint(&mystring,42);

log_output(mystring.str); => "42"


cat_string (struct string *str, const struct string *src);

Create base 10 string from unsigned int

struct string mystring={PTR_NULL};

struct string myotherstring={PTR_NULL};

make_string(&mystring,"hello ");

make_string(&myotherstring,"world");

cat_string(&mystring,&myotherstring);

log_output(mystring.str); => "hello world"


cat_cstring (struct string *str, const char *src);

Concatenate input C string to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello ");

cat_cstring(&mystring,"world");

log_output(mystring.str); => "hello world"


cat_ncstring (struct string *str, const char *src, size_t src_len);

Concatenate input n chars from C string to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello ");

cat_ncstring(&mystring,"world",3);

log_output(mystring.str); => "hello wor"


cat_cstring_p (struct string *str, const char *src);

Concatenate path seperator and input from C string to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello");

cat_cstring_p(&mystring,"world");

log_output(mystring.str); => "hello/world" or "hello\world"


cat_ncstring_p (struct string *str, const char *src, size_t src_len);

Concatenate path seperator and input n chars from C string to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello");

cat_ncstring_p(&mystring,"world",3);

log_output(mystring.str); => "hello/wor" or "hello\wor"


strcat_uint (struct string *str, size_t i);

Concatenate input unsigned integer to base 10 string in target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello ");

strcat_uint(&mystring,42);

log_output(mystring.str); => "hello 42"


strcat_int (struct string *str, int i);

Concatenate input signed integer to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello ");

strcat_int(&mystring,-42);

log_output(mystring.str); => "hello -42"


strcat_float (struct string *str, double f);

Concatenate input float to target

struct string mystring={PTR_NULL};

make_string(&mystring,"hello ");

strcat_float(&mystring,3.1459);

log_output(mystring.str); => "hello 3.1459"


The base api to manipulate files is found in libcon/include/fsio.h


libcon/win32/stat_file.c and libcon/unix/stat_file.c

int stat_file(const char *path);

Return 0 if file system entry exist, non zero if not.

if(stat_file("myfile.txt")==0)

log_output("entry exist in the file system.");


int get_file(const char *path, unsigned char **data, size_t *data_len);

Read whole file into a buffer. Caller need to free the buffer.

unsigned char *data; size_t size;

if(get_file("myfile.txt",&data,&size)>0)

{

log_output(data);

free_c(data);

}


int put_file(const char *path, void *data, size_t data_len);

Write the whole buffer into the file.

put_file("myfile.txt", "hello world", 12);


size_t file_size(const char *path);

Return size of the file.


size_t size;

size=file_size("myfile.txt");


int append_file(const char *path, const void *data, size_t data_len);

Return size of the file.


put_file("myfile.txt","hello ",6);

append_file("myfile.txt","world",5);


int truncate_file(const char *path, size_t ofset, const void *data, size_t data_len);

Truncate file to specified length, and optionally append new data at this position.


put_file("myfile.txt","hello ",6);

truncate_file("myfile.txt",4," world",3)

"myfile.txt" => "hell wor"

truncate_file("myfile.txt",4,PTR_NULL,0)

"myfile.txt" => "hell"


int move_file(const char *ipath,const char *opath);

Move file from source path to destination path.


move_file("myfile.txt","myotherfile.txt");


int del_file(const char *path);

Remove file from file system.


del_file("myfile.txt");


ctime_t get_time_c(void);

Get current time as unix timestamp in second.


ctime_t mytime;

mytime=get_time_c();


ctime_t get_system_time_c(void);

Get system high precision timer as millisec elapsed since boot.


ctime_t mytime;

get_system_time_c(&mytime);


int set_ftime(const char *path, ctime_t time);

Set file time


ctime_t mytime;

mytime=gettime_c();

set_ftime("myfile.txt",mytime);


int set_ftime(const char *path, ctime_t *time);

Set file time


ctime_t mytime;

get_ftime("myfile.txt",&mytime);


int create_dir(const char *path);

Create new directory on the local file system


create_dir("mynewdir");


int del_dir(const char *path);

Remove empty directory from the local file system


del_dir("mynewdir");


int rm_dir(const char *dir);

Remove directory and sub files / empty directory from the local file system


rm_dir("mynewdir");


int get_sub_dirs(const char *path, struct string *dir_list);

Get list of subdirectory from a specified path.


struct string dir_list={PTR_NULL};

get_sub_dirs("mynewdir",&dir_list);

free_string(&dir_list);


int get_sub_files(const char *path, struct string *file_list);

Get list of file in the directory at specified path.


struct string file_list={PTR_NULL};

get_sub_files("mynewdir",&file_list);

free_string(&file_list);


set_cwd(const char *path);

Set current working directory.


set_cwd("mynewdir");


get_cwd (char *path, size_t len);

Get current working directory.


char mycwd[256];

get_cwd(mycwd,256);


void console_print(const char *msg);

Output string to stdio/console


console_print("hello world");


int log_output(const char *data);

Output string to log


log_output("hello world");


The base api to manipulate sockect is found in libcon/include/connect.h

It support both blocking and non blocking io, and uPnp.

libcon/win32/connect.c and libcon/unix/connect.c

int network_init ();

Initialize network API.

network_init();


int network_free();

Free resources used by the network API.

network_free();


get_if(const char *gw_ip, struct string *name, struct string *ip);

Get the name and ip of the local interface connected to the speciefied gateway.

struct string if_name={PTR_NULL},if_ip={PTR_NULL};;

get_if("192.168.1.1", &if_name, &if_ip);


struct con *do_connect(const struct host_def *host);

Open connection to the specified host.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);


char *readline(struct con *Con, ctime_t timeout);

Read a line from the opened connection, and block until the specified timeout.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

readline(mycon,10);


int read_data(struct con *Con, size_t max);

Syncrhonously read 'max' bytes from the opened connection. Return number of byte read, or -1 in case of error.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

int size;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

size=read_data(mycon,4096);


int read_av_data(struct con *Con, size_t max);

Read 'max' bytes from the opened connection using non blocking i/o. Return number of byte read, or -1 in case of error.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

int size;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

size=read_av_data(mycon,4096);


int send_data(struct con *Con, unsigned char *data, size_t len);

Synchronously write 'max' bytes to the opened connection. Return number of byte wrote, or -1 in case of error.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

int size;

struct mystring={PTR_NUL};

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

make_string(&mystring,"hello world");

size=send_data(mycon,mystring.str,mystring.len);


int send_data_av(struct con *Con, unsigned char *data, size_t len);

Write 'max' bytes to the opened connection using non blocking i/o. Return number of byte wrote, or -1 in case of error.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

int size;

struct mystring={PTR_NUL};

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

make_string(&mystring,"hello world");

size=send_data_av(mycon,mystring.str,mystring.len);


const struct string* get_con_error(struct con *Con);

Return a constant pointer to the connection error string.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

struct string *error=PTR_NUL;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

error=get_con_error(mycon);


int con_consume_data(struct con *Con, size_t mov_len);

Shift the connection data buffer of the specified amount of byte. This function is not thread safe.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

struct string *data=PTR_NUL;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

readline(mycon,10);

data=get_con_lastline(mycon);

con_consume_data(mycon,data->len);


int reconnect(struct con *mycon);

Attempt to reconnect the host, when read or write operation return an error.

struct host_def *myhost=PTR_NULL;

struct con *mycon;

int size;

myhost=make_host_def("google.com",80);

mycon=do_connect(myhost);

size=send_data(mycon,"hello",5);

if(size<0){reconnect(mycon);}


struct con * open_port(const char *my_addr, unsigned short port);

Open a port on the local system using the specified address, and return the connection.

struct con *mycon;

int size;

mycon=open_port("127.0.0.1",80);


struct con *do_get_incoming(struct con *listen_con, unsigned int time_out);

Return newly opened connection, or PTR_NULL if there is no new connection.

struct con *mycon;

>

struct con *netcon;

int size;

mycon=open_port("127.0.0.1",80);

netcon=do_get_incoming(mycon,10)


void con_close(struct con *Con);

Close the connection and free the memory.

struct con *mycon;

struct con *netcon;

int size;

mycon=open_port("127.0.0.1",80);

netcon=do_get_incoming(mycon,10)

size=read_data(netcon,1024);

con_close(netcon);


The base api to manipulate modules is found in libcon/include/tpo_mod.h

libcon/tpo_mod.c

void tpo_mod_init(tpo_mod_file *driver);

Initialize tpo module memory.

tpo_mod_file mod;

tpo_mod_init(&mod);


int tpo_mod_load_tpo(mem_stream *file_stream, tpo_mod_file *tpo_file, unsigned int imp_func_addr);

Initialize the module from the binary image.

tpo_mod_file mod;

struct mem_stream modstrm;

get_file_to_memstream("modz/libbase.tpo", &modstrm);

tpo_mod_init(&mod);

tpo_mod_load_tpo(&modstrm,&mod, 0);

mem_stream_close(&modstrm);


void_func_ptr tpo_mod_get_exp_addr(mem_stream *file_stream, const char *sym)

Get the address of exported function from the module in the binary image.

struct mem_stream modstrm;

void_func_ptr my_func;

get_file_to_memstream("modz/libbase.tpo", &modstrm);

my_func=tpo_mod_get_exp_addr(&modstrm,"my_func");


void register_tpo_exports(tpo_mod_file *tpo_mod, const char *mod_name);

Make the exported symbols visible to the dynamic linker. Other module can then import the symbol based on linker definition.

struct mem_stream modstrm;

get_file_to_memstream("modz/libbase.tpo", &modstrm);

tpo_mod_init(&mod);

tpo_mod_load_tpo(&modstrm,&mod, 0);

mem_stream_close(&modstrm);

register_tpo_exports(&mod,"my_mod");


int load_module(const char *file, const char *mod_name, tpo_mod_file *mod);

Initialize the module from file system image, and make its exported symbol visible to the linker.

tpo_mod_file mod;

load_module("modz/libbase.tpo","libbase",&mod);


void_func_ptr get_tpo_mod_exp_addr_name(const tpo_mod_file *tpo_mod, const char *name, unsigned int deco_type);

Get the address of exported function from the module in memory.

tpo_mod_file mod;

void_func_ptr my_func;

tpo_mod_init(&mod);

load_module("modz/libbase.tpo", &mod);

my_func=tpo_mod_get_exp_addr(&mod,"my_func",0);


int execute_script_mod_call(tpo_mod_file *tpo_mod, const char *method);

Execute the module function with no arguments. Return 0 if the function return failure state, 1 if the function return success state, -1 if the function call didn't happen.

tpo_mod_file mod;

tpo_mod_init(&mod);

load_module("modz/libbase.tpo", &mod);

execute_script_mod_call(&mod,"my_func");


execute_script_mod_rcall(tpo_mod_file *tpo_mod, const char *method, mem_zone_ref_ptr input);

Execute the module function with one argument. Return 0 if the function return failure state, 1 if the function return success state, -1 if the function call didn't happen.

tpo_mod_file mod;

mem_zone_ref input={PTR_NULL}

tpo_mod_init(&mod);

load_module("modz/libbase.tpo", &mod);

tree_manager_create_node("param",NODE_GFX_INT,&input);

tree_manager_write_node_dword(&input,0,42);

execute_script_mod_rcall(&mod,"my_func",&input);


execute_script_mod_rcall(tpo_mod_file *tpo_mod, const char *method, mem_zone_ref_ptr input, mem_zone_ref_ptr output);

Execute the module function with two arguments. Return 0 if the function return failure state, 1 if the function return success state, -1 if the function call didn't happen.

tpo_mod_file mod;

mem_zone_ref input={PTR_NULL},output={PTR_NULL};

tpo_mod_init(&mod);

load_module("modz/libbase.tpo", &mod);

tree_manager_create_node("param",NODE_GFX_INT,&input);

tree_manager_write_node_dword(&input,0,42);

execute_script_mod_rwcall(&mod,"my_func",&input,&output);


Launcher

The source code of the nodix blockchain launcher loading the nodix.node script is on the github Nodix launcher on github

Example C code using libcon to run an application.

#include <base/std_def.h>

#include <base/std_mem.h>

#include <base/mem_base.h>

#include <base/std_str.h>


#include <strs.h>

#include <connect.h>

#include <mem_stream.h>

#include <tpo_mod.h>

#include <fsio.h>



typedef int C_API_FUNC app_func(mem_zone_ref_ptr params);

typedef void C_API_FUNC tree_manager_init_func(size_t size);

typedef int C_API_FUNC load_script_func(const char *file, mem_zone_ref_ptr script_vars, unsigned int opt);

typedef int C_API_FUNC resolve_script_var_func(mem_zone_ref_ptr script_vars, mem_zone_ref_ptr script_proc, const char *var_path, unsigned int var_type, mem_zone_ref_ptr out_var, mem_zone_ref_ptr pout_var);

typedef int C_API_FUNC get_script_var_value_str_func(mem_zone_ref_ptr global_vars, const char *var_path, struct string *out, unsigned int radix);

typedef int C_API_FUNC get_script_var_value_ptr_func(mem_zone_ref_ptr global_vars, const char *var_path, mem_ptr *out);

typedef int C_API_FUNC execute_script_proc_func(mem_zone_ref_ptr global_vars, mem_zone_ref_ptr proc);


typedef app_func *app_func_ptr;

typedef load_script_func *load_script_func_ptr;

typedef resolve_script_var_func *resolve_script_var_func_ptr;

typedef get_script_var_value_str_func *get_script_var_value_str_func_ptr;

typedef get_script_var_value_ptr_func *get_script_var_value_ptr_func_ptr;

typedef execute_script_proc_func *execute_script_proc_func_ptr;

typedef tree_manager_init_func *tree_manager_init_func_ptr;


load_script_func_ptr load_script = PTR_INVALID;

resolve_script_var_func_ptr resolve_script_var = PTR_INVALID;

get_script_var_value_str_func_ptr get_script_var_value_str = PTR_INVALID;

get_script_var_value_ptr_func_ptr get_script_var_value_ptr = PTR_INVALID;

execute_script_proc_func_ptr execute_script_proc = PTR_INVALID;

tree_manager_init_func_ptr tree_manager_init = PTR_INVALID;


app_func_ptr app_init = PTR_INVALID , app_start = PTR_INVALID , app_loop = PTR_INVALID , app_stop = PTR_INVALID;


tpo_mod_file libbase_mod = { 0xDEF00FED };



int main( int argc , const char ** argv)

{

struct string node_name = { PTR_NULL },data_dir={ PTR_NULL};

mem_zone_ref params = { PTR_NULL }, script_vars = { PTR_NULL }, init_node_proc = { PTR_NULL };

const_mem_ptr *params_ptr;

tpo_mod_file *nodix_mod;

int done = 0,n;


init_mem_system ();

init_default_mem_area (24 * 1024 * 1024);

set_exe_path ();

network_init ();


create_def();


tpo_mod_init (&libbase_mod);

load_module ("modz/libbase.tpo" , "libbase" , &libbase_mod);


load_script = ( load_script_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "load_script" , 0);

resolve_script_var = ( resolve_script_var_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "resolve_script_var" , 0);

get_script_var_value_str = ( get_script_var_value_str_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "get_script_var_value_str" , 0);;

get_script_var_value_ptr = ( get_script_var_value_ptr_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "get_script_var_value_ptr" , 0);;

execute_script_proc = ( execute_script_proc_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "execute_script_proc" , 0);;

tree_manager_init = ( tree_manager_init_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "tree_manager_init" , 0);;




tree_manager_init (16 * 1024 * 1024);

load_script ( "nodix.node" , &script_vars,3);

if (!get_script_var_value_str(&script_vars, "configuration.name" , &node_name, 0))

make_string(&node_name, "nodix");


if (get_script_var_value_str(&script_vars, "SelfNode.data_dir" , &data_dir, 0))

{

set_data_dir (&data_dir, "nodix");

free_string (&data_dir);

}

else

{

if (!set_home_path(node_name.str))

{

console_print( "could not set home dir 'nodix' \n" );

return 0;

}

}


get_script_var_value_ptr(&script_vars, "nodix.mod_ptr" , ( mem_ptr *)&nodix_mod);

resolve_script_var (&script_vars, PTR_NULL , "init_node" , 0xFFFFFFFF, &init_node_proc, PTR_NULL);


app_init = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_init" , 0);

app_start = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_start" , 0);

app_loop = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_loop" , 0);

app_stop = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_stop" , 0);


if (!app_init(&script_vars))

{

console_print( "could not initialize app " );

console_print(nodix_mod->name);

console_print("\n");

return 0;

}

if (!execute_script_proc(&script_vars, &init_node_proc))

{

console_print( "could not execute script initialization routine." );

return 0;

}

if (daemonize(node_name.str) <= 0)

{

console_print( "daemonize failed \n" );

return 0;

}

if ( argc > 1)

{

allocate_new_zone(0, argc*sizeof(mem_ptr ), &params);

for (n = 0; n < ( argc -1); n++)

{

params_ptr = get_zone_ptr(&params, n* sizeof(mem_ptr));

(*params_ptr) = argv[n+1];

}

params_ptr = get_zone_ptr(&params, n* sizeof(mem_ptr));

(*params_ptr) = PTR_NULL;

}


if (!app_start(&params))

{

console_print( "could not start app " );

console_print(nodix_mod->name);

console_print("\n");

return 0;

}

while (isRunning())

{

app_loop(PTR_NULL);

}


app_stop(PTR_NULL);

}