From 4ae82c64d8f219666c2f8315a8a5ab9e30a1c1af Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Sat, 29 Oct 2022 15:37:18 +0200 Subject: WIP --- src/sman/session.c | 534 --------------------------------- src/sman/session.cc | 534 +++++++++++++++++++++++++++++++++ src/sman/sman.c | 794 ------------------------------------------------- src/sman/sman.cc | 794 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sman/spadclient.c | 75 ----- src/sman/spadclient.cc | 74 +++++ 6 files changed, 1402 insertions(+), 1403 deletions(-) delete mode 100644 src/sman/session.c create mode 100644 src/sman/session.cc delete mode 100644 src/sman/sman.c create mode 100644 src/sman/sman.cc delete mode 100644 src/sman/spadclient.c create mode 100644 src/sman/spadclient.cc (limited to 'src/sman') diff --git a/src/sman/session.c b/src/sman/session.c deleted file mode 100644 index 20a29307..00000000 --- a/src/sman/session.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd. - All rights reserved. - - Copyright (C) 2007-2013, Gabriel Dos Reis. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - 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. - - - Neither the name of The Numerical ALgorithms Group Ltd. 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 OWNER - 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. -*/ - -/* #define DEBUG */ -#define _SESSION_C - -#include -#include -#include -#include -#include -#include - -#include "open-axiom.h" -#include "sockio.h" -#include "com.h" -#include "bsdsignal.h" -#include "cfuns.h" -#include "sockio.h" - -using namespace OpenAxiom; - -static void usr1_handler(int); -static void usr2_handler(int); -static void term_handler(int); -static void close_client(int); -static void read_SpadServer_command(void); -static int test_sock_for_process(openaxiom_sio*); -static void read_menu_client_command(void); -static void read_from_spad_io(void); -static void kill_spad(void); -static int accept_session_connection(openaxiom_sio*); -static void read_from_session(openaxiom_sio*); -static void manage_sessions(void); - - -#define BufSize 4096 /* size of communication buffer */ - -typedef struct sock_list { /* linked list of Sock */ - openaxiom_sio Socket; - struct sock_list *next; -} Sock_List; - -openaxiom_sio* spad_io = 0; /* to_server socket for SessionIO */ -openaxiom_sio* spad_server = 0; /* to_server socket for SpadServer */ -openaxiom_sio* menu_client = 0; /* to_client socket for MenuServerName */ -openaxiom_sio* active_session = 0; /* pointer to currently active session */ - -Sock_List *plSock = (Sock_List *) 0; - -char big_bad_buf[BufSize]; /* big I/O buffer */ -int num_active_clients = 0; /* number of InterpWindows attached */ -int reading_output = 0; -fd_set session_socket_mask; - -static void -usr1_handler(int sig) -{ - return; -} - -static void -usr2_handler(int sig) -{ - send_signal(spad_server, SIGINT); - return; -} - -static void -term_handler(int sig) -{ - exit(1); -} - -#ifdef DEBUG -static void -pr() -{ - Sock_List *pSock; - - fprintf(stderr,"The socket list:\n"); - for(pSock=plSock;pSock!=(Sock_List *)0;pSock=pSock->next){ - fprintf(stderr,"(%d,%d,%d)\t",pSock->Socket.pid,2<<(pSock->Socket.socket),pSock->Socket.frame); - } - fprintf(stderr,"\n"); -} -#endif - -static void -close_client(int frame) -{ - Sock_List *pSock,*locSock; - int socket_fd; - - /* we will check for frame equality, - kill with send_signal, - notify HyperTex so that it updates its list (if it's a spadbuf), - repair the list, - unset the active_session, - update num_active_clients - */ - - - /* first check head */ -#ifdef DEBUG -fprintf(stderr,"close_client(%d)\n",frame); -#endif - - if ( (plSock) && (plSock->Socket.frame == frame) ){ - socket_fd = plSock->Socket.socket; - send_signal((openaxiom_sio *)plSock, SIGTERM); - if ( menu_client != (openaxiom_sio *) 0){ - send_int(menu_client,CloseClient); - send_int(menu_client,(*plSock).Socket.pid); - } -#ifdef DEBUG -fprintf(stderr,"trying to clear %u\n",socket_fd); -#endif - FD_CLR(socket_fd,&session_socket_mask); - locSock = plSock; - if ((*plSock).next == (Sock_List *) 0) - {plSock = (Sock_List *) 0;} - else - {plSock = plSock->next;} - active_session = (openaxiom_sio *) 0; - num_active_clients--; - free(locSock); - } - - /* now check the rest */ - - else { - for (pSock=plSock; pSock->next != (Sock_List *) 0 ; pSock=pSock->next) - if (pSock->next->Socket.frame == frame){ - socket_fd = pSock->next->Socket.socket; - send_signal((openaxiom_sio *)pSock->next, SIGTERM); - if ( menu_client != (openaxiom_sio *) 0){ - send_int(menu_client,CloseClient); - send_int(menu_client,(*plSock).Socket.pid); - } -#ifdef DEBUG -fprintf(stderr,"trying to clear %u\n",socket_fd); -#endif - FD_CLR(socket_fd,&session_socket_mask); - locSock = pSock->next; - if ( pSock->next->next == (Sock_List *) 0 ) - { pSock->next= (Sock_List *) 0;} - else - { pSock->next = pSock->next->next;} - num_active_clients--; - active_session = (openaxiom_sio *) 0; - free(locSock); - break; - } - } -#ifdef DEBUG -pr(); -#endif -} - -static void -read_SpadServer_command(void) -{ - int cmd, frame, num; - cmd = get_int(spad_server); - switch (cmd) { - case EndOfOutput: - if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGUSR2); - if (reading_output != 0) reading_output = 0; - break; - case QueryClients: - /* don't count MenuServer */ - num = num_active_clients ; - send_int(spad_server, num); - break; - case CloseClient: - frame = get_int(spad_server); - if (frame != -1) close_client(frame); - break; - case SendXEventToHyperTeX: - break; - default: - fprintf(stderr, "session : unknown command from SpadServer %d\n", cmd); - break; - } -} - -static int -test_sock_for_process(openaxiom_sio *sock) -{ - if (sock == (openaxiom_sio *)0 ) return -1; - return kill(sock->pid, 0); -} - -static void -read_menu_client_command(void) -{ - int cmd,frame, i,socket_fd; - Sock_List *pSock; - - /* save it for possible clearing */ - socket_fd = menu_client->socket; - - if (test_sock_for_process(menu_client) == -1) { - FD_CLR(socket_fd,&session_socket_mask); - menu_client = (openaxiom_sio *) 0; - reading_output = 0; - return; - } - cmd = get_int(menu_client); - switch(cmd) { - case -1: /* socket closed */ - FD_CLR(socket_fd,&session_socket_mask); - menu_client = (openaxiom_sio *) 0; - reading_output = 0; - break; - case SwitchFrames: -#ifdef DEBUG -fprintf(stderr,"menu:SwitchFrames\n"); -#endif - frame = get_int(menu_client); - send_int(spad_server, SwitchFrames); - send_int(spad_server, frame); - for(i=0,pSock=plSock; pSock != (Sock_List *) 0 ; i++,pSock=pSock->next) - if (pSock->Socket.frame == frame) { - active_session = (openaxiom_sio *)pSock; - reading_output = 1; - break; - } - if (i == num_active_clients) { - /* fprintf(stderr, "Couldn't find socket for frame %d\n", frame); */ - } - break; - case QuerySpad: -#ifdef DEBUG -fprintf(stderr,"menu:QuerySpad\n"); -#endif - send_int(menu_client, reading_output); - break; - default: - fprintf(stderr, "session : unknown command from MenuServer: %d\n", cmd); - menu_client = (openaxiom_sio *) 0; - break; - } -} - -static void -read_from_spad_io(void) -{ - int ret_code; - ret_code = sread(spad_io, byte_address(big_bad_buf), BufSize, - "session: stdout socket"); - if (ret_code == -1) return; - if(active_session != (openaxiom_sio *) 0) { - ret_code = swrite(active_session, byte_address(big_bad_buf), - ret_code, NULL); - } -} - -static void -kill_spad(void) -{ - int i; - Sock_List *pSock; - - send_signal(spad_server, SIGTERM); - for (pSock=plSock,i=0; - (inext) { - if ((pSock->Socket).socket != 0) - send_signal((openaxiom_sio *)pSock, SIGTERM); - } - if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGTERM); - exit(0); -} - -static int -accept_session_connection(openaxiom_sio *server_sock) -{ - int sock_fd, ret_code; - Sock_List *pls; - - /* Could be three things : KillSpad MenuServer InterpWindow */ - - pls = (Sock_List *) malloc(sizeof (Sock_List)); - sock_fd = accept(server_sock->socket, 0, 0); - if (sock_fd == -1) { - perror("session : accepting connection"); - return -1; - } - (pls->Socket).socket = sock_fd; - get_socket_type((openaxiom_sio *)pls); - - switch((pls->Socket).purpose) { - case KillSpad: - kill_spad(); - return KillSpad; - free(pls); - case MenuServer: -#ifdef DEBUG - fprintf(stderr,"session: accepted MenuServer , fd = %d\n",sock_fd); -#endif - menu_client = &(pls->Socket); - FD_SET(menu_client->socket, &session_socket_mask); - return MenuServer; - case InterpWindow: -#ifdef DEBUG - fprintf(stderr,"session: accepted InterpWindow , fd = %d\n",sock_fd); -#endif - - /* new Sock is put at the head of the list */ - if (plSock == (Sock_List *)0 ) { - plSock = pls; - plSock->next = (Sock_List *)0 ; - } - else{ - pls->next = plSock; - plSock = pls; - } - - /* we need to maintain session_socket_mask here since we roll our own accept */ - - FD_SET(plSock->Socket.socket, &session_socket_mask); - send_int(spad_server, CreateFrame); - plSock->Socket.frame = get_int(spad_server); - active_session = (openaxiom_sio *)plSock; - get_string_buf(spad_server, big_bad_buf, BufSize); - ret_code = swrite((openaxiom_sio *)plSock, - byte_address(big_bad_buf), - strlen(big_bad_buf)+1, - "session: writing to InterpWindow"); - if (ret_code == -1) - return -1; - num_active_clients++; -#ifdef DEBUG -pr(); -#endif - return plSock->Socket.purpose; - } - return (-1); -} - -static void -read_from_session(openaxiom_sio *sock) -{ - int ret_code; - if (sock != active_session) { - send_int(spad_server, SwitchFrames); - send_int(spad_server, sock->frame); - } - active_session = sock; - ret_code = sread(sock, byte_address(big_bad_buf), BufSize, - "session: reading InterpWindow"); - if (ret_code == -1) { - active_session = (openaxiom_sio *) 0; - reading_output = 0; - return; - } - ret_code = swrite(spad_io, byte_address(big_bad_buf), ret_code, - "session: writing SessionIO"); - if (ret_code == -1) { - active_session = (openaxiom_sio *)0 ; - reading_output = 0; - return; - } - reading_output = 1; -} - -static void -manage_sessions(void) -{ - int ret_code; - fd_set rd, wr, ex; - Sock_List *pSock; - - reading_output = 0; - while (1) { - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - - /* Allow server socket and all connections if not waiting for output - socket_mask is maintained by libspad.a */ -#ifdef DEBUG -fprintf(stderr,"session_socket_mask=%u ",*((long *)session_socket_mask.fds_bits)); -#endif - rd = session_socket_mask; - if (!reading_output) { - rd = session_socket_mask; - } - - /* Allow the active_session if set */ - if (active_session) FD_SET(active_session->socket, &rd); -#ifdef DEBUG -fprintf(stderr,"[rd=%u ",*((long *)rd.fds_bits)); -#endif - - ret_code = sselect(FD_SETSIZE, &rd, &wr, &ex, NULL); - if (ret_code == -1) { - break; - } -#ifdef DEBUG -fprintf(stderr,"rd=%u]\n",*((long *)rd.fds_bits)); -#endif - - if ((menu_client != (openaxiom_sio *) 0) - && FD_ISSET(menu_client->socket, &rd)) { - /* MenuServer wants to talk */ - read_menu_client_command(); } - - - if (FD_ISSET(spad_io->socket, &rd)) { - /* Lisp has output */ - read_from_spad_io(); } - - - if (FD_ISSET(server.socket, &rd)) { - /* Someone wants to connect to our server socket */ - accept_session_connection(&server); } - - - for(pSock=plSock; pSock != (Sock_List *) 0 ; pSock=pSock->next) { - if ((active_session == (openaxiom_sio *)pSock || !reading_output) && - (pSock->Socket).socket>0 && FD_ISSET(pSock->Socket.socket, &rd)) { - /* An InterpWindow */ - read_from_session((openaxiom_sio *)pSock); } - } - - - if (FD_ISSET(spad_server->socket, &rd)) { - /* The Lisp socket */ - read_SpadServer_command(); } - } -} - -int -main(void) -{ - using namespace OpenAxiom; -#ifdef DEBUG2 - /* delay for attaching with debugger before interesting things happen */ - openaxiom_sleep(30); -#endif - - oa_setenv("LC_ALL", "C"); - setlocale(LC_ALL, ""); - /* spad_server connects to Lisp server socket - read_SpadServer_command handles requests */ - spad_server = connect_to_local_server(SpadServer, SessionManager, Forever); - if (spad_server == (openaxiom_sio *) 0) { - fprintf(stderr, "session: Cannot connect to OpenAxiom server!\n"); - exit(0); - } - else { -#ifdef DEBUG - fprintf(stderr, "session: connected SpadServer , fd = %d\n", - spad_server->socket); -#endif - FD_SET(spad_server->socket, &session_socket_mask); - } - - - /* spad_io connects to SessionIOName server socket - this is Lisp std IO read_from_spad_io handles requests */ - spad_io = connect_to_local_server(SessionIOName, SessionIO, Forever); - if (spad_io == (openaxiom_sio *) 0) { - fprintf(stderr, "session: Cannot connect to OpenAxiom IO!\n"); - exit(0); - } - else { -#ifdef DEBUG - fprintf(stderr,"session: connected SessionIOName , fd = %d\n", - spad_io->socket); -#endif - FD_SET(spad_io->socket, &session_socket_mask); - } - bsdSignal(SIGUSR2, usr2_handler,DontRestartSystemCalls); - bsdSignal(SIGUSR1, usr1_handler,RestartSystemCalls); - bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); - bsdSignal(SIGTERM, term_handler,RestartSystemCalls); - - /* open_server opens the server socket so that we can accept connections - we expect connections from spadbuf/spadclient(purpose:InterpWindow) - and hypertex (MenuServer) */ - - if (open_server(SessionServer) == -2) { - fprintf(stderr, "session: Cannot make server socket!\n"); - exit(-1); - } - else { -#ifdef DEBUG - fprintf(stderr, "session: opened SessionServer , fd = %d\n", - server.socket); -#endif - FD_SET(server.socket,&session_socket_mask); - } - manage_sessions(); - return(0); -} - - diff --git a/src/sman/session.cc b/src/sman/session.cc new file mode 100644 index 00000000..20a29307 --- /dev/null +++ b/src/sman/session.cc @@ -0,0 +1,534 @@ +/* + Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd. + All rights reserved. + + Copyright (C) 2007-2013, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - 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. + + - Neither the name of The Numerical ALgorithms Group Ltd. 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 OWNER + 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. +*/ + +/* #define DEBUG */ +#define _SESSION_C + +#include +#include +#include +#include +#include +#include + +#include "open-axiom.h" +#include "sockio.h" +#include "com.h" +#include "bsdsignal.h" +#include "cfuns.h" +#include "sockio.h" + +using namespace OpenAxiom; + +static void usr1_handler(int); +static void usr2_handler(int); +static void term_handler(int); +static void close_client(int); +static void read_SpadServer_command(void); +static int test_sock_for_process(openaxiom_sio*); +static void read_menu_client_command(void); +static void read_from_spad_io(void); +static void kill_spad(void); +static int accept_session_connection(openaxiom_sio*); +static void read_from_session(openaxiom_sio*); +static void manage_sessions(void); + + +#define BufSize 4096 /* size of communication buffer */ + +typedef struct sock_list { /* linked list of Sock */ + openaxiom_sio Socket; + struct sock_list *next; +} Sock_List; + +openaxiom_sio* spad_io = 0; /* to_server socket for SessionIO */ +openaxiom_sio* spad_server = 0; /* to_server socket for SpadServer */ +openaxiom_sio* menu_client = 0; /* to_client socket for MenuServerName */ +openaxiom_sio* active_session = 0; /* pointer to currently active session */ + +Sock_List *plSock = (Sock_List *) 0; + +char big_bad_buf[BufSize]; /* big I/O buffer */ +int num_active_clients = 0; /* number of InterpWindows attached */ +int reading_output = 0; +fd_set session_socket_mask; + +static void +usr1_handler(int sig) +{ + return; +} + +static void +usr2_handler(int sig) +{ + send_signal(spad_server, SIGINT); + return; +} + +static void +term_handler(int sig) +{ + exit(1); +} + +#ifdef DEBUG +static void +pr() +{ + Sock_List *pSock; + + fprintf(stderr,"The socket list:\n"); + for(pSock=plSock;pSock!=(Sock_List *)0;pSock=pSock->next){ + fprintf(stderr,"(%d,%d,%d)\t",pSock->Socket.pid,2<<(pSock->Socket.socket),pSock->Socket.frame); + } + fprintf(stderr,"\n"); +} +#endif + +static void +close_client(int frame) +{ + Sock_List *pSock,*locSock; + int socket_fd; + + /* we will check for frame equality, + kill with send_signal, + notify HyperTex so that it updates its list (if it's a spadbuf), + repair the list, + unset the active_session, + update num_active_clients + */ + + + /* first check head */ +#ifdef DEBUG +fprintf(stderr,"close_client(%d)\n",frame); +#endif + + if ( (plSock) && (plSock->Socket.frame == frame) ){ + socket_fd = plSock->Socket.socket; + send_signal((openaxiom_sio *)plSock, SIGTERM); + if ( menu_client != (openaxiom_sio *) 0){ + send_int(menu_client,CloseClient); + send_int(menu_client,(*plSock).Socket.pid); + } +#ifdef DEBUG +fprintf(stderr,"trying to clear %u\n",socket_fd); +#endif + FD_CLR(socket_fd,&session_socket_mask); + locSock = plSock; + if ((*plSock).next == (Sock_List *) 0) + {plSock = (Sock_List *) 0;} + else + {plSock = plSock->next;} + active_session = (openaxiom_sio *) 0; + num_active_clients--; + free(locSock); + } + + /* now check the rest */ + + else { + for (pSock=plSock; pSock->next != (Sock_List *) 0 ; pSock=pSock->next) + if (pSock->next->Socket.frame == frame){ + socket_fd = pSock->next->Socket.socket; + send_signal((openaxiom_sio *)pSock->next, SIGTERM); + if ( menu_client != (openaxiom_sio *) 0){ + send_int(menu_client,CloseClient); + send_int(menu_client,(*plSock).Socket.pid); + } +#ifdef DEBUG +fprintf(stderr,"trying to clear %u\n",socket_fd); +#endif + FD_CLR(socket_fd,&session_socket_mask); + locSock = pSock->next; + if ( pSock->next->next == (Sock_List *) 0 ) + { pSock->next= (Sock_List *) 0;} + else + { pSock->next = pSock->next->next;} + num_active_clients--; + active_session = (openaxiom_sio *) 0; + free(locSock); + break; + } + } +#ifdef DEBUG +pr(); +#endif +} + +static void +read_SpadServer_command(void) +{ + int cmd, frame, num; + cmd = get_int(spad_server); + switch (cmd) { + case EndOfOutput: + if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGUSR2); + if (reading_output != 0) reading_output = 0; + break; + case QueryClients: + /* don't count MenuServer */ + num = num_active_clients ; + send_int(spad_server, num); + break; + case CloseClient: + frame = get_int(spad_server); + if (frame != -1) close_client(frame); + break; + case SendXEventToHyperTeX: + break; + default: + fprintf(stderr, "session : unknown command from SpadServer %d\n", cmd); + break; + } +} + +static int +test_sock_for_process(openaxiom_sio *sock) +{ + if (sock == (openaxiom_sio *)0 ) return -1; + return kill(sock->pid, 0); +} + +static void +read_menu_client_command(void) +{ + int cmd,frame, i,socket_fd; + Sock_List *pSock; + + /* save it for possible clearing */ + socket_fd = menu_client->socket; + + if (test_sock_for_process(menu_client) == -1) { + FD_CLR(socket_fd,&session_socket_mask); + menu_client = (openaxiom_sio *) 0; + reading_output = 0; + return; + } + cmd = get_int(menu_client); + switch(cmd) { + case -1: /* socket closed */ + FD_CLR(socket_fd,&session_socket_mask); + menu_client = (openaxiom_sio *) 0; + reading_output = 0; + break; + case SwitchFrames: +#ifdef DEBUG +fprintf(stderr,"menu:SwitchFrames\n"); +#endif + frame = get_int(menu_client); + send_int(spad_server, SwitchFrames); + send_int(spad_server, frame); + for(i=0,pSock=plSock; pSock != (Sock_List *) 0 ; i++,pSock=pSock->next) + if (pSock->Socket.frame == frame) { + active_session = (openaxiom_sio *)pSock; + reading_output = 1; + break; + } + if (i == num_active_clients) { + /* fprintf(stderr, "Couldn't find socket for frame %d\n", frame); */ + } + break; + case QuerySpad: +#ifdef DEBUG +fprintf(stderr,"menu:QuerySpad\n"); +#endif + send_int(menu_client, reading_output); + break; + default: + fprintf(stderr, "session : unknown command from MenuServer: %d\n", cmd); + menu_client = (openaxiom_sio *) 0; + break; + } +} + +static void +read_from_spad_io(void) +{ + int ret_code; + ret_code = sread(spad_io, byte_address(big_bad_buf), BufSize, + "session: stdout socket"); + if (ret_code == -1) return; + if(active_session != (openaxiom_sio *) 0) { + ret_code = swrite(active_session, byte_address(big_bad_buf), + ret_code, NULL); + } +} + +static void +kill_spad(void) +{ + int i; + Sock_List *pSock; + + send_signal(spad_server, SIGTERM); + for (pSock=plSock,i=0; + (inext) { + if ((pSock->Socket).socket != 0) + send_signal((openaxiom_sio *)pSock, SIGTERM); + } + if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGTERM); + exit(0); +} + +static int +accept_session_connection(openaxiom_sio *server_sock) +{ + int sock_fd, ret_code; + Sock_List *pls; + + /* Could be three things : KillSpad MenuServer InterpWindow */ + + pls = (Sock_List *) malloc(sizeof (Sock_List)); + sock_fd = accept(server_sock->socket, 0, 0); + if (sock_fd == -1) { + perror("session : accepting connection"); + return -1; + } + (pls->Socket).socket = sock_fd; + get_socket_type((openaxiom_sio *)pls); + + switch((pls->Socket).purpose) { + case KillSpad: + kill_spad(); + return KillSpad; + free(pls); + case MenuServer: +#ifdef DEBUG + fprintf(stderr,"session: accepted MenuServer , fd = %d\n",sock_fd); +#endif + menu_client = &(pls->Socket); + FD_SET(menu_client->socket, &session_socket_mask); + return MenuServer; + case InterpWindow: +#ifdef DEBUG + fprintf(stderr,"session: accepted InterpWindow , fd = %d\n",sock_fd); +#endif + + /* new Sock is put at the head of the list */ + if (plSock == (Sock_List *)0 ) { + plSock = pls; + plSock->next = (Sock_List *)0 ; + } + else{ + pls->next = plSock; + plSock = pls; + } + + /* we need to maintain session_socket_mask here since we roll our own accept */ + + FD_SET(plSock->Socket.socket, &session_socket_mask); + send_int(spad_server, CreateFrame); + plSock->Socket.frame = get_int(spad_server); + active_session = (openaxiom_sio *)plSock; + get_string_buf(spad_server, big_bad_buf, BufSize); + ret_code = swrite((openaxiom_sio *)plSock, + byte_address(big_bad_buf), + strlen(big_bad_buf)+1, + "session: writing to InterpWindow"); + if (ret_code == -1) + return -1; + num_active_clients++; +#ifdef DEBUG +pr(); +#endif + return plSock->Socket.purpose; + } + return (-1); +} + +static void +read_from_session(openaxiom_sio *sock) +{ + int ret_code; + if (sock != active_session) { + send_int(spad_server, SwitchFrames); + send_int(spad_server, sock->frame); + } + active_session = sock; + ret_code = sread(sock, byte_address(big_bad_buf), BufSize, + "session: reading InterpWindow"); + if (ret_code == -1) { + active_session = (openaxiom_sio *) 0; + reading_output = 0; + return; + } + ret_code = swrite(spad_io, byte_address(big_bad_buf), ret_code, + "session: writing SessionIO"); + if (ret_code == -1) { + active_session = (openaxiom_sio *)0 ; + reading_output = 0; + return; + } + reading_output = 1; +} + +static void +manage_sessions(void) +{ + int ret_code; + fd_set rd, wr, ex; + Sock_List *pSock; + + reading_output = 0; + while (1) { + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&ex); + + /* Allow server socket and all connections if not waiting for output + socket_mask is maintained by libspad.a */ +#ifdef DEBUG +fprintf(stderr,"session_socket_mask=%u ",*((long *)session_socket_mask.fds_bits)); +#endif + rd = session_socket_mask; + if (!reading_output) { + rd = session_socket_mask; + } + + /* Allow the active_session if set */ + if (active_session) FD_SET(active_session->socket, &rd); +#ifdef DEBUG +fprintf(stderr,"[rd=%u ",*((long *)rd.fds_bits)); +#endif + + ret_code = sselect(FD_SETSIZE, &rd, &wr, &ex, NULL); + if (ret_code == -1) { + break; + } +#ifdef DEBUG +fprintf(stderr,"rd=%u]\n",*((long *)rd.fds_bits)); +#endif + + if ((menu_client != (openaxiom_sio *) 0) + && FD_ISSET(menu_client->socket, &rd)) { + /* MenuServer wants to talk */ + read_menu_client_command(); } + + + if (FD_ISSET(spad_io->socket, &rd)) { + /* Lisp has output */ + read_from_spad_io(); } + + + if (FD_ISSET(server.socket, &rd)) { + /* Someone wants to connect to our server socket */ + accept_session_connection(&server); } + + + for(pSock=plSock; pSock != (Sock_List *) 0 ; pSock=pSock->next) { + if ((active_session == (openaxiom_sio *)pSock || !reading_output) && + (pSock->Socket).socket>0 && FD_ISSET(pSock->Socket.socket, &rd)) { + /* An InterpWindow */ + read_from_session((openaxiom_sio *)pSock); } + } + + + if (FD_ISSET(spad_server->socket, &rd)) { + /* The Lisp socket */ + read_SpadServer_command(); } + } +} + +int +main(void) +{ + using namespace OpenAxiom; +#ifdef DEBUG2 + /* delay for attaching with debugger before interesting things happen */ + openaxiom_sleep(30); +#endif + + oa_setenv("LC_ALL", "C"); + setlocale(LC_ALL, ""); + /* spad_server connects to Lisp server socket + read_SpadServer_command handles requests */ + spad_server = connect_to_local_server(SpadServer, SessionManager, Forever); + if (spad_server == (openaxiom_sio *) 0) { + fprintf(stderr, "session: Cannot connect to OpenAxiom server!\n"); + exit(0); + } + else { +#ifdef DEBUG + fprintf(stderr, "session: connected SpadServer , fd = %d\n", + spad_server->socket); +#endif + FD_SET(spad_server->socket, &session_socket_mask); + } + + + /* spad_io connects to SessionIOName server socket + this is Lisp std IO read_from_spad_io handles requests */ + spad_io = connect_to_local_server(SessionIOName, SessionIO, Forever); + if (spad_io == (openaxiom_sio *) 0) { + fprintf(stderr, "session: Cannot connect to OpenAxiom IO!\n"); + exit(0); + } + else { +#ifdef DEBUG + fprintf(stderr,"session: connected SessionIOName , fd = %d\n", + spad_io->socket); +#endif + FD_SET(spad_io->socket, &session_socket_mask); + } + bsdSignal(SIGUSR2, usr2_handler,DontRestartSystemCalls); + bsdSignal(SIGUSR1, usr1_handler,RestartSystemCalls); + bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); + bsdSignal(SIGTERM, term_handler,RestartSystemCalls); + + /* open_server opens the server socket so that we can accept connections + we expect connections from spadbuf/spadclient(purpose:InterpWindow) + and hypertex (MenuServer) */ + + if (open_server(SessionServer) == -2) { + fprintf(stderr, "session: Cannot make server socket!\n"); + exit(-1); + } + else { +#ifdef DEBUG + fprintf(stderr, "session: opened SessionServer , fd = %d\n", + server.socket); +#endif + FD_SET(server.socket,&session_socket_mask); + } + manage_sessions(); + return(0); +} + + diff --git a/src/sman/sman.c b/src/sman/sman.c deleted file mode 100644 index ac941266..00000000 --- a/src/sman/sman.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd. - All rights reserved. - Copyright (C) 2007-2014, Gabriel Dos Reis. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - 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. - - - Neither the name of The Numerical Algorithms Group Ltd. 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 OWNER - 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. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "open-axiom.h" -#include "sockio.h" -#include "com.h" -#include "bsdsignal.h" -#include "sman.h" - -#include "sockio.h" -#include "openpty.h" -#include "cfuns.h" - -using namespace OpenAxiom; - -static void process_arguments(Command*, int, char**); -static int in_X(void); -static void set_up_defaults(void); -static void process_options(Command*, int, char**); -static void death_handler(int); -static void sman_catch_signals(void); -static void fix_env(int); -static void init_term_io(void); -static const char* strPrefix(const char* , const char*); -static void check_spad_proc(const char* , const char*); -static void clean_up_old_sockets(void); -static SpadProcess* fork_you(int); -static void exec_command_env(const char*); -static SpadProcess* spawn_of_hell(const char* , int); -static void start_the_spadclient(void); -static void start_the_local_spadclient(void); -static void start_the_session_manager(void); -static void start_the_hypertex(Command*); -static void start_the_graphics(Command*); -static void fork_Axiom(Command*); -static void start_the_Axiom(Command*); -static void clean_up_sockets(void); -static void clean_hypertex_socket(void); -static void read_from_spad_io(int); -static void read_from_manager(int); -static void manage_spad_io(int); -static SpadProcess* find_child(int); -static void kill_all_children(void); -static void monitor_children(void); - -/* System defined pointer to array or environment variables. */ -extern char** environ; - -int start_clef; /* start clef under spad */ -int start_graphics; /* start the viewman */ -int start_ht; /* start hypertex */ -int start_spadclient; /* Start the client spad buffer */ -int start_local_spadclient; /* Start the client spad buffer */ -int use_X; /* Use the X windows environment */ -int server_num; /* OpenAxiom server number */ - -/************************************************/ -/* definitions of programs which sman can start */ -/************************************************/ - -const char *GraphicsProgram = "/lib/viewman"; -const char *HypertexProgram = "/lib/hypertex"; -const char *ClefProgram = "$AXIOM/bin/clef -f $AXIOM/lib/command.list -e "; -const char *SessionManagerProgram = "$AXIOM/lib/session"; -const char *SpadClientProgram = "$AXIOM/lib/spadclient"; -char *PasteFile = NULL; -char *MakeRecordFile = NULL; -char *VerifyRecordFile = NULL; - -SpadProcess *spad_process_list = NULL; -/***************************/ -/* sman defaults file name */ -/***************************/ - -#define SpadDefaultFile "spadprof.input" - -char ClefCommandLine[256]; - -#define BufSize 4096 /* size of communication buffer */ -char big_bad_buf[BufSize]; /* big I/O buffer */ - -openaxiom_sio* session_io = NULL; /* socket connecting to session manager */ - -/***********************************************************/ -/* Some characters used and externally defined in edible.h */ -/***********************************************************/ - -unsigned char _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2; - -/*************************************/ -/* Stuff for opening pseudo-terminal */ -/*************************************/ - -int ptsNum, ptcNum; -char ptsPath[20]; - -int child_pid; /* child's process id */ -struct termios oldbuf; /* the original settings */ -struct termios childbuf; /* terminal structure for user i/o */ - - -int death_signal = 0; - -static void -process_arguments(Command* command, int argc,char ** argv) -{ - int arg; - int other = 0; - for (arg = 1; arg < argc; arg++) { - if (strcmp(argv[arg], "-noclef") == 0) - start_clef = 0; - else if (strcmp(argv[arg], "-clef") == 0) - start_clef = 1; - else if (strcmp(argv[arg], "-gr") == 0 - || strcmp(argv[arg], "--graph") == 0 ) { - if (!OPENAXIOM_HAVE_GRAPHICS) - fprintf(stderr, "OpenAxiom was not build with Graphics support.\n"); - else - start_graphics = 1; - } - else if (strcmp(argv[arg], "-nogr") == 0 - || strcmp(argv[arg], "--no-graph") == 0) - start_graphics = 0; - else if (strcmp(argv[arg], "-ht") == 0 - || strcmp(argv[arg], "--hyperdoc") == 0) { - if (!OPENAXIOM_HAVE_GRAPHICS) - fprintf(stderr, "OpenAxiom was not build with HyperDoc support.\n"); - else - start_ht = 1; - } - else if (strcmp(argv[arg], "-noht") == 0 - || strcmp(argv[arg], "--no-hyperdoc") == 0) - start_ht = 0; - else if (strcmp(argv[arg], "-iw") == 0) - start_spadclient = 1; - else if (strcmp(argv[arg], "-ihere") == 0) - start_local_spadclient = 1; - else if (strcmp(argv[arg], "-noihere") == 0) - start_local_spadclient = 0; - else if (strcmp(argv[arg], "-noiw") == 0) - start_spadclient = 0; - else if (strcmp(argv[arg], "-nox") == 0 - || strcmp(argv[arg], "--no-gui") == 0) { - use_X = 0; - start_local_spadclient = 1; - start_spadclient = 0; - start_ht = 0; - start_graphics = 0; - } - else if (strcmp(argv[arg], "-clefprog") == 0) { - strcpy(ClefCommandLine,argv[++arg]); - ClefProgram = - strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e "); - } - else if (strcmp(argv[arg], "-rm") == 0) - MakeRecordFile = argv[++arg]; - else if (strcmp(argv[arg], "-rv") == 0) - VerifyRecordFile = argv[++arg]; - else if (strcmp(argv[arg], "-paste") == 0) - PasteFile = argv[++arg]; - else - argv[other++] = argv[arg]; - } - - command->core.argv = argv; - command->core.argc = other; - -/* If there were no X libraries - * at build-time, we proceed to - * overwrite the defaults startup - * values to not start any of the - * graphical components of - * OpenAxiom (Hyperdoc, Graphics). */ - - if (!OPENAXIOM_HAVE_GRAPHICS) { - use_X = 0; - start_local_spadclient = 1; - start_ht = 0; - start_graphics = 0; - } -} - -static int -in_X(void) -{ - if (oa_getenv("DISPLAY")) return 1; - return 0; -} - -static void -set_up_defaults(void) -{ - start_clef = 1; - start_graphics = 1; - start_ht = 1; - start_spadclient = 0; - start_local_spadclient = 1; - use_X = isatty(0) && in_X(); -} - -static void -process_options(Command* command, int argc, char **argv) -{ - set_up_defaults(); - process_arguments(command, argc, argv); - /* Complain about command line arguments unknown to Superman. */ - if (command->core.argc > 0) { - int i; - for (i = 0; i < command->core.argc; ++i) - fprintf(stderr,"command line error: %s\n", command->core.argv[i]); - exit(-1); - } -} - -static void -death_handler(int sig) -{ - death_signal = 1; -} - -static void -sman_catch_signals(void) -{ - - /* Set up the signal handlers for sman */ - bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); - bsdSignal(SIGTERM, death_handler,RestartSystemCalls); - bsdSignal(SIGQUIT, death_handler,RestartSystemCalls); - bsdSignal(SIGHUP, death_handler,RestartSystemCalls); - bsdSignal(SIGILL, death_handler,RestartSystemCalls); - bsdSignal(SIGTRAP, death_handler,RestartSystemCalls); - -#ifdef SIGABRT - bsdSignal(SIGABRT, death_handler,RestartSystemCalls); -#else - #ifdef SIGIOT - bsdSignal(SIGIOT, death_handler,RestartSystemCalls); - #endif -#endif - - bsdSignal(SIGBUS, death_handler,RestartSystemCalls); - bsdSignal(SIGSEGV, death_handler,RestartSystemCalls); - -} - -static void -fix_env(int spadnum) -{ - char sn[20]; - sprintf(sn, "%d", spadnum); - oa_setenv("SPADNUM", sn); - oa_setenv("SPADSERVER", "TRUE"); -} - -static void -init_term_io(void) -{ - if(!isatty(0)) return; - if( tcgetattr(0, &oldbuf) == -1) { - perror("getting termios"); - return ; /* exit(-1); */ - } - if( tcgetattr(0, &childbuf) == -1) { - perror("getting termios"); - return ; /* exit(-1); */ - } - _INTR = oldbuf.c_cc[VINTR]; - _QUIT = oldbuf.c_cc[VQUIT]; - _ERASE = oldbuf.c_cc[VERASE]; - _KILL = oldbuf.c_cc[VKILL]; - _EOF = oldbuf.c_cc[VEOF]; - _EOL = oldbuf.c_cc[VEOL]; -} - -static const char* -strPrefix(const char* prefix, const char* s) -{ - while (*prefix != '\0' && *prefix == *s) { - prefix++; - s++; - } - if (*prefix == '\0') return s; - return NULL; -} - -static void -check_spad_proc(const char *file, const char *prefix) -{ - const char *num; - int pid; - if ((num = strPrefix(prefix, file))) { - pid = atoi(num); - if (pid > 2) { - kill(pid, 0); - if (kill(pid, 0) == -1 && errno == ESRCH) { - unlink(file); - } - } - } -} - -static void -clean_up_old_sockets(void) -{ - char com[512], tmp_file[128]; - FILE *file; - int len; - sprintf(tmp_file, "/tmp/socks.%d", server_num); - sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s", - tmp_file, tmp_file); - system(com); - file = fopen(tmp_file, "r"); - if (file == NULL) { - fprintf(stderr, "Can't open socket listing file\n"); - return; - } - while(fgets(com, 512, file) != NULL) { - len = strlen(com); - if (len) com[len-1] = '\0'; - else break; - check_spad_proc(com, "/tmp/.d"); - check_spad_proc(com, "/tmp/.s"); - check_spad_proc(com, "/tmp/.i"); - check_spad_proc(com, "/tmp/.h"); - } - fclose(file); - unlink(tmp_file); -} - -static SpadProcess * -fork_you(int death_action) -{ - /* fork a new process, giving it a default death action */ - /* return NULL in child, SpadProcess in parent */ - int child_pid = fork(); - SpadProcess *proc; - if (!child_pid) return NULL; - proc = (SpadProcess *) malloc(sizeof(SpadProcess)); - proc->proc_id = child_pid; - proc->death_action = death_action; - proc->command = NULL; - proc->next = spad_process_list; - spad_process_list = proc; - return proc; -} - -static void -exec_command_env(const char *command) -{ - char new_command[512]; - sprintf(new_command, "exec %s", command); - execle("/bin/sh","/bin/sh", "-c", new_command, (char*)NULL, environ); -} - -static SpadProcess * -spawn_of_hell(const char *command, int death_action) -{ - SpadProcess *proc = fork_you(death_action); - if (proc != NULL) { - proc->command = command; - return proc; - } - exec_command_env(command); - return NULL; -} - -static void -start_the_spadclient(void) -{ - char command[256]; - if (start_clef) - sprintf(command, - "xterm -sb -sl 500 -name axiomclient -n OpenAxiom -T OpenAxiom -e %s %s", - ClefProgram, SpadClientProgram); - else - sprintf(command, - "xterm -sb -sl 500 -name axiomclient -n OpenAxiom -T OpenAxiom -e %s", - SpadClientProgram); - spawn_of_hell(command, NadaDelShitsky); -} - -static void -start_the_local_spadclient(void) -{ - char command[256]; - if (start_clef) - sprintf(command, "%s %s", ClefProgram, SpadClientProgram); - else - sprintf(command, "%s", SpadClientProgram); - spawn_of_hell(command, NadaDelShitsky); -} - -static void -start_the_session_manager(void) -{ - spawn_of_hell(SessionManagerProgram, Die); -} - -static void -start_the_hypertex(Command* cmd) -{ - const char* root_dir = cmd->root_dir; - const char* command = oa_concatenate_string(root_dir,HypertexProgram); - - if (readablep(command) != 1) { - fprintf(stderr, "Hypertex program not found.\n"); - return; - } - if (PasteFile){ - command = oa_concatenate_string(command, " -s -k -ip "); - command = oa_concatenate_string(command, PasteFile); - spawn_of_hell(command, NadaDelShitsky); - } - else if (MakeRecordFile){ - command = oa_concatenate_string(command, " -s -k -rm "); - command = oa_concatenate_string(command, MakeRecordFile); - spawn_of_hell(command, NadaDelShitsky); - } - else if (VerifyRecordFile){ - command = oa_concatenate_string(command, " -s -k -rv "); - command = oa_concatenate_string(command, VerifyRecordFile); - spawn_of_hell(command, NadaDelShitsky); - } - else - spawn_of_hell(command, CleanHypertexSocket); -} - -static void -start_the_graphics(Command* cmd) -{ - const char* root_dir = cmd -> root_dir; - const char* command = oa_concatenate_string(root_dir,GraphicsProgram); - - if (readablep(command) == 1) - spawn_of_hell(command, DoItAgain); - else - fprintf(stderr, "Graphics program not found.\n"); -} - -/* Start the core executable session in a separate process, */ -/* using a pseudo-terminal to catch all input and output */ -static void -fork_Axiom(Command* cmd) -{ - SpadProcess *proc; - - proc = fork_you(Die); - child_pid = (proc == NULL ? 0 : proc->proc_id); - switch(child_pid) { - case -1 : - fprintf(stderr, "Can't create a new process \n"); - exit(0); - case 0: - /* Dissasociate from my parents group so all my child processes */ - /* look at my terminal as the controlling terminal for the */ - /* group */ - - if(setsid() < 0) { - perror("Dissassociating from parents group"); - exit(-1); - } - - close(ptsNum); - /* Now reopen the server side, so that pg, su, etc. work properly */ - - if ((ptsNum = open(ptsPath, O_RDWR)) < 0 ) { - perror("fork_Axiom: Failed to reopen server"); - exit(-1); - } -#if defined(SUN4OS5platform) || defined(HP10platform) - ioctl(ptsNum,I_PUSH,"ptem"); - ioctl(ptsNum,I_PUSH,"ldterm"); -#endif - - /* since I am the child, I can close ptc, and dup pts for all its */ - /* standard descriptors */ - - if( (dup2(ptsNum, 0) == -1) || - (dup2(ptsNum, 1) == -1) || - (dup2(ptsNum, 2) == -1) ) { - perror("trying to dupe the child"); - exit(-1); - } - close(ptcNum); - close(ptsNum); - - - /* I also have to turn off echoing, since I am echoing all the */ - /* input myself */ - - childbuf.c_lflag &= ~ECHO; - if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) { - perror("setting the term buffer"); - exit(-1); - } - - /* Tell the Core that it is being invoked in server mode. */ - oa_allocate_process_argv(&cmd->core, 2); - cmd->core.argv[0] = (char*) make_path_for(cmd->root_dir, Driver::core); - cmd->core.argv[1] = (char*) "--role=server"; - execute_core(cmd, Driver::core); - } -} - -static void -start_the_Axiom(Command* cmd) -{ - server_num = make_server_number(); - clean_up_old_sockets(); - if (server_num == -1) { - fprintf(stderr, "could not get an OpenAxiom server number\n"); - exit(-1); - } - if (ptyopen(&ptcNum, &ptsNum, ptsPath) == -1) { - perror("start_the_Axiom: ptyopen failed"); - exit(-1); - } - fix_env(server_num); - fork_Axiom(cmd); - close(ptsNum); -} - -static void -clean_hypertex_socket(void) -{ - char name[256]; - sprintf(name, "%s%d", MenuServerName, server_num); - unlink(name); -} - -static void -clean_up_sockets(void) -{ - char name[256]; - sprintf(name, "%s%d", SpadServer, server_num); - unlink(name); - sprintf(name, "%s%d", SessionServer, server_num); - unlink(name); - sprintf(name, "%s%d", SessionIOName, server_num); - unlink(name); - clean_hypertex_socket(); -} - -static void -read_from_spad_io(int ptcNum) -{ - int ret_code = 0, i=0; - static int mes_len =0; - ret_code = read(ptcNum, big_bad_buf, BufSize); - if (ret_code == -1) { - clean_up_sockets(); - exit(-1); - } - if (session_io == NULL) { - if (ret_code < mes_len) - mes_len -= ret_code; - else { - if (mes_len > 0) { - i = mes_len; - mes_len = 0; - } - else - i = 0; - ret_code = write(1, big_bad_buf+i, ret_code-i); - } - } - else - ret_code = swrite(session_io, byte_address(big_bad_buf), ret_code, - "writing to session man"); - if (ret_code == -1) { - perror("writing output to session manager"); - clean_up_sockets(); - exit(-1); - } -} - -static void -read_from_manager(int ptcNum) -{ - int ret_code; - ret_code = sread(session_io, byte_address(big_bad_buf), BufSize, - "reading session io"); - if (ret_code == -1) { - return; - } - ret_code = write(ptcNum, big_bad_buf, ret_code); - if (ret_code == -1) { - return; - } -} - -static void -manage_spad_io(int ptcNum) -{ - int ret_code, p; - fd_set rd; - while (1) { - rd = socket_mask; - FD_SET(ptcNum, &rd); - if (session_io != NULL) - FD_SET(session_io->socket, &rd); - ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL); - if (ret_code == -1) { - perror("Session manager select"); - clean_up_sockets(); - exit(-1); - } - if (FD_ISSET(ptcNum, &rd)) { - read_from_spad_io(ptcNum); - } - if (server.socket > 0 && FD_ISSET(server.socket, &rd)) { - p = accept_connection(); - switch(p) { - case SessionIO: - session_io = purpose_table[SessionIO]; - /* printf("connected session manager\n\r");*/ - printf("\n"); - break; - default: - printf("sman: Unknown connection request type: %d\n", p); - break; - } - } - if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) { - read_from_manager(ptcNum); - } - } -} - -#if 0 -static void -print_spad_process_list() -{ - SpadProcess *proc; - for(proc = spad_process_list; proc != NULL; proc = proc->next) - fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id, - proc->death_action); -} -#endif - -static SpadProcess * -find_child(int proc_id) -{ - SpadProcess *proc; - for(proc = spad_process_list; proc != NULL; proc = proc->next) - if (proc->proc_id == proc_id) return proc; - return NULL; -} - -static void -kill_all_children(void) -{ - char name[256]; - SpadProcess *proc; - - - for(proc = spad_process_list; proc != NULL; proc = proc->next) { - kill(proc->proc_id, SIGTERM); - } - sprintf(name, "/tmp/hyper%d.input",server_num); - unlink(name); - -} - -static void -monitor_children(void) -{ - int dead_baby, stat; - SpadProcess *proc; - while (1) { - stat = 0; - dead_baby = wait(&stat); - /* Check the value of dead_baby, since wait may have returned - a pid but subsequently we have received a signal. Yeuch! */ - if (dead_baby == -1 && death_signal) { - kill_all_children(); - clean_up_sockets(); - openaxiom_sleep(2); - exit(0); - } - - if (dead_baby == -1) { - fprintf(stderr, "sman: wait returned -1\n"); - continue; - } - proc = find_child(dead_baby); - if (proc == NULL) { - /* fprintf(stderr, "sman: %d is not known to be a child process\n", - dead_baby); - */ - continue; - } - switch(proc->death_action) { - case Die: - kill_all_children(); - clean_up_sockets(); - openaxiom_sleep(2); - exit(0); - case NadaDelShitsky: - break; - case DoItAgain: - spawn_of_hell(proc->command, DoItAgain); - break; - case CleanHypertexSocket: - clean_hypertex_socket(); - break; - } - } -} - -int -main(int argc, char *argv[]) -{ - Command command; - command.root_dir = get_systemdir(argc, argv); - process_options(&command, argc, argv); - - oa_setenv("LC_ALL", "C"); - setlocale(LC_ALL, ""); - bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); - init_term_io(); - spad_process_list = NULL; - start_the_Axiom(&command); - if (open_server(SessionIOName) == -2) { - fprintf(stderr, "Fatal error opening I/O socket\n"); - clean_up_sockets(); - exit(-1); - } - start_the_session_manager(); - if (start_spadclient) - start_the_spadclient(); - if (start_local_spadclient) - start_the_local_spadclient(); - if (start_ht and in_X()) - start_the_hypertex(&command); - if (start_graphics and in_X()) - start_the_graphics(&command); - openaxiom_sleep(1); - - if (fork_you(Die) != NULL) { - sman_catch_signals(); - monitor_children(); - exit(0); - } - manage_spad_io(ptcNum); - return(0); -} - - diff --git a/src/sman/sman.cc b/src/sman/sman.cc new file mode 100644 index 00000000..ac941266 --- /dev/null +++ b/src/sman/sman.cc @@ -0,0 +1,794 @@ +/* + Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd. + All rights reserved. + Copyright (C) 2007-2014, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - 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. + + - Neither the name of The Numerical Algorithms Group Ltd. 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 OWNER + 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. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open-axiom.h" +#include "sockio.h" +#include "com.h" +#include "bsdsignal.h" +#include "sman.h" + +#include "sockio.h" +#include "openpty.h" +#include "cfuns.h" + +using namespace OpenAxiom; + +static void process_arguments(Command*, int, char**); +static int in_X(void); +static void set_up_defaults(void); +static void process_options(Command*, int, char**); +static void death_handler(int); +static void sman_catch_signals(void); +static void fix_env(int); +static void init_term_io(void); +static const char* strPrefix(const char* , const char*); +static void check_spad_proc(const char* , const char*); +static void clean_up_old_sockets(void); +static SpadProcess* fork_you(int); +static void exec_command_env(const char*); +static SpadProcess* spawn_of_hell(const char* , int); +static void start_the_spadclient(void); +static void start_the_local_spadclient(void); +static void start_the_session_manager(void); +static void start_the_hypertex(Command*); +static void start_the_graphics(Command*); +static void fork_Axiom(Command*); +static void start_the_Axiom(Command*); +static void clean_up_sockets(void); +static void clean_hypertex_socket(void); +static void read_from_spad_io(int); +static void read_from_manager(int); +static void manage_spad_io(int); +static SpadProcess* find_child(int); +static void kill_all_children(void); +static void monitor_children(void); + +/* System defined pointer to array or environment variables. */ +extern char** environ; + +int start_clef; /* start clef under spad */ +int start_graphics; /* start the viewman */ +int start_ht; /* start hypertex */ +int start_spadclient; /* Start the client spad buffer */ +int start_local_spadclient; /* Start the client spad buffer */ +int use_X; /* Use the X windows environment */ +int server_num; /* OpenAxiom server number */ + +/************************************************/ +/* definitions of programs which sman can start */ +/************************************************/ + +const char *GraphicsProgram = "/lib/viewman"; +const char *HypertexProgram = "/lib/hypertex"; +const char *ClefProgram = "$AXIOM/bin/clef -f $AXIOM/lib/command.list -e "; +const char *SessionManagerProgram = "$AXIOM/lib/session"; +const char *SpadClientProgram = "$AXIOM/lib/spadclient"; +char *PasteFile = NULL; +char *MakeRecordFile = NULL; +char *VerifyRecordFile = NULL; + +SpadProcess *spad_process_list = NULL; +/***************************/ +/* sman defaults file name */ +/***************************/ + +#define SpadDefaultFile "spadprof.input" + +char ClefCommandLine[256]; + +#define BufSize 4096 /* size of communication buffer */ +char big_bad_buf[BufSize]; /* big I/O buffer */ + +openaxiom_sio* session_io = NULL; /* socket connecting to session manager */ + +/***********************************************************/ +/* Some characters used and externally defined in edible.h */ +/***********************************************************/ + +unsigned char _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2; + +/*************************************/ +/* Stuff for opening pseudo-terminal */ +/*************************************/ + +int ptsNum, ptcNum; +char ptsPath[20]; + +int child_pid; /* child's process id */ +struct termios oldbuf; /* the original settings */ +struct termios childbuf; /* terminal structure for user i/o */ + + +int death_signal = 0; + +static void +process_arguments(Command* command, int argc,char ** argv) +{ + int arg; + int other = 0; + for (arg = 1; arg < argc; arg++) { + if (strcmp(argv[arg], "-noclef") == 0) + start_clef = 0; + else if (strcmp(argv[arg], "-clef") == 0) + start_clef = 1; + else if (strcmp(argv[arg], "-gr") == 0 + || strcmp(argv[arg], "--graph") == 0 ) { + if (!OPENAXIOM_HAVE_GRAPHICS) + fprintf(stderr, "OpenAxiom was not build with Graphics support.\n"); + else + start_graphics = 1; + } + else if (strcmp(argv[arg], "-nogr") == 0 + || strcmp(argv[arg], "--no-graph") == 0) + start_graphics = 0; + else if (strcmp(argv[arg], "-ht") == 0 + || strcmp(argv[arg], "--hyperdoc") == 0) { + if (!OPENAXIOM_HAVE_GRAPHICS) + fprintf(stderr, "OpenAxiom was not build with HyperDoc support.\n"); + else + start_ht = 1; + } + else if (strcmp(argv[arg], "-noht") == 0 + || strcmp(argv[arg], "--no-hyperdoc") == 0) + start_ht = 0; + else if (strcmp(argv[arg], "-iw") == 0) + start_spadclient = 1; + else if (strcmp(argv[arg], "-ihere") == 0) + start_local_spadclient = 1; + else if (strcmp(argv[arg], "-noihere") == 0) + start_local_spadclient = 0; + else if (strcmp(argv[arg], "-noiw") == 0) + start_spadclient = 0; + else if (strcmp(argv[arg], "-nox") == 0 + || strcmp(argv[arg], "--no-gui") == 0) { + use_X = 0; + start_local_spadclient = 1; + start_spadclient = 0; + start_ht = 0; + start_graphics = 0; + } + else if (strcmp(argv[arg], "-clefprog") == 0) { + strcpy(ClefCommandLine,argv[++arg]); + ClefProgram = + strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e "); + } + else if (strcmp(argv[arg], "-rm") == 0) + MakeRecordFile = argv[++arg]; + else if (strcmp(argv[arg], "-rv") == 0) + VerifyRecordFile = argv[++arg]; + else if (strcmp(argv[arg], "-paste") == 0) + PasteFile = argv[++arg]; + else + argv[other++] = argv[arg]; + } + + command->core.argv = argv; + command->core.argc = other; + +/* If there were no X libraries + * at build-time, we proceed to + * overwrite the defaults startup + * values to not start any of the + * graphical components of + * OpenAxiom (Hyperdoc, Graphics). */ + + if (!OPENAXIOM_HAVE_GRAPHICS) { + use_X = 0; + start_local_spadclient = 1; + start_ht = 0; + start_graphics = 0; + } +} + +static int +in_X(void) +{ + if (oa_getenv("DISPLAY")) return 1; + return 0; +} + +static void +set_up_defaults(void) +{ + start_clef = 1; + start_graphics = 1; + start_ht = 1; + start_spadclient = 0; + start_local_spadclient = 1; + use_X = isatty(0) && in_X(); +} + +static void +process_options(Command* command, int argc, char **argv) +{ + set_up_defaults(); + process_arguments(command, argc, argv); + /* Complain about command line arguments unknown to Superman. */ + if (command->core.argc > 0) { + int i; + for (i = 0; i < command->core.argc; ++i) + fprintf(stderr,"command line error: %s\n", command->core.argv[i]); + exit(-1); + } +} + +static void +death_handler(int sig) +{ + death_signal = 1; +} + +static void +sman_catch_signals(void) +{ + + /* Set up the signal handlers for sman */ + bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); + bsdSignal(SIGTERM, death_handler,RestartSystemCalls); + bsdSignal(SIGQUIT, death_handler,RestartSystemCalls); + bsdSignal(SIGHUP, death_handler,RestartSystemCalls); + bsdSignal(SIGILL, death_handler,RestartSystemCalls); + bsdSignal(SIGTRAP, death_handler,RestartSystemCalls); + +#ifdef SIGABRT + bsdSignal(SIGABRT, death_handler,RestartSystemCalls); +#else + #ifdef SIGIOT + bsdSignal(SIGIOT, death_handler,RestartSystemCalls); + #endif +#endif + + bsdSignal(SIGBUS, death_handler,RestartSystemCalls); + bsdSignal(SIGSEGV, death_handler,RestartSystemCalls); + +} + +static void +fix_env(int spadnum) +{ + char sn[20]; + sprintf(sn, "%d", spadnum); + oa_setenv("SPADNUM", sn); + oa_setenv("SPADSERVER", "TRUE"); +} + +static void +init_term_io(void) +{ + if(!isatty(0)) return; + if( tcgetattr(0, &oldbuf) == -1) { + perror("getting termios"); + return ; /* exit(-1); */ + } + if( tcgetattr(0, &childbuf) == -1) { + perror("getting termios"); + return ; /* exit(-1); */ + } + _INTR = oldbuf.c_cc[VINTR]; + _QUIT = oldbuf.c_cc[VQUIT]; + _ERASE = oldbuf.c_cc[VERASE]; + _KILL = oldbuf.c_cc[VKILL]; + _EOF = oldbuf.c_cc[VEOF]; + _EOL = oldbuf.c_cc[VEOL]; +} + +static const char* +strPrefix(const char* prefix, const char* s) +{ + while (*prefix != '\0' && *prefix == *s) { + prefix++; + s++; + } + if (*prefix == '\0') return s; + return NULL; +} + +static void +check_spad_proc(const char *file, const char *prefix) +{ + const char *num; + int pid; + if ((num = strPrefix(prefix, file))) { + pid = atoi(num); + if (pid > 2) { + kill(pid, 0); + if (kill(pid, 0) == -1 && errno == ESRCH) { + unlink(file); + } + } + } +} + +static void +clean_up_old_sockets(void) +{ + char com[512], tmp_file[128]; + FILE *file; + int len; + sprintf(tmp_file, "/tmp/socks.%d", server_num); + sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s", + tmp_file, tmp_file); + system(com); + file = fopen(tmp_file, "r"); + if (file == NULL) { + fprintf(stderr, "Can't open socket listing file\n"); + return; + } + while(fgets(com, 512, file) != NULL) { + len = strlen(com); + if (len) com[len-1] = '\0'; + else break; + check_spad_proc(com, "/tmp/.d"); + check_spad_proc(com, "/tmp/.s"); + check_spad_proc(com, "/tmp/.i"); + check_spad_proc(com, "/tmp/.h"); + } + fclose(file); + unlink(tmp_file); +} + +static SpadProcess * +fork_you(int death_action) +{ + /* fork a new process, giving it a default death action */ + /* return NULL in child, SpadProcess in parent */ + int child_pid = fork(); + SpadProcess *proc; + if (!child_pid) return NULL; + proc = (SpadProcess *) malloc(sizeof(SpadProcess)); + proc->proc_id = child_pid; + proc->death_action = death_action; + proc->command = NULL; + proc->next = spad_process_list; + spad_process_list = proc; + return proc; +} + +static void +exec_command_env(const char *command) +{ + char new_command[512]; + sprintf(new_command, "exec %s", command); + execle("/bin/sh","/bin/sh", "-c", new_command, (char*)NULL, environ); +} + +static SpadProcess * +spawn_of_hell(const char *command, int death_action) +{ + SpadProcess *proc = fork_you(death_action); + if (proc != NULL) { + proc->command = command; + return proc; + } + exec_command_env(command); + return NULL; +} + +static void +start_the_spadclient(void) +{ + char command[256]; + if (start_clef) + sprintf(command, + "xterm -sb -sl 500 -name axiomclient -n OpenAxiom -T OpenAxiom -e %s %s", + ClefProgram, SpadClientProgram); + else + sprintf(command, + "xterm -sb -sl 500 -name axiomclient -n OpenAxiom -T OpenAxiom -e %s", + SpadClientProgram); + spawn_of_hell(command, NadaDelShitsky); +} + +static void +start_the_local_spadclient(void) +{ + char command[256]; + if (start_clef) + sprintf(command, "%s %s", ClefProgram, SpadClientProgram); + else + sprintf(command, "%s", SpadClientProgram); + spawn_of_hell(command, NadaDelShitsky); +} + +static void +start_the_session_manager(void) +{ + spawn_of_hell(SessionManagerProgram, Die); +} + +static void +start_the_hypertex(Command* cmd) +{ + const char* root_dir = cmd->root_dir; + const char* command = oa_concatenate_string(root_dir,HypertexProgram); + + if (readablep(command) != 1) { + fprintf(stderr, "Hypertex program not found.\n"); + return; + } + if (PasteFile){ + command = oa_concatenate_string(command, " -s -k -ip "); + command = oa_concatenate_string(command, PasteFile); + spawn_of_hell(command, NadaDelShitsky); + } + else if (MakeRecordFile){ + command = oa_concatenate_string(command, " -s -k -rm "); + command = oa_concatenate_string(command, MakeRecordFile); + spawn_of_hell(command, NadaDelShitsky); + } + else if (VerifyRecordFile){ + command = oa_concatenate_string(command, " -s -k -rv "); + command = oa_concatenate_string(command, VerifyRecordFile); + spawn_of_hell(command, NadaDelShitsky); + } + else + spawn_of_hell(command, CleanHypertexSocket); +} + +static void +start_the_graphics(Command* cmd) +{ + const char* root_dir = cmd -> root_dir; + const char* command = oa_concatenate_string(root_dir,GraphicsProgram); + + if (readablep(command) == 1) + spawn_of_hell(command, DoItAgain); + else + fprintf(stderr, "Graphics program not found.\n"); +} + +/* Start the core executable session in a separate process, */ +/* using a pseudo-terminal to catch all input and output */ +static void +fork_Axiom(Command* cmd) +{ + SpadProcess *proc; + + proc = fork_you(Die); + child_pid = (proc == NULL ? 0 : proc->proc_id); + switch(child_pid) { + case -1 : + fprintf(stderr, "Can't create a new process \n"); + exit(0); + case 0: + /* Dissasociate from my parents group so all my child processes */ + /* look at my terminal as the controlling terminal for the */ + /* group */ + + if(setsid() < 0) { + perror("Dissassociating from parents group"); + exit(-1); + } + + close(ptsNum); + /* Now reopen the server side, so that pg, su, etc. work properly */ + + if ((ptsNum = open(ptsPath, O_RDWR)) < 0 ) { + perror("fork_Axiom: Failed to reopen server"); + exit(-1); + } +#if defined(SUN4OS5platform) || defined(HP10platform) + ioctl(ptsNum,I_PUSH,"ptem"); + ioctl(ptsNum,I_PUSH,"ldterm"); +#endif + + /* since I am the child, I can close ptc, and dup pts for all its */ + /* standard descriptors */ + + if( (dup2(ptsNum, 0) == -1) || + (dup2(ptsNum, 1) == -1) || + (dup2(ptsNum, 2) == -1) ) { + perror("trying to dupe the child"); + exit(-1); + } + close(ptcNum); + close(ptsNum); + + + /* I also have to turn off echoing, since I am echoing all the */ + /* input myself */ + + childbuf.c_lflag &= ~ECHO; + if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) { + perror("setting the term buffer"); + exit(-1); + } + + /* Tell the Core that it is being invoked in server mode. */ + oa_allocate_process_argv(&cmd->core, 2); + cmd->core.argv[0] = (char*) make_path_for(cmd->root_dir, Driver::core); + cmd->core.argv[1] = (char*) "--role=server"; + execute_core(cmd, Driver::core); + } +} + +static void +start_the_Axiom(Command* cmd) +{ + server_num = make_server_number(); + clean_up_old_sockets(); + if (server_num == -1) { + fprintf(stderr, "could not get an OpenAxiom server number\n"); + exit(-1); + } + if (ptyopen(&ptcNum, &ptsNum, ptsPath) == -1) { + perror("start_the_Axiom: ptyopen failed"); + exit(-1); + } + fix_env(server_num); + fork_Axiom(cmd); + close(ptsNum); +} + +static void +clean_hypertex_socket(void) +{ + char name[256]; + sprintf(name, "%s%d", MenuServerName, server_num); + unlink(name); +} + +static void +clean_up_sockets(void) +{ + char name[256]; + sprintf(name, "%s%d", SpadServer, server_num); + unlink(name); + sprintf(name, "%s%d", SessionServer, server_num); + unlink(name); + sprintf(name, "%s%d", SessionIOName, server_num); + unlink(name); + clean_hypertex_socket(); +} + +static void +read_from_spad_io(int ptcNum) +{ + int ret_code = 0, i=0; + static int mes_len =0; + ret_code = read(ptcNum, big_bad_buf, BufSize); + if (ret_code == -1) { + clean_up_sockets(); + exit(-1); + } + if (session_io == NULL) { + if (ret_code < mes_len) + mes_len -= ret_code; + else { + if (mes_len > 0) { + i = mes_len; + mes_len = 0; + } + else + i = 0; + ret_code = write(1, big_bad_buf+i, ret_code-i); + } + } + else + ret_code = swrite(session_io, byte_address(big_bad_buf), ret_code, + "writing to session man"); + if (ret_code == -1) { + perror("writing output to session manager"); + clean_up_sockets(); + exit(-1); + } +} + +static void +read_from_manager(int ptcNum) +{ + int ret_code; + ret_code = sread(session_io, byte_address(big_bad_buf), BufSize, + "reading session io"); + if (ret_code == -1) { + return; + } + ret_code = write(ptcNum, big_bad_buf, ret_code); + if (ret_code == -1) { + return; + } +} + +static void +manage_spad_io(int ptcNum) +{ + int ret_code, p; + fd_set rd; + while (1) { + rd = socket_mask; + FD_SET(ptcNum, &rd); + if (session_io != NULL) + FD_SET(session_io->socket, &rd); + ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL); + if (ret_code == -1) { + perror("Session manager select"); + clean_up_sockets(); + exit(-1); + } + if (FD_ISSET(ptcNum, &rd)) { + read_from_spad_io(ptcNum); + } + if (server.socket > 0 && FD_ISSET(server.socket, &rd)) { + p = accept_connection(); + switch(p) { + case SessionIO: + session_io = purpose_table[SessionIO]; + /* printf("connected session manager\n\r");*/ + printf("\n"); + break; + default: + printf("sman: Unknown connection request type: %d\n", p); + break; + } + } + if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) { + read_from_manager(ptcNum); + } + } +} + +#if 0 +static void +print_spad_process_list() +{ + SpadProcess *proc; + for(proc = spad_process_list; proc != NULL; proc = proc->next) + fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id, + proc->death_action); +} +#endif + +static SpadProcess * +find_child(int proc_id) +{ + SpadProcess *proc; + for(proc = spad_process_list; proc != NULL; proc = proc->next) + if (proc->proc_id == proc_id) return proc; + return NULL; +} + +static void +kill_all_children(void) +{ + char name[256]; + SpadProcess *proc; + + + for(proc = spad_process_list; proc != NULL; proc = proc->next) { + kill(proc->proc_id, SIGTERM); + } + sprintf(name, "/tmp/hyper%d.input",server_num); + unlink(name); + +} + +static void +monitor_children(void) +{ + int dead_baby, stat; + SpadProcess *proc; + while (1) { + stat = 0; + dead_baby = wait(&stat); + /* Check the value of dead_baby, since wait may have returned + a pid but subsequently we have received a signal. Yeuch! */ + if (dead_baby == -1 && death_signal) { + kill_all_children(); + clean_up_sockets(); + openaxiom_sleep(2); + exit(0); + } + + if (dead_baby == -1) { + fprintf(stderr, "sman: wait returned -1\n"); + continue; + } + proc = find_child(dead_baby); + if (proc == NULL) { + /* fprintf(stderr, "sman: %d is not known to be a child process\n", + dead_baby); + */ + continue; + } + switch(proc->death_action) { + case Die: + kill_all_children(); + clean_up_sockets(); + openaxiom_sleep(2); + exit(0); + case NadaDelShitsky: + break; + case DoItAgain: + spawn_of_hell(proc->command, DoItAgain); + break; + case CleanHypertexSocket: + clean_hypertex_socket(); + break; + } + } +} + +int +main(int argc, char *argv[]) +{ + Command command; + command.root_dir = get_systemdir(argc, argv); + process_options(&command, argc, argv); + + oa_setenv("LC_ALL", "C"); + setlocale(LC_ALL, ""); + bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls); + init_term_io(); + spad_process_list = NULL; + start_the_Axiom(&command); + if (open_server(SessionIOName) == -2) { + fprintf(stderr, "Fatal error opening I/O socket\n"); + clean_up_sockets(); + exit(-1); + } + start_the_session_manager(); + if (start_spadclient) + start_the_spadclient(); + if (start_local_spadclient) + start_the_local_spadclient(); + if (start_ht and in_X()) + start_the_hypertex(&command); + if (start_graphics and in_X()) + start_the_graphics(&command); + openaxiom_sleep(1); + + if (fork_you(Die) != NULL) { + sman_catch_signals(); + monitor_children(); + exit(0); + } + manage_spad_io(ptcNum); + return(0); +} + + diff --git a/src/sman/spadclient.c b/src/sman/spadclient.c deleted file mode 100644 index 85b8815e..00000000 --- a/src/sman/spadclient.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd. - All rights reserved. - Copyright (C) 2007-2009, Gabriel Dos Reis. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - 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. - - - Neither the name of The Numerical Algorithms Group Ltd. 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 OWNER - 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. -*/ - - -#define _SPADCLIENT_C - -#include -#include -#include - -#include "openaxiom-c-macros.h" -#include "sockio.h" -#include "com.h" -#include "bsdsignal.h" -#include "cfuns.h" -#include - -#include "sockio.h" - -using namespace OpenAxiom; - -openaxiom_sio* sock; - -static void -inter_handler(int sig) -{ - send_signal(sock, SIGUSR2); - fflush(stderr); -} - - -int -main(void) -{ - using namespace OpenAxiom; - oa_setenv("LC_ALL", "C"); - setlocale(LC_ALL, ""); - sock = connect_to_local_server(SessionServer, InterpWindow, Forever); - bsdSignal(SIGINT, inter_handler,RestartSystemCalls); - remote_stdio(sock); - return(0); -} - diff --git a/src/sman/spadclient.cc b/src/sman/spadclient.cc new file mode 100644 index 00000000..029d354a --- /dev/null +++ b/src/sman/spadclient.cc @@ -0,0 +1,74 @@ +/* + Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd. + All rights reserved. + Copyright (C) 2007-2009, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - 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. + + - Neither the name of The Numerical Algorithms Group Ltd. 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 OWNER + 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. +*/ + + +#define _SPADCLIENT_C + +#include +#include +#include + +#include "sockio.h" +#include "com.h" +#include "bsdsignal.h" +#include "cfuns.h" +#include + +#include "sockio.h" + +using namespace OpenAxiom; + +openaxiom_sio* sock; + +static void +inter_handler(int sig) +{ + send_signal(sock, SIGUSR2); + fflush(stderr); +} + + +int +main(void) +{ + using namespace OpenAxiom; + oa_setenv("LC_ALL", "C"); + setlocale(LC_ALL, ""); + sock = connect_to_local_server(SessionServer, InterpWindow, Forever); + bsdSignal(SIGINT, inter_handler,RestartSystemCalls); + remote_stdio(sock); + return(0); +} + -- cgit v1.2.3