/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

**********************************************************************/


#include	"fcntl.h"
#include	<stdlib.h>
#include	"init.h"
#include	"gbview.h"
#include	"xlerror.h"
#include	"xl.h"
#include	"machine/err.h"
#include	"machine/param_gbview.h"
#include	"client.h"
#include	"pri_level.h"
#include	"memory_debug.h"

STREAM * target;
STREAM * read_file;
int retry_cnt;


void
ipc_init(int argc,char ** argv)
{
XL_INTERPRETER * xli;

	init_xl(INI_DONTWAITCHI);
	init_function(
		gblisp_top_env0,
		gblisp_top_env1,
		argc,
		argv); 
/*
	xlsh_init_fd();
*/

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
}

void
write_task()
{
int er;
char buffer[1001];
STREAM * id,* fd2;
	id = target;
	fd2 = read_file;
	for ( ; ; ) {
		er = s_read(fd2,buffer,1000);
		if ( er < 0 ) {
			perror("connection error\n");
			exit(1);
		}
		if ( er <= 0 )
			break;
		s_write(id,buffer,er);
	}
	s_printf(id,"(CloseInterpreter(GetIid))\n");
	s_flush(id);
	s_close(fd2);
}

void
launch_gbview()
{
	if ( retry_cnt == 0 )
		launch_devnull("cosmos v");
	sleep_sec(2);
	retry_cnt ++;
	if ( retry_cnt > 10 ) {
		fprintf(stderr,"cannot launch the task gbview v\n");
		exit(1);
	}
}

void
ipc_system(int argc,char ** argv)
{
int i;
int no;
STREAM * id;
char file[100];
STREAM * fd;
STREAM * fd2;
char hostname[100];
int j;
XL_SEXP * ap, * r, * cmd;
XL_SEXP * port,* perm;
XL_SEXP * pid;
int cerr;
char * str;

	retry_cnt = 0;

	gc_push(0,0,"ipc_task");
retry:
	sprintf(file,"%s%s",get_preference_path(),GBVIEW_AP);
	fd = s_open_file(file,O_RDONLY);
	if ( fd == 0 ){
		launch_gbview();
		goto retry;
	}
	ap = init_parse(fd,l_string(std_cm,"gbview ap file"),0);
	if ( get_type(ap) != XLT_PAIR ) {
		launch_gbview();
		goto retry;
	}
	no = -1;
	for ( ; get_type(ap) ; ap = cdr(ap) ) {
		r = car(ap);
		if ( get_type(r) != XLT_PAIR )
			continue;
		cmd = car(r);
		if ( get_type(cmd) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(cmd->symbol.data,
				l_string(std_cm,"port")) == 0 ) {
			port = get_el(r,1);
			if ( get_type(port) != XLT_INTEGER ) {
				fprintf(stderr,
					"invalid gbview.ap format (port)\n");
				print_sexp(s_stderr,r,0);
				fprintf(stderr,"\n");
				launch_gbview();
				goto retry;
			}
			no = port->integer.data;
		}
		else if ( l_strcmp(cmd->symbol.data,
				l_string(std_cm,"pid")) == 0 ) {
			pid = get_el(r,1);
			if ( get_type(pid) != XLT_INTEGER ) {
				fprintf(stderr,
					"invalid gbview.ap format (pid)\n");
				print_sexp(s_stderr,r,0);
				fprintf(stderr,"\n");
				launch_gbview();
				goto retry;
			}
			// checking the pid is a process id for gbview 
			if ( check_pid(pid->integer.data,"cosmos") ) {
				s_close(fd);
				launch_gbview();
				goto retry;
			}
		}
	}
	if ( no == -1 ) {
		launch_gbview();
		goto retry;
	}
	id = new_connection(&cerr,"localhost",0,no,0,0);
	if ( id == 0 ) {
		launch_gbview();
		goto retry;
	}
	if ( retry_cnt )
		sleep_sec(2);
	s_printf(id,"\n");
	ap = init_parse(id,l_string(std_cm,"connection"),0);
	for ( ; get_type(ap) ; ap = cdr(ap) ) {
		r = car(ap);
		if ( get_type(r) == XLT_ERROR ) {
			fprintf(stderr,"connection error ");
			print_sexp(s_stderr,r,0);
			fprintf(stderr,"\n");
			exit(1);
		}
		if ( get_type(r) != XLT_PAIR )
			continue;
		cmd = car(r);
		if ( get_type(cmd) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(cmd->symbol.data,
				l_string(std_cm,"Permission")) )
			continue;
		perm = get_el(r,1);
		if ( get_type(perm) == XLT_ERROR ) {
			fprintf(stderr,"connection error ");
			print_sexp(s_stderr,r,0);
			fprintf(stderr,"\n");
			exit(1);
		}
		if ( get_type(perm) != XLT_STRING ) {
			fprintf(stderr,"permission error\n");
			exit(1);
		}
		if ( l_strcmp(perm->string.data,l_string(std_cm,"Allow")) ) {
			fprintf(stderr,"permission error %s\n",
				n_string(std_cm,perm->string.data));
			exit(1);
		}
		break;
	}
	str = normalize_delim_str(argv[2]);
	read_file = s_open_file(str,O_RDONLY);
	d_f_ree(str);
	if ( read_file == 0 ) {
		perror("cannot open the file of the argument");
		exit(1);
	}
	target = id;

	create_task(write_task,0,PRI_IPC_TASK);

	for ( ; get_type(ap) ; ap = cdr(ap) ) {
		if ( strcmp(argv[1],"o") == 0 ) {
			print_sexp(s_stdout,car(ap),PF_RAW_DISABLE);
			printf("\n");
		}
	}
	gc_pop(0,0);
	s_close(id);
}
