/* Copyright (C) 2002 Hayato Fujiwara This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include "defun-dld.h" #include "dirfns.h" #include "error.h" #include "help.h" #include "oct-map.h" #include "systime.h" #include "ov.h" #include "oct-obj.h" #include "utils.h" #include "oct-env.h" #include "file-io.h" #ifndef HAVE_OCTAVE_29 #include "pt-plot.h" #endif #include "sighandlers.h" #include "parse.h" #include "cmd-edit.h" #include "variables.h" #include "toplev.h" #include "sysdep.h" #include "oct-prcstrm.h" #include "oct-stream.h" #include "oct-strstrm.h" #include "oct-iostrm.h" #include "unwind-prot.h" #include "input.h" #ifdef NEED_OCTAVE_QUIT #define OCTAVE_QUIT do {} while (0) #else #include "quit.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUFF_SIZE SSIZE_MAX static bool quitting_gracefully = false; // Handle server SIGTERM SIGQUIT static RETSIGTYPE sigterm_handler (int /* sig */) { int len=118; char hostname[120],pidname[128]; gethostname(hostname,len); sprintf(pidname,"/tmp/.octave-%s.pid",hostname); remove (pidname); close_files (); std::cerr << "exiting, " < 0) ; signal(SIGCHLD, sigchld_handler); } // XXX FIXME XXX -- this should really be static, but that causes // problems on some systems. std::stack octave_atexit_functions; void do_octave_atexit_server (void) { static bool deja_vu = false; while (! octave_atexit_functions.empty ()) { std::string fcn = octave_atexit_functions.top (); octave_atexit_functions.pop (); feval (fcn, octave_value_list (), 0); flush_octave_stdout (); } if (! deja_vu) { deja_vu = true; command_editor::restore_terminal_state (); // XXX FIXME XXX -- is this needed? Can it cause any trouble? raw_mode (0); close_files (); cleanup_tmp_files (); flush_octave_stdout (); if (!quitting_gracefully && (interactive || forced_interactive)) std::cout << "\n"; } } void clean_up_and_exit_server (int retval) { do_octave_atexit_server (); exit (retval == EOF ? 0 : retval); } int reval_loop (int sock) { // Allow the user to interrupt us without exiting. int len=0; char *ev_str; std::string s; octave_save_signal_mask (); if (octave_set_current_context) { #if defined (USE_EXCEPTIONS_FOR_INTERRUPTS) panic_impossible (); #else unwind_protect::run_all (); raw_mode (0); std::cout << "\n"; octave_restore_signal_mask (); #endif } can_interrupt = true; octave_catch_interrupts (); octave_initialized = true; // The big loop. char dummy; read(sock,&dummy,sizeof(char)); int retval,count,r_len,num,fin,nl; struct pollfd *pollfd; pollfd=(struct pollfd *)malloc(sizeof(struct pollfd)); pollfd[0].fd=sock; pollfd[0].events=0; pollfd[0].events=POLLIN|POLLERR|POLLHUP; do { pollfd[0].revents=0; num=poll(pollfd,1,-1); if(num){ if(pollfd[0].revents && (pollfd[0].fd !=0)){ if(pollfd[0].revents&POLLIN){ fin=read(sock,&nl,sizeof(int)); len=ntohl(nl); if(!fin) clean_up_and_exit_server (0); } if(pollfd[0].revents&POLLERR){ std::cerr <<"Error condition "<sin_family=AF_INET; addr->sin_port=htons(12502); addr->sin_addr.s_addr=INADDR_ANY; if(bind(sock,(struct sockaddr *) addr,sizeof(*addr))!=0){ perror("bind "); int len=118; char hostname[120],pidname[128]; gethostname(hostname,len); sprintf(pidname,".octave-%s.pid",hostname); remove (pidname); close_files (); clean_up_and_exit (1); } free(addr); if(listen(sock,1)!=0){ perror("listen "); clean_up_and_exit (1); } dsock=socket(PF_INET,SOCK_STREAM,0); if(dsock==-1){ perror("socket : "); exit(-1); } addr=(struct sockaddr_in *) calloc(1,sizeof(struct sockaddr_in)); addr->sin_family=AF_INET; addr->sin_port=htons(12501); addr->sin_addr.s_addr=INADDR_ANY; if(bind(dsock,(struct sockaddr *) addr,sizeof(*addr))!=0){ perror("bind : "); exit(-1); } if(listen(dsock,SOMAXCONN)!=0){ perror("listen : "); exit(-1); } free(addr); int param=1; socklen_t ol=sizeof(param); setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,¶m,ol); setsockopt(dsock,SOL_SOCKET,SO_REUSEADDR,¶m,ol); int val=1,num_nodes,me,i,j=0,pppid=0,rpppid=0,result=0,nl; int *sock_v; char **host_list,rem_name[128]; struct hostent *he; ol=sizeof(val); for(;;) { asock=accept(sock,0,0); if(asock==-1){ perror("accept com"); clean_up_and_exit (1); } /* Normal production daemon. Fork, and have the child process the connection. The parent continues listening. */ if((pid=fork())==-1) { perror("fork "); clean_up_and_exit (1); } else if(pid==0) { close(sock); signal(SIGCHLD,SIG_DFL); signal(SIGTERM,SIG_DFL); signal(SIGQUIT,SIG_DFL); val=1; ol=sizeof(val); setsockopt(asock,SOL_SOCKET,SO_REUSEADDR,&val,ol); read(asock,&nl,sizeof(int)); num_nodes=ntohl(nl); read(asock,&nl,sizeof(int)); me=ntohl(nl); read(asock,&nl,sizeof(int)); pppid=ntohl(nl); sock_v=(int *)calloc((num_nodes+1)*3,sizeof(int)); host_list=(char **)calloc(num_nodes,sizeof(char *)); for(i=0;i<=num_nodes;i++){ read(asock,&nl,sizeof(int)); len=ntohl(nl); host_list[i]=(char *)calloc(len,sizeof(char *)); read(asock,host_list[i],len); } sprintf(errname,"/tmp/octave_error-%s_%05d.log",hostname,pppid); if(stat(errname,&fstat)==0){ sprintf(bakname,"/tmp/octave_error-%s_%05d.bak",hostname,pppid); rename(errname,bakname); } freopen(errname, "w", stderr); for(i=0;isin_family=AF_INET; addr->sin_port=htons(12501); he=gethostbyname(host_list[i]); if(he == NULL){ error("Unknown host %s",host_list[i]); } memcpy(&addr->sin_addr,he->h_addr_list[0],he->h_length); while(1){ for(j=0;j<10;j++){ if(connect(dsock,(struct sockaddr *)addr,sizeof(*addr))==0){ break; }else if(errno!=ECONNREFUSED){ perror("connect : "); exit(-1); }else { usleep(5000); } } int bufsize=262144; socklen_t ol; ol=sizeof(bufsize); setsockopt(dsock,SOL_SOCKET,SO_SNDBUF,&bufsize,ol); setsockopt(dsock,SOL_SOCKET,SO_RCVBUF,&bufsize,ol); bufsize=1; ol=sizeof(bufsize); setsockopt(dsock,SOL_SOCKET,SO_REUSEADDR,&bufsize,ol); //send pppid write(dsock,&nl,sizeof(int)); pppid=ntohl(nl); //send name size len=strlen(host_list[me]); nl=htonl(len); write(dsock,&nl,sizeof(int)); //send name write(dsock,host_list[me],len+1); //recv result code read(dsock,&nl,sizeof(int)); result=ntohl(nl); if(result==0){ sock_v[i]=dsock; //recv endian read(sock,&nl,sizeof(int)); sock_v[i+2*(num_nodes+1)]=ntohl(nl); //send endian nl=htonl(__BYTE_ORDER); write(sock,&nl,sizeof(int)); break; }else{ close(dsock); } } free(addr); } /* for(i=0;i<=num_nodes;i++){ free(host_list[i]); } free(host_list); */ //normal act install_signal_handlers (); atexit (do_octave_atexit_server); char * s; int stat; s=(char *)calloc(32,sizeof(char)); sprintf(s,"sockets=[%d,0,%d]",sock_v[0],sock_v[2*(num_nodes+1)]); eval_string(std::string(s),true,stat); for(i=1;i<=num_nodes;i++){ sprintf(s,"sockets=[sockets;%d,0,%d]",sock_v[i+2*(num_nodes+1)]); eval_string(std::string(s),true,stat); } interactive = false; line_editing = false; // int retval = main_loop (); char *newdir; int newdir_len; read(asock,&nl,sizeof(int)); newdir_len=ntohl(nl); newdir=(char *)calloc(sizeof(char),newdir_len+1); read(asock,newdir,newdir_len); int cd_ok=octave_env::chdir (newdir); if(cd_ok != true){ octave_env::chdir ("/tmp"); } int retval = reval_loop(asock); if (retval == 1 && ! error_state) retval = 0; close(asock); clean_up_and_exit_server (retval); } close(asock); } close(sock); exit(-1); }