home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / comserver / comserver.c < prev    next >
C/C++ Source or Header  |  1995-01-14  |  22KB  |  990 lines

  1. /* 
  2.  * Compute Server for ME2
  3.  *
  4.  * comserver socket-name
  5.  */
  6.  
  7. /* 
  8.  * Notes:
  9.  *   select() sez a pipe has input when the pipe is closed.
  10.  */
  11.  
  12. /* Protocol
  13.  *   Send/recieve packets
  14.  *   Packet format: <type><bytes>
  15.  *     <type> is 4 byte int
  16.  *     STRING <length><bytes>
  17.  *     NUMBER <number>
  18.  *  Types of Packets:
  19.  *    To server:
  20.  *      Connect
  21.  *      Disconnect
  22.  *      Dir-to-compute-in <dir>
  23.  *      Command-to-exec <command> <arg1> <arg2> ...
  24.  *      Just-do-it
  25.  *        Exec current cp.
  26.  *      Stop-process
  27.  *        Terminate the current process, if it is exec'ed.
  28.  *        Can be exec'ed again.
  29.  *      Delete-process
  30.  *        Stop and remove from process server the cp.
  31.  *      Send-me-signals <my-pid>
  32.  *      Create-process
  33.  *        Creates a cp.
  34.  *      Make-process-current <cpid>
  35.  *        Make a cp the current one so can change it, exec it, etc.
  36.  *    To client:
  37.         ???? what process
  38.  *      Output-stdout <text>
  39.  *      Output-stderr <text>
  40.  *      Process completed, exit status
  41.  */
  42.  
  43. /* Copyright 1991 Craig Durland
  44.  *   Distributed under the terms of the GNU General Public License.
  45.  *   Distributed "as is", without warranties of any kind, but comments,
  46.  *     suggestions and bug reports are welcome.
  47.  */
  48.  
  49. static char what[] = "@(#)Compute Server 2/17/91 v1.2 8/93";
  50.  
  51. #ifdef __STDC__
  52.  
  53. #ifdef __hpux            /* for ANSI C on HP-UX */
  54. #define _HPUX_SOURCE
  55. #endif  /* __hpux */
  56.  
  57. #ifdef __apollo            /* for ANSI C on Apollo BSD */
  58. #define _BSD_SOURCE
  59. #endif    /* __apollo */
  60.  
  61. #ifdef _AIX            /* for ANSI C on IBM AIX */
  62. #define _ALL_SOURCE
  63. #endif  /* _AIX */
  64.  
  65. #endif    /*  __STDC__ */
  66.  
  67. #include <stdio.h>
  68. #include <sys/types.h>
  69. #include <fcntl.h>
  70. #include <const.h>
  71.  
  72. #include <os.h>
  73.  
  74. #if BSD_OS || POSIX_OS || AIX_OS
  75. #include <sys/time.h>
  76.  
  77. #else    /* SYSV_OS */
  78.  
  79. #include <time.h>
  80. #endif
  81.  
  82. #include <signal.h>
  83. #include "comserver.h"
  84.  
  85. /* *********************  ***************************** */
  86.  
  87. typedef struct Process
  88. {
  89.   int id;        /* 0...?   !!!??? rollover?? use table[10]? */
  90.   int pid;        /* process id, 0 if process not running */
  91.   int two_pipe;        /* TRUE if use seprate stdout and stderr */
  92.   int fd_output[2];    /* 0 is stdout, 1 is stderr */
  93.   int self_destruct;    /* TRUE if go away when done */
  94.   int go_mask;
  95.   char
  96.     *dir,        /* directory to compute in */
  97.     *command;        /* command to exec */
  98.   struct Process *next;
  99. } Process;
  100.  
  101. typedef struct Client
  102. {
  103.   int
  104.     id_seed,    /* 1...?   !!!??? rollover?? don't use 0, use table[10]? */
  105.     pid,        /* clients pid */
  106.     sig,        /* signal to use to kick client */
  107.     socket,        /* socket used to talk to client */
  108.     blocked;        /* true if haven't written all of packet */
  109.   CSPacket packet;
  110.   Process
  111.     *processes,        /* list of processes */
  112.     *current_process;
  113.   struct Client *next;
  114. } Client;
  115.  
  116. /* ******************************************************************** */
  117. /* *********************************  ********************************* */
  118. /* ******************************************************************** */
  119.  
  120. static int
  121.   get_dpart(), open_request_socket(), another_server_running(), get_packet(),
  122.   connect_to_client();
  123. static void
  124.   flush_client(), flush_all_clients(), process_done(), close_process();
  125.  
  126. /* ******************************************************************** */
  127. /* ************************ Select Mask Stuff ************************* */
  128. /* ******************************************************************** */
  129.  
  130. #define CONNECT            0
  131. #define CLIENT_SEND        1
  132. #define PROCESS_SEND        2
  133. #define PROCESS_SEND_ERR    3
  134.  
  135.  
  136. #define MAX_FDS        32    /* max file descripters */
  137.  
  138. typedef struct
  139. {
  140.   int
  141.     class,
  142.     live;        /* if fd is for real */
  143.   Client *client;
  144.   Process *process;
  145. } FD;
  146.  
  147. #define MASK(f)        (1 << (f))
  148.  
  149. static int select_mask, biggest_fd;
  150. static FD fd_table[MAX_FDS];    /* all fields set to 0 */
  151.  
  152. static void make_select_mask()
  153. {
  154.   FD *pfd;
  155.   int n, fd;
  156.  
  157.   select_mask = 0;
  158.   biggest_fd = 0;
  159.  
  160.   for (n = MAX_FDS; n--; )
  161.   {
  162.     pfd = &fd_table[n];
  163.     if (pfd->live && !(pfd->client && pfd->client->blocked))
  164.     {
  165.       fd = n;
  166.       select_mask |= MASK(fd);
  167.       biggest_fd = imax(biggest_fd, fd);
  168.     }
  169.   }
  170.   biggest_fd++;
  171. }
  172.  
  173. static int add_fd(fd, client, process, class)
  174.   int fd; Client *client; Process *process; int class;
  175. {
  176.   FD *pfd;
  177.  
  178.   if (fd >= MAX_FDS || fd == -1) return FALSE;        /* full up */
  179.  
  180.   if (!fd_table[fd].live)
  181.   {
  182.     pfd = &fd_table[fd];
  183.     pfd->live = TRUE;
  184.  
  185.     pfd->client = client;
  186.     pfd->process = process;
  187.     pfd->class = class;
  188.  
  189.     make_select_mask();
  190.   }
  191.  
  192.   return TRUE;
  193. }
  194.  
  195. static int remove_fd(fd) int fd;
  196. {
  197.   FD *pfd;
  198.  
  199.   if (fd < 0 || fd >= MAX_FDS) return FALSE;
  200.  
  201.   pfd = &fd_table[fd];
  202.   if (!pfd->live) return FALSE;
  203.  
  204.   pfd->live = FALSE;
  205.   close(fd);
  206.  
  207.   make_select_mask();
  208.  
  209.   return TRUE;
  210. }
  211.  
  212. static int selecter;
  213.  
  214. static int wait_for_something()
  215. {
  216.   int readfds, nfound;
  217.   struct timeval timeout;
  218.  
  219.   selecter = 0;
  220.  
  221.   timeout.tv_sec  = 2;
  222.   timeout.tv_usec = 0;
  223.  
  224.   while (TRUE)
  225.   {
  226.     readfds = select_mask;
  227.     if ((nfound = select(biggest_fd, &readfds, 0, 0, &timeout)) == -1)
  228.     perror("select failed");
  229.     else
  230.       if (nfound == 0)    /* select timeout */
  231.       {
  232.     flush_all_clients();    /* in case any are blocked */
  233.       }
  234.       else
  235.       {
  236.     selecter = readfds;
  237.           return TRUE;
  238.       }
  239.   }
  240.   /* doesn't get here */
  241. }
  242.  
  243. static FD *whats_waiting()
  244. {
  245.   int n, bit;
  246.  
  247.   for (n = biggest_fd; n--; )
  248.   {
  249.     bit = MASK(n);
  250.  
  251.     if (bit & selecter)
  252.     {
  253.       selecter &= ~bit;
  254.  
  255.       return &fd_table[n];
  256.     }
  257.   }
  258.   return NULL;
  259. }
  260.  
  261. /* *********************  ***************************** */
  262.  
  263. extern char *malloc();
  264. static void sig_die();
  265.  
  266. main(argc, argv) int argc; char **argv;
  267. {
  268.   char *socket_name;
  269.   FD *foo;
  270.  
  271.   if (argc < 2) { printf("comserver socket-name\n"); exit(1); }
  272.  
  273.   socket_name = argv[1];
  274.  
  275.   if (another_server_running(socket_name))
  276.   {
  277.     printf("Another server running!\n    On socket: \"%s\"\n",socket_name);
  278.     exit(1);
  279.   }
  280.  
  281.   signal(SIGTERM,sig_die);
  282.   signal(SIGHUP, sig_die);
  283.   signal(SIGINT, sig_die);
  284.  
  285. signal(SIGPIPE,SIG_IGN);
  286.  
  287.   if (!open_request_socket(socket_name)) exit(1);
  288.  
  289.   while (TRUE)
  290.   {
  291.     wait_for_something();
  292.     while (foo = whats_waiting())
  293.     {
  294.       Client *client = foo->client;
  295.       Process *process = foo->process;
  296.  
  297.       switch(foo->class)
  298.       {
  299.     case CONNECT:            /* client trying to connect */
  300.       connect_to_client();
  301.       break;
  302.     case CLIENT_SEND:        /* client sending me data */
  303.       get_packet(client);
  304.       break;
  305.     case PROCESS_SEND:        /* process sending me data */
  306.       transfer_data(client, process, process->fd_output[0],
  307.         CS_OUTPUT, 0x1);
  308.       break;
  309.     case PROCESS_SEND_ERR:        /* process sending me data */
  310.       transfer_data(client, process, process->fd_output[1],
  311.         CS_OUTPUT_ERR, 0x2);
  312.       break;
  313.       }
  314.     }
  315.   }
  316.   /* Doesn't get here */
  317. }
  318.  
  319.  
  320. /* ******************************************************************** */
  321. /* ***************************** Signals ****************************** */
  322. /* ******************************************************************** */
  323.  
  324. #include <sys/wait.h>
  325.  
  326. static int command_exit_status;
  327.  
  328.     /* Signal handler for sig child.
  329.      * If we get this signal, we know wait() will return immediately.
  330.      */
  331. static void sig_child(dummy) int dummy;
  332. {
  333.   int s, pid;
  334.  
  335.   pid = wait(&s);
  336.  
  337.   command_exit_status = WEXITSTATUS(s);
  338.  
  339. #if 0
  340. {
  341.   Process *process = the_client.current_process;
  342.   if (process) process_done(&the_client, process);
  343.   else printf("process already closed\n");
  344. }
  345. #endif
  346. printf("sig_child: pid = %d,  s = %x, %d\n",pid, s, command_exit_status);
  347. }
  348.  
  349. static void close_all_clients();
  350.  
  351. static void sig_die()
  352. {
  353.   close_all_clients();
  354.   printf("\nCompute Server stopped via signal\n");
  355.   exit(1);
  356. }
  357.  
  358. /* ******************************************************************** */
  359. /* *********************** Exec Compute Process *********************** */
  360. /* ******************************************************************** */
  361.  
  362. static char *zargv[50], zbuf[10000];
  363.  
  364. #define STDIN  0
  365. #define STDOUT 1
  366. #define STDERR 2
  367.  
  368. static int do_command(client) Client *client;
  369. {
  370.   int command_pid, two_pipe, fd_out, fd_err, pipe_stdout[2], pipe_stderr[2];
  371.   Process *process;
  372.  
  373.   if (!(process = client->current_process))
  374.   {
  375. printf("No current process!\n");
  376.     return FALSE;
  377.   }
  378.  
  379.   if (!process->command)
  380.   {
  381. printf("No command!\n");
  382.     return FALSE;
  383.   }
  384.  
  385.   two_pipe = process->two_pipe;
  386.  
  387.     /* !!!error check */
  388.   pipe(pipe_stdout); fd_out = pipe_stdout[0];
  389.   if (two_pipe) { pipe(pipe_stderr); fd_err = pipe_stderr[0]; }
  390.  
  391. #if 1
  392.   signal(SIGCHLD,sig_child);
  393. #else
  394. signal(SIGCHLD,SIG_IGN);
  395. #endif
  396.  
  397.   switch(command_pid = fork())
  398.   {
  399.     default:        /* I'm the parent */
  400.       process->pid = command_pid;
  401.  
  402.       process->fd_output[0] = fd_out;
  403.       add_fd(fd_out, client, process, PROCESS_SEND);    /* !!!error check */
  404.       close(pipe_stdout[1]);
  405.  
  406.       if (two_pipe)
  407.       {
  408.     process->fd_output[1] = fd_err;
  409.     add_fd(fd_err, client, process, PROCESS_SEND_ERR);  /* !!!error check */
  410.     close(pipe_stderr[1]);
  411.       }
  412.  
  413.       break;
  414.     case  0:        /* I'm the child */
  415.       if (process->dir && chdir(process->dir))
  416.       {
  417.     printf("chdir didn't\n");
  418.         exit(1);
  419.       }
  420.  
  421.       dup2(pipe_stdout[1], STDOUT); close(pipe_stdout[0]);
  422.  
  423.       if (two_pipe)
  424.     {  dup2(pipe_stderr[1], STDERR); close(pipe_stderr[0]); }
  425.       else dup2(pipe_stdout[1], STDERR);    /* send stderr to stdout */
  426.  
  427.       exec_ize(process);
  428.  
  429.       if (-1 == execvp(zargv[0], zargv))
  430.       {
  431.     perror("Child exec error: ");
  432.     exit(1);
  433.       }
  434.  
  435.       /* Never gets here */
  436.  
  437.     case -1:        /* error */
  438.       perror("Trying to fork: ");
  439.       /* !!!?????????? */
  440.       return FALSE;
  441.   }
  442.   /* NOTREACHED */
  443. }
  444.  
  445.  
  446. #define BUF_SIZE 200
  447.  
  448.         /* suck up childs output and ship it to client */
  449. transfer_data(client, process, fd, op, flag)
  450.   Client *client;
  451.   Process *process;
  452.   int fd, op;
  453. {
  454.   char buf[BUF_SIZE+1];
  455.   int n;
  456.  
  457.   n = read(fd, buf, BUF_SIZE);
  458.   if (-1 == n)  { perror("transfer_data read: "); }
  459.   else
  460.     if (0 == n) { process->go_mask |= flag; }        /* EoF */
  461.     else                        /* real data */
  462.     {
  463.       buf[n] = '\0';
  464.  
  465.       CSbuild_packet(&client->packet, op, "ns", process->id, buf);
  466.       flush_client(client);
  467.     }
  468.  
  469.   if (process->go_mask == 0x3) process_done(client, process);
  470. }
  471.  
  472. #include <ctype.h>
  473.  
  474.     /* Convert command in to some thing I can exec().
  475.      *   Expand file names.
  476.      *   "foo" -> foo
  477.      *   If see a " >*> ", the rest of the line is one arg.
  478.      *     Only after the first arg.
  479.      */
  480. exec_ize(process) Process *process;
  481. {
  482.   char *ptr, *qtr;
  483.   int n;
  484.  
  485.   ptr = process->command;
  486.  
  487.   get_dpart(&ptr,zbuf); zargv[0] = zbuf;
  488.  
  489.   qtr = zbuf; qtr += strlen(qtr); *qtr++ = '\0';
  490.  
  491.   n = 1;
  492.   while (get_dpart(&ptr,qtr))
  493.   {
  494.     if (0 == strcmp("<*>", qtr))
  495.     {
  496.       zargv[n++] = ptr;        /* the rest of the line */
  497.       break;
  498.     }
  499.  
  500.     zargv[n] = qtr;
  501.     qtr += strlen(qtr); *qtr++ = '\0';
  502.  
  503.     n++;
  504.   }
  505.   zargv[n] = NULL;
  506.  
  507. #if 0
  508.   for (n = 0; zargv[n]; n++) printf("argv[%d]: \"%s\"\n", n, zargv[n]);
  509. #endif
  510. }
  511.  
  512. static int get_dpart(start,word) char **start, *word;
  513. {
  514.   register char *ptr = *start;
  515.   int quote = FALSE;
  516.  
  517.   if (*ptr == '\0') return FALSE;
  518.   while (TRUE)
  519.   {
  520.     switch (*word++ = *ptr++)
  521.     {
  522.       case '"':
  523.         if (quote)
  524.     {
  525.       word--;
  526.       goto done;
  527.     }
  528.     word--;
  529.     quote = TRUE;
  530.     break;
  531.       case ' ':    /* !!! really want isspace() */
  532.     if (quote) break;
  533.     while (isspace(*ptr)) ptr++;
  534.     word--;
  535.     goto done;
  536.       case '\0':
  537. /* if in quote: boo-boo */
  538.     ptr--;        /* back up to '\0' */
  539.     goto done;
  540.     }
  541.   }
  542.  done:
  543.   *start = ptr;
  544.   *word = '\0';
  545.   return TRUE;
  546. }
  547.  
  548. /* ******************************************************************** */
  549. /* *************************** Client Stuff *************************** */
  550. /* ******************************************************************** */
  551.  
  552. static Client *first_client = NULL;
  553.  
  554. Client *create_client(socket) int socket;
  555. {
  556.   Client *client;
  557.  
  558.   if (!(client = (Client *)malloc(sizeof(Client)))) return NULL;
  559.  
  560.   client->id_seed = 1;
  561.   client->pid = client->sig = 0;
  562.   client->blocked = FALSE;
  563.   client->packet.size = 0;    /* !!! need an init_packet(); */
  564.   client->socket = socket;
  565.   client->processes = client->current_process = NULL;
  566.  
  567.   client->next = first_client;
  568.   first_client = client;
  569.  
  570.   return client;
  571. }
  572.  
  573. static void add_process_to_client(client, process)
  574.   Client *client; Process *process;
  575. {
  576.   client->current_process = process;
  577.  
  578.   process->next = client->processes;
  579.   client->processes = process;
  580. }
  581.  
  582. static void remove_process_from_client(client, process)
  583.   Client *client; Process *process;
  584. {
  585.   Process *ptr, *drag;
  586.  
  587.   ptr = client->processes;
  588.   if (ptr == process)
  589.   {
  590.     client->processes = ptr->next;
  591.   }
  592.   else
  593.   {
  594.     for (; ptr; ptr = ptr->next)
  595.     {
  596.       if (ptr == process) break;
  597.       drag = ptr;
  598.     }
  599.     drag->next = process->next;
  600.   }
  601.  
  602.   if (client->current_process == process) client->current_process = NULL;
  603. }
  604.  
  605.     /* Allocate an id that a process can use.
  606.      * Returns:
  607.      *   0 : No ids available
  608.      *   n : Your new process id.
  609.      */
  610. static int alloc_pid(client) Client *client;
  611. {
  612.   return client->id_seed++;
  613. }
  614.  
  615. static void close_client(client, error_code) Client *client;
  616. {
  617.   Process *process, *ptr;
  618.  
  619. /*  if (!client) return;*/
  620.  
  621. /* !!! don't write if client croaked */
  622.   if (error_code != -1)
  623.   {
  624.     CSbuild_packet(&client->packet, CS_ERROR, "nn", 0, error_code);
  625.     flush_client(client);
  626.   }
  627.  
  628.   remove_fd(client->socket);
  629.  
  630.   for (process = client->processes; process; process = ptr)
  631.   {
  632.     ptr = process->next;        /* free() nukes next ptr */
  633.     close_process(process);
  634.   }
  635.  
  636.   if (first_client == client) first_client = client->next;
  637.   else
  638.   {
  639.     Client *ptr, *qtr;
  640.  
  641.     for (ptr = qtr = first_client; ptr; ptr = ptr->next)
  642.     {
  643.       if (ptr == client) break;
  644.       qtr = ptr;
  645.     }
  646.     qtr->next = ptr->next;
  647.   }
  648.  
  649.   free((char *)client);
  650. }
  651.  
  652. static void close_all_clients()
  653. {
  654.   Client *client;
  655.  
  656.   while (client = first_client) close_client(client,CS_ERROR_SERVER_DIED);
  657. }
  658.  
  659. static void client_blocked(client, blocked) Client *client;
  660. {
  661.   if (client->blocked == blocked) return;
  662.   client->blocked = blocked;
  663.   make_select_mask();
  664. }
  665.  
  666.     /* Notes:
  667.      *   Gotta be a little careful when closing a client because
  668.      *     close_client() calls flush_client().
  669.      */
  670. static void flush_client(client) Client *client;
  671. {
  672.   CSPacket *pak = &client->packet;
  673.   int pid;
  674.  
  675.   if (0 == pak->size) return;    /* got nothing something to write */
  676.  
  677.   switch(CSwrite_packet(pak, client->socket))
  678.   {
  679.     case -1:        /* error : nuke client */
  680.       close_client(client, -1);
  681.       return;
  682.     case  0: client_blocked(client, TRUE);  break;
  683.     case  1: client_blocked(client, FALSE); break;
  684.     case  2: return;        /* didn't do nothing */
  685.   }
  686.  
  687.     /* !!! only do this if write something? */
  688.   pid = client->pid;
  689.   if (pid && (-1 == kill(pid,client->sig)))
  690.     { perror("flush_client: Signal client"); /* !!!????????? */}
  691. }
  692.  
  693. static void flush_all_clients()
  694. {
  695.   Client *client;
  696.  
  697.   for (client = first_client; client; client = client->next)
  698.     flush_client(client);
  699. }
  700.  
  701.  
  702.     /* Try and send a message to all clients.
  703.      * WARNINGS
  704.      *   This is mostly a crock.  If a client is blocked, that means I can't
  705.      *     use its packet so I can't send it a message.  Not good if there
  706.      *     is a lot going on or a client is slow.  Need some buffering.
  707.      */
  708. static void send_client_msg(tag, msg) int tag; char *msg;
  709. {
  710.   Client *client;
  711.  
  712.   flush_all_clients();        /* try and make sure packets empty */
  713.  
  714.   for (client = first_client; client; client = client->next)
  715.     if (!client->blocked)
  716.       CSbuild_packet(&client->packet, CS_CLIENT_MSG, "ns", tag, msg);
  717.  
  718.   flush_all_clients();        /* send the packets */
  719. }
  720.  
  721. /* ******************************************************************** */
  722. /* *************************** Socket Code **************************** */
  723. /* ******************************************************************** */
  724.  
  725. extern char *savestr();
  726.  
  727. static int request_socket;
  728.  
  729. #include <sys/socket.h>
  730. #include <sys/un.h>
  731. #include <sys/stat.h>
  732.  
  733. static int open_request_socket(socket_name) char *socket_name;
  734. {
  735.   int len;
  736.   struct sockaddr_un unsock;
  737.  
  738.   if ((request_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  739.   {
  740.     perror("Creating Unix socket");
  741.     return FALSE;
  742.   }
  743.  
  744. /*  bzero((char *) &unsock, sizeof (unsock));  /*  */
  745.  
  746.   unsock.sun_family = AF_UNIX;
  747.  
  748.   strcpy(unsock.sun_path, socket_name);
  749. #ifdef SUN_LEN    /* BSD44SOCKETS, SUN_LEN defined in sys/un.h on AIX */
  750.   unsock.sun_len = strlen(unsock.sun_path);
  751.   len = SUN_LEN(&unsock);
  752. #else
  753. #ifdef SCM_RIGHTS    /* 4.3bsd reno and later (e.g. 386bsd) */
  754.     /* The following is taken from Stevens, _Advanced Programming in the
  755.      * UNIX Environment_.  -Thomas Gellekum
  756.      */
  757.   len = sizeof(unsock.sun_len) + sizeof(unsock.sun_family) +
  758.         strlen(unsock.sun_path) + 1;
  759.   unsock.sun_len = len;
  760. #else
  761.   len = strlen(unsock.sun_path) + 2;
  762. #endif /* SCM_RIGHTS */
  763. #endif /* SUN_LEN */
  764.  
  765. /*len = strlen(unsock.sun_path) + sizeof(sun_family);    /* ???vanilla 4.3bsd */
  766.  
  767.   unlink (unsock.sun_path);
  768.  
  769.   if (bind(request_socket, (struct sockaddr *)&unsock, len))
  770.   {
  771.     perror("Binding Unix socket");
  772.     close(request_socket);
  773.     return FALSE;
  774.   }
  775.  
  776.   if (listen(request_socket, 20))
  777.   {
  778.     perror("Unix Listening");
  779.     close(request_socket);
  780.     return FALSE;
  781.   }
  782.  
  783.   add_fd(request_socket, (Client *)NULL, (Process *)NULL, CONNECT);
  784.  
  785.   return TRUE;
  786. }
  787.  
  788.  
  789. typedef struct sockaddr_un SocketType;
  790.  
  791.     /* 
  792.      * Notes:
  793.      *   I need to the write socket to nonblocking so my round robin scheme
  794.      *     will work.  I prefer O_NONBLOCK but O_NDELAY seems to work.
  795.      */
  796. static int connect_to_client()
  797. {
  798.   Client *client;
  799.   int fd, addrlen;
  800.   SocketType new;        /* info on new socket */
  801.  
  802.   addrlen = sizeof(SocketType);
  803.  
  804.   if ((fd = accept(request_socket, (void *)&new, &addrlen)) == -1)
  805.   {
  806.     perror("connect_to_client: accept: ");
  807.     return FALSE;
  808.   }
  809.  
  810. #ifdef O_NONBLOCK
  811.   fcntl(fd, F_SETFL, O_NONBLOCK);
  812. #else
  813.   fcntl(fd, F_SETFL, O_NDELAY);
  814. #endif
  815.  
  816.   if (!(client = create_client(fd))) { close(fd); return FALSE; }
  817.  
  818.   if (!add_fd(fd, client, (Process *)NULL, CLIENT_SEND))
  819.   {
  820.     close_client(client, -1);
  821.     return FALSE;
  822.   }
  823.  
  824.   return TRUE;
  825. }
  826.  
  827. static int another_server_running(socket_name) char *socket_name;
  828. {
  829.   int fd;
  830.  
  831.   if (-1 == (fd = CSopen_client_socket(socket_name, 10))) return FALSE;
  832.   close(fd);        /* hope that other server knows how to handle this */
  833.   return TRUE;
  834. }
  835.  
  836. /* ******************************************************************** */
  837. /* **************************** Processes ***************************** */
  838. /* ******************************************************************** */
  839.  
  840. static void create_process(client, use_stdout_and_stderr) Client *client;
  841. {
  842.   Process *process;
  843.   int id;
  844.  
  845.   if (!(process = (Process *)malloc(sizeof(Process)))    ||
  846.       !(id = alloc_pid(client)))
  847.   {
  848.     CSbuild_packet(&client->packet, CS_PROCESS_ID, "n", -1);
  849.     flush_client(client);
  850. /* !!!??? no signal */
  851.     return;
  852.   }
  853.  
  854.   process->id = id;
  855.   process->self_destruct = TRUE;
  856.  
  857.   process->dir = NULL;
  858.   process->command = NULL;
  859.  
  860.   process->pid = 0;
  861.  
  862.   process->fd_output[0] = -1;
  863.   process->fd_output[1] = -1;
  864.  
  865.   process->two_pipe =  use_stdout_and_stderr;
  866.   process->go_mask  = (use_stdout_and_stderr ? 0 : 2);
  867.  
  868.   add_process_to_client(client, process);
  869.  
  870.   CSbuild_packet(&client->packet, CS_PROCESS_ID, "n", process->id);
  871.   flush_client(client);
  872.  
  873. /* !!!??? no signal */
  874. }
  875.  
  876. static void close_process(process) Process *process;
  877. {
  878.   int n;
  879.  
  880. /* !!!??? gotta wait for the sigchild??? */
  881. /* could put these on a kill list, send int and wait for sigchilds */
  882.   if (process->pid)
  883.       n = kill(process->pid, SIGINT);
  884.  
  885.   if (process->dir)     free(process->dir);
  886.   if (process->command) free(process->command);
  887.  
  888.   remove_fd(process->fd_output[0]);
  889.   remove_fd(process->fd_output[1]);
  890.  
  891.   free((char *)process);
  892. }
  893.  
  894. static void process_done(client, process) Client *client; Process *process;
  895. {
  896.   int exit_status;
  897.  
  898. printf("Process done\n"); fflush(stdout);
  899.  
  900.   exit_status = 0;    /* !!!??? */
  901.  
  902.   CSbuild_packet(&client->packet, CS_PROCESS_DONE,
  903.     "nn", process->id, exit_status);
  904.   flush_client(client);
  905.  
  906.   process->pid = 0;
  907.  
  908.   remove_fd(process->fd_output[0]); process->fd_output[0] = -1;
  909.   remove_fd(process->fd_output[1]); process->fd_output[1] = -1;
  910.  
  911.   if (process->self_destruct)
  912.   {
  913.     remove_process_from_client(client, process);
  914.     close_process(process);
  915.   }
  916. }
  917.  
  918. /* ******************************************************************** */
  919. /* ***************************** Packets ****************************** */
  920. /* ******************************************************************** */
  921.  
  922. static int get_packet(client) Client *client;
  923. {
  924.   char type;
  925.   CSPacket packet;
  926.   int fd;
  927.   Process *process;
  928.   xPacket event;
  929.  
  930.   fd = client->socket;
  931.   process = client->current_process;
  932.  
  933.   if (!CSread_packet(&packet, fd, &event))    /* error */
  934.   {
  935. printf("Bad data: Client closed\n");
  936.     close_client(client, -1);
  937.     return FALSE;
  938.   }
  939.  
  940.   type = event.type;
  941. printf("type = %d\n",type); fflush(stdout);
  942.  
  943.   switch(type)
  944.   {
  945.     default:            /* invalid type */
  946. close_client(client, CS_ERROR_PROTOCOL);
  947. return FALSE;
  948.     case CS_CREATE_PROCESS:
  949. printf("create-process: %d\n",event.u.Process.two_pipe); fflush(stdout);
  950.       create_process(client, event.u.Process.two_pipe);
  951.       break;
  952.     case CS_DISCONNECT:
  953.       close_client(client, -1);
  954.       return FALSE;
  955.     case CS_DIR:
  956.       if (process)
  957.       {
  958.     process->dir = savestr(event.u.Directory.dir);
  959. printf("DIRECTORY: %s\n",process->dir); fflush(stdout);
  960.       }
  961.       break;
  962.     case CS_DO_IT:
  963. printf("DO IT\n"); fflush(stdout);
  964.       do_command(client);
  965.       break;
  966.     case CS_COMMAND:    /* command */
  967.       if (process)
  968.       {
  969.     if (process->command) free(process->command);
  970.     process->command = savestr(event.u.Command.command);    /* !!! error check? */
  971. printf("COMMAND: %s\n",process->command); fflush(stdout);
  972.       }
  973.       break;
  974.     case CS_SIGNAL:    /* pid signal# */
  975.       client->pid = event.u.Signal.pid;
  976.       client->sig = event.u.Signal.sig;
  977. printf("Client pid = %d %d\n",client->pid, client->sig);
  978. fflush(stdout);
  979.  
  980.       break;
  981.     case CS_CLIENT_MSG:
  982. printf("client message: %d, %s\n",
  983.   event.u.ClientMsg.tag, event.u.ClientMsg.msg);
  984. fflush(stdout);
  985.       send_client_msg(event.u.ClientMsg.tag, event.u.ClientMsg.msg);
  986.       break;
  987.   }
  988.   return TRUE;
  989. }
  990.