home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------*/
- /*----Communications controller between tuple server and client */
- /*----processes. Execed by the server, and uses rexec to start */
- /*----clients. */
- /*---- */
- /*----Written by James Pinakis 7/12/89 */
- /*----Upgraded by Geoff Sutcliffe 11/4/90 */
- /*----Completely re-written by Geoff Sutcliffe 24/8/90 */
- /*-------------------------------------------------------------------*/
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/timeb.h>
- #include <netdb.h>
-
- #define BUFFER_SIZE 4096
- #define MAX_CLIENT_MACHINES 30
- #define MAX_STRING_LENGTH 15
- #define ERROR -1
- #define SOCKET_EOF -2
- #define OK 1
- #define COMPLETE 0
- #define NULL_DESCRIPTOR -1
-
- /*----Enuerated type for each of the types of messages that may */
- /*----appear */
- typedef enum
- {
- machines,
- start,
- stop,
- forward,
- exit_communicator,
- eof,
- blank_line,
- error
- } request_type;
-
- typedef enum
- {
- read_ok,
- read_eof,
- read_blank_line,
- read_error
- } read_result;
-
- typedef char string_type[MAX_STRING_LENGTH];
-
- typedef char buffer_type[BUFFER_SIZE];
-
- /*----Structure for holding logical and actual machine name, and the */
- /*----descriptor for writing and read to/from them */
- typedef struct
- {
- string_type client_machine_name;
- string_type machine_name;
- int descriptor;
- } machine_table_entry_type;
-
- typedef machine_table_entry_type machine_table_type[
- MAX_CLIENT_MACHINES];
- /*-------------------------------------------------------------------*/
- /*----Get the arguments to the communicator. There should be two */
- /*----integers - the descriptor for writing to and that for reading */
- /*----from. */
- void get_argument_values(number_of_arguments,arguments,
- write_descriptor,read_descriptor)
- int number_of_arguments,*write_descriptor,*read_descriptor;
- char *arguments[];
- {
- int i1;
-
- if (number_of_arguments != 5)
- {
- (void) fprintf(stderr,"%s: incorrect no. of arguments\n",
- arguments[0]);
- for (i1=0;i1<number_of_arguments;i1++)
- (void) fprintf(stderr,"Argument %d is %s\n",i1,arguments[i1]);
- exit(1);
- }
- *write_descriptor = atoi(arguments[1]);
- *read_descriptor = atoi(arguments[2]);
- #ifdef DEBUG
- (void) fprintf(stderr,"Write_descriptor is %d, Read_descriptor is %d\n",
- *write_descriptor,*read_descriptor);
- #endif
- }
- /*-------------------------------------------------------------------*/
- /*----Initialise the use of sockets, using tcp protocol */
- void initialise_sockets(server_pointer,port_number,read_template)
- struct servent **server_pointer;
- int *port_number;
- fd_set *read_template;
- {
- *server_pointer = getservbyname("exec","tcp");
- if (*server_pointer == NULL)
- {
- perror("exec - unknown service");
- exit(1);
- }
- *port_number = (*server_pointer)->s_port;
- FD_ZERO(read_template);
- }
- /*-------------------------------------------------------------------*/
- /*----Put a logical and absolute machine name into the machine table.*/
- /*----A null descriptor is assigned to the machine. */
- void load_machine_table(machine_table,entry_number,client_machine_name)
- machine_table_type machine_table;
- int entry_number;
- char *client_machine_name;
- {
- char *cp1;
-
- #ifdef DEBUG
- (void) fprintf(stderr,"Loading machine %s at position %d\n",
- client_machine_name,entry_number);
- #endif
- (void) strcpy(machine_table[entry_number].client_machine_name,
- client_machine_name);
- cp1 = strchr(client_machine_name,'(');
- *cp1 = '\0';
- #ifdef DEBUG
- (void) fprintf(stderr,"Absolute machine name is %s\n",
- client_machine_name);
- #endif
- (void) strcpy(machine_table[entry_number].machine_name,
- client_machine_name);
- machine_table[entry_number].descriptor = NULL_DESCRIPTOR;
- }
- /*-------------------------------------------------------------------*/
- /*----Find the index of a given logical machine name in the machine */
- /*----table. */
- int entry_lookup(machine_table,client_machine_name)
- machine_table_type machine_table;
- char *client_machine_name;
- {
- int entry_number;
-
- for (entry_number = 0;entry_number<MAX_CLIENT_MACHINES;entry_number++)
- if (!strcmp(client_machine_name,machine_table[entry_number].
- client_machine_name))
- return(entry_number);
- (void) fprintf(stderr,"Machine table does not hold %s\n",
- client_machine_name);
- return(ERROR);
- }
- /*-------------------------------------------------------------------*/
- /*----Remove unwanted spaces from the buffer */
- void tidy_buffer(buffer)
- char *buffer;
- {
- char *new_buffer;
-
- new_buffer = buffer;
- while (*buffer != '\0')
- {
- if (*buffer != ' ')
- *new_buffer++ = *buffer;
- buffer++;
- }
- *new_buffer = '\0';
- }
- /*-------------------------------------------------------------------*/
- /*----Read an \n terminated string from a descriptor, into a buffer. */
- read_result read_string(buffer,maximum_size,descriptor)
- char *buffer;
- int maximum_size,descriptor;
- {
- int this_read,number_read;
-
- #ifdef DEBUG2
- fprintf(stderr,"Input on %d\n",descriptor);
- #endif
- number_read = 0;
- while (((this_read = read(descriptor,buffer,1)) > 0) &&
- (number_read < maximum_size) && (*buffer != '\n'))
- {
- #ifdef DEBUG2
- (void) fprintf(stderr,".%c",*buffer);
- #endif
- number_read++;
- buffer++;
- }
- if (this_read == 0)
- return(read_eof);
- if (this_read < 0)
- return(read_error);
- if (number_read > maximum_size)
- {
- #ifdef DEBUG
- (void) fprintf(stderr,"Input too long in read_string\n");
- #endif
- return(read_error);
- }
- if (number_read == 0)
- return(read_blank_line);
- /*----Replace \n by \0 */
- #ifdef DEBUG
- (void) fprintf(stderr,"Length %d\n",number_read);
- #endif
- *buffer = '\0';
- return(read_ok);
- }
- /*-------------------------------------------------------------------*/
- /*----Read input from a descriptor, work out what kind of message it */
- /*----is, and fix the arguments so that they are , separated so that */
- /*----they can be accessed with strtok. The buffer_pointer is set to */
- /*----point to the first argument. */
- request_type parse(descriptor,buffer_pointer)
- int descriptor;
- char **buffer_pointer;
- {
- request_type request;
- static buffer_type buffer;
- char *cp1;
-
- switch (read_string(buffer,BUFFER_SIZE,descriptor))
- {
- case read_error:
- return(error);
- break;
- case read_eof:
- return(eof);
- break;
- case read_blank_line:
- return(blank_line);
- break;
- case read_ok:
- tidy_buffer(buffer);
- #ifdef DEBUG
- (void) fprintf(stderr,"Request =%s=\n",buffer);
- #endif
- *buffer_pointer = buffer;
- /*----Now to get the arguments out by themselves. If there are any */
- /*----arguments, then make buffer pointer to them as a string */
- if ((cp1 = strrchr(buffer,')')) != NULL)
- {
- *cp1 = '\0';
- if ((cp1 = strchr(buffer,'(')) != NULL)
- {
- *buffer_pointer = cp1 + 1;
- *cp1 = '\0';
- }
- else return(error);
- }
- /*----Otherwise put a \0 on the . and buffer pointer is NULL */
- else if ((cp1 = strchr(buffer,'.')) != NULL)
- {
- *cp1 = '\0';
- *buffer_pointer = NULL;
- }
- else return(error);
- /*----Decide on the message type */
- if (strcmp(buffer,"machines") == 0)
- return(machines);
- else if (strcmp(buffer,"start") == 0)
- return(start);
- else if (strcmp(buffer,"stop") == 0)
- return(stop);
- else if (strcmp(buffer,"forward") == 0)
- return(forward);
- else if (strcmp(buffer,"exit") == 0)
- return(exit_communicator);
- else return(error);
- break;
- default:
- return(error);
- break;
- }
- }
- /*-------------------------------------------------------------------*/
- /*----Start up a client machine using rexec, and update the machine */
- /*----table with the descriptor returned. */
- void start_machine(machine_table,buffer,port_number,read_template)
- machine_table_type machine_table;
- char *buffer;
- int port_number;
- fd_set *read_template;
- {
- char *client_machine_name,*machine_name;
- int descriptor,entry_number;
-
- client_machine_name = strtok(buffer,",");
- if ((entry_number = entry_lookup(machine_table,client_machine_name)) !=
- ERROR)
- {
- machine_name = machine_table[entry_number].machine_name;
- #ifdef DEBUG
- (void) fprintf(stderr,"About to rexec %s\n",machine_name);
- #endif
- if ((descriptor = rexec(&machine_name,(u_short) port_number,
- "geoff","uktt,g","bin/prolog linda/linda",(int *) 0)) == ERROR)
- {
- perror("Cannot rexec");
- return;
- }
- else {
- machine_table[entry_number].descriptor = descriptor;
- FD_SET(descriptor,read_template);
- #ifdef DEBUG
- (void) fprintf(stderr,"%s uses descriptor %d\n",machine_name,
- descriptor);
- #endif
- }
- }
- }
- /*-------------------------------------------------------------------*/
- /*----Close the socket for a client machine that has terminated, and */
- /*----set the associated descriptor in the machine table to null. */
- void stop_machine(machine_table,buffer,read_template)
- machine_table_type machine_table;
- char *buffer;
- fd_set *read_template;
- {
- int entry_number;
- char *client_machine_name;
-
- client_machine_name = strtok(buffer,",");
- if ((entry_number = entry_lookup(machine_table,client_machine_name)) !=
- ERROR)
- {
- FD_CLR(machine_table[entry_number].descriptor,read_template);
- (void)close(machine_table[entry_number].descriptor);
- machine_table[entry_number].descriptor = NULL_DESCRIPTOR;
- }
- }
- /*-------------------------------------------------------------------*/
- void forward_message(machine_table,buffer)
- machine_table_type machine_table;
- char *buffer;
- {
- char *client_machine_name,*term;
- int entry_number;
-
- client_machine_name = buffer;
- term = strchr(buffer,',');
- *term++ = '\0';
- if ((entry_number = entry_lookup(machine_table,client_machine_name)) !=
- ERROR)
- {
- (void) strcat(term,".\n");
- #ifdef DEBUG
- (void) fprintf(stderr,"Sending =%s= to %s on %d, entry %d\n",term,
- client_machine_name,machine_table[entry_number].descriptor,entry_number);
- #endif
- if (write(machine_table[entry_number].descriptor,term,
- strlen(term)) != strlen(term))
- perror("Forwarding a term");
- }
- }
- /*-------------------------------------------------------------------*/
- int serve_request(machine_table,port_number,read_template)
- machine_table_type machine_table;
- int port_number;
- fd_set *read_template;
- {
- fd_set detect_template;
- int number_of_readable_sockets,entry_number,status;
- static int number_of_entries = 2; /*----0 and 1 are the server */
- char *buffer,*argument;
-
- detect_template = *read_template;
- number_of_readable_sockets = select(FD_SETSIZE,&detect_template,
- (fd_set *)0,(fd_set *)0,(struct timeval *)0);
- if (number_of_readable_sockets < 0)
- {
- perror("select");
- exit(1);
- }
- status = OK;
- /*----Search for input from entry number 1. 0 is write to server. */
- for (entry_number = 0;status == OK && entry_number < number_of_entries;
- entry_number++)
- if (machine_table[entry_number].descriptor != NULL_DESCRIPTOR &&
- FD_ISSET(machine_table[entry_number].descriptor,&detect_template))
- {
- #ifdef TIME
- {
- struct timeb time_data;
-
- ftime(&time_data);
- printf("=%d %d=\n",time_data.time, time_data.millitm);
- }
- #endif
- #ifdef DEBUG
- (void) fprintf(stderr,"Input on %d\n",machine_table[entry_number].
- descriptor);
- #endif
- switch (parse(machine_table[entry_number].descriptor,&buffer))
- {
- case machines:
- argument = strtok(buffer,",");
- while (argument != NULL)
- {
- load_machine_table(machine_table,number_of_entries++,
- argument);
- argument = strtok((char *)NULL,",");
- }
- break;
- case start:
- start_machine(machine_table,buffer,port_number,
- read_template);
- break;
- case stop:
- stop_machine(machine_table,buffer,read_template);
- break;
- case forward:
- forward_message(machine_table,buffer);
- break;
- case exit_communicator:
- status = COMPLETE;
- break;
- case eof:
- break;
- case blank_line:
- break;
- case error:
- (void) fprintf(stderr,"\nBad input : %s\n",buffer);
- status = ERROR;
- break;
- default:
- (void) fprintf(stderr,"Error in serve_request - \
- no descriptor found\n");
- status = ERROR;
- break;
- }
- }
- return(status);
- }
- /*-------------------------------------------------------------------*/
- int main(number_of_arguments,arguments)
- int number_of_arguments;
- char *arguments[];
- {
- int read_descriptor,write_descriptor,port_number;
- struct servent *server_pointer;
- fd_set read_template;
- machine_table_type machine_table;
-
- #ifdef DEBUG
- int descriptor;
- if ((descriptor = open("comm_debug",O_CREAT|O_TRUNC|O_WRONLY,0644)) < 0)
- perror("Cannot debug");
- else dup2(descriptor,2);
- (void) fprintf(stderr,"Communicator is going\n");
- #endif
-
- get_argument_values(number_of_arguments,arguments,&write_descriptor,
- &read_descriptor);
- initialise_sockets(&server_pointer,&port_number,&read_template);
- /*----Load write to server details in position 0 of the table */
- load_machine_table(machine_table,0,"server(1)");
- machine_table[0].descriptor = write_descriptor;
- /*----Load read from server details in position 1 */
- load_machine_table(machine_table,1,"server(0)");
- machine_table[1].descriptor = read_descriptor;
- FD_SET(read_descriptor,&read_template);
- while (serve_request(machine_table,port_number,&read_template) == OK)
- ;
- #ifdef DEBUG
- (void) fprintf(stderr,"Request service completed\n");
- #endif
- FD_CLR(read_descriptor,&read_template);
- #ifdef DEBUG
- (void) fprintf(stderr,"Read descriptor cleared\n");
- #endif
- machine_table[0].descriptor = NULL_DESCRIPTOR;
- machine_table[1].descriptor = NULL_DESCRIPTOR;
- return(0);
- }
- /*-------------------------------------------------------------------*/
-
-