
/****************************************************************************
  This program is used to transform data into xml document in the outer way and to 
 receive command from a client side.

  This program takes the identifiers of main task process, 
  command shared memory segment and semaphore array in its arguments
  
  Keyboard input loop :

    - First read the result of last command executed by the main task
    (At semaphore released by the main task)
    - Read next command
    At That moment the main task is not executing anything.
    When the user press Return, the command line is copied into
    the command shared memory segment and the semaphore of the main task,
    which is currently blocking, is released
    
************************************************************************/

#include "xml-keyboard.h"

#include "service.h"
#include "gcore/gcomm.h"

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#ifdef linux
static sigjmp_buf sjmpbuf;      /* for RedHAt 5.1 */
#else
static jmp_buf jmpbuf;
#endif

extern void quit( );

#include "ggui/gkbd_term.h"

void send_status( command_line_t *c)
{
    char response[MAXBUF + 256];

    if (c->code == 0) {
        sprintf( response, "<gui_status valid=\"true\" ");
    } else {
        sprintf( response, "<gui_status valid=\"false\" reason=\"bad command\" ");
    }
    write( sockfd, response, strlen( response));
    if ((c->nc) > 0) {
        sprintf( response, "command=\"%s\"></gui_status>\n", xmlAttributeFilter( c->line));
    } else {
        sprintf( response, "></gui_status>\n");
    }
    write( sockfd, response, strlen( response));
    /*  return command line data */
    /*  without esc command... */
    sprintf( response, "<gui_log prompt=\"%s\"", xmlAttributeFilter( c->prompt));
    write( sockfd, response, strlen( response));
    /* error case */
    if (c->code != 0) {
        sprintf( response, " promptColor=\"red\"");
        write( sockfd, response, strlen( response));
    }
    if ((c->code) != 0) {
        sprintf( response, " line=\"%s\"></gui_log>\n", xmlAttributeFilter( c->line));
    } else {
        sprintf( response, "></gui_log>\n");
    }
    write( sockfd, response, strlen( response));
    fflush( NULL);
}


void trap_sig( int lesignal)
{
    signal( lesignal, trap_sig);
}

extern void jumper( );

#ifdef linux
extern void sleepons( );
#endif

/*  read command on socket */
void sock_line( command_line_t *c)
{
    c->code = 0;
    /*   write( sockfd,"\n",1);  */
    c->nc = read( sockfd, c->line, MAXBUF) - 1;
    if (c->nc >= 0)
        c->line[c->nc] = '\0';
}

void socket_loop( )
{
    command_line_t command_line;

#ifdef linux
    sigsetjmp( sjmpbuf, 1);
#else
    setjmp( jmpbuf);
#endif

    signal( SIGUSR2, jumper);
    signal( SIGINT, jumper);
#ifdef linux
    signal( SIGTTOU, sleepons);
    signal( SIGTTIN, sleepons);
    signal( SIGCONT, jumper);
#endif
    signal( SIGTERM, quit);

    while (1) {
        sic_wait_prompt( &command_line, -1);

        /* handshake */
        send_status( &command_line);

        /* Read socket command */
        sock_line( &command_line);

        sic_post_command_from_prompt( &command_line);
    }
}

int run_xml_keyboard( void *command_line)
{
    /* create socket endpoint */
    if (!connect_to_server( )) {
        /* Cannot do anything about this. We need to stop master task
         * since there is no recovery possible and the processes are 
         * stuck in a wait state uncomprehensible for normal user */
        fprintf( stderr, "Fatal: Using XML client server Widgets, i am\n");
        fprintf( stderr, "       unable to connect to socket, exiting.\n");
        return 1;
    }
    sendConfig( "sic_keyboard", NULL);
    socket_loop( );

    return 0;
}


#ifdef linux
void sleepons( int lesignal)
{
    signal( SIGTTIN, sleepons);
    signal( SIGTTOU, sleepons);
    pause( );
}
#endif

void jumper( int lesignal)
{
    signal( lesignal, jumper);

#ifdef linux
    siglongjmp( sjmpbuf, 1);
#else
    longjmp( jmpbuf, 1);
#endif
}
void quit( int lesignal)
{
    /*   kill (masterpid,SIGTERM); */
    sic_do_exit( 1);
}
