home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / gopher / gopher1.01 / mindexd / mindexd.c < prev    next >
C/C++ Source or Header  |  1992-04-08  |  8KB  |  329 lines

  1. /* Derived from an 
  2.  * Example of server using TCP protocol
  3.  * pp 284-5 Stevens UNIX Network Programming
  4.  */
  5.  
  6. #include "mindexd.h"
  7.  
  8. char Zehostname[128];
  9.     
  10. struct one_slave {
  11.    int  port;
  12.    char *host[128];
  13.    int  sockfd;
  14. };
  15. struct one_slave slaves[MAXSLAVES];
  16.  
  17. int LastSlave;
  18.  
  19.  
  20. /*  read the config file and fill the slaves struct, returns
  21.     the number of slave servers */
  22. int
  23. getconfig( the_filename )
  24.   char *the_filename;
  25. {
  26.     char *cp;
  27.     int  n;
  28.     char *local;
  29.     int i;
  30.     FILE *fp;
  31.     char    line[256];      /* line buffer for reading config */
  32.     char    *linep;         /* pointer to 'line' */
  33.  
  34.  
  35.     local = the_filename;
  36.  
  37.     if ((fp = fopen(local, "r")) == NULL) {
  38.             exit(1);
  39.     }
  40.  
  41.     LastSlave = -1;
  42.     for (;;) {
  43.         if (fgets(line, sizeof line, fp) == NULL)
  44.                break;  /* done */
  45.  
  46.         if ((i = strlen(line)))
  47.                line[i-1] = 0;  /* remove trailing newline */
  48.         if (line[0] == '#' || line[0] == 0)
  49.                continue;       /* skip comment lines */
  50.         else {
  51.                LastSlave++;
  52.                linep = line;
  53.                /* the port number is seperated from the host name by a space */
  54.  
  55.                slaves[LastSlave].port = atoi( index(linep, ' ') );
  56.                cp = index(linep, ' ');
  57.                cp[0] = 0; /* trim off stuff after the hostname */
  58.                cp = slaves[LastSlave].host;
  59.                strcpy(cp, linep);
  60.         }
  61.     }
  62.     close(fp);
  63.  
  64.     return( LastSlave );
  65. }
  66.  
  67.  
  68.  
  69.  
  70. void
  71. main(argc, argv)
  72. int     argc;
  73. char     *argv[];
  74. {
  75.      int sockfd;
  76.      int newsockfd;
  77.      int clilen;
  78.      int childpid;
  79.      int i;
  80.      char *config_filename;
  81.  
  82.      struct sockaddr_in cli_addr;
  83.      struct sockaddr_in serv_addr;
  84.  
  85.      pname = argv[0];
  86.      
  87.      if (DEBUG == FALSE)
  88.       daemon_start(0);
  89.  
  90.      /** Open a TCP socket (an internet stream socket **/
  91.      
  92.      if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  93.       err_dump("server: can't open stream socket");
  94.      
  95.      /*
  96.       * Bind our local address so that the client can send to us
  97.       */
  98.      
  99.      bzero((char *) &serv_addr, sizeof(serv_addr));
  100.      serv_addr.sin_family         = AF_INET;
  101.      serv_addr.sin_addr.s_addr     = htonl(INADDR_ANY);
  102.      serv_addr.sin_port        = htons(GOPHER_INDEX_PORT);
  103.     
  104.  
  105.      if (argc < 1){
  106.              syntax(argv[0]);
  107.      }
  108.      for (i=1;i<argc-1;i++){
  109.              if (argv[i][0] == '-'){
  110.                      if (strncmp(argv[i],"-p",2) == 0){
  111.                              serv_addr.sin_port = htons( atoi(argv[++i]) );
  112.                      } else {
  113.                          if (strncmp(argv[i],"-c",2) == 0){
  114.                              config_filename = argv[++i];
  115.                          } else {
  116.                              fprintf(stderr,"Unknown option %s.\n",argv[i]);
  117.                              syntax(argv[0]);
  118.                          }
  119.                      }
  120.              }
  121.      }
  122.  
  123.  
  124.      if ((LastSlave = getconfig(config_filename)) == -1) 
  125.          err_dump("can't read config file" );
  126.  
  127.  
  128.      if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0)
  129.       err_dump("server: can't bind local address");
  130.      
  131.      listen(sockfd, 5);
  132.      
  133.      for ( ; ; ) {
  134.       /*
  135.        * Wait for a connection from a client process.
  136.        * This is an example of a concurrent server.
  137.        */
  138.       
  139.       clilen = sizeof(cli_addr);
  140.       newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,
  141.                  &clilen);
  142.       
  143.       if (newsockfd < 0)
  144.            err_dump("server: accept error");
  145.       
  146.       if ( (childpid = fork()) < 0)
  147.            err_dump("server: fork error");
  148.       
  149.       else if (childpid == 0) {    /* Child process */
  150.            close(sockfd);        /* close original socket */
  151.  
  152.            if (gethostname(Zehostname, 128) !=0 )
  153.             strcpy(Zehostname, "<<no-name>>");
  154.  
  155.  
  156.                /* process the request */
  157.            while(do_command(newsockfd)!=0);
  158.            exit(0);
  159.       }
  160.       /** clean up any zombie children **/
  161.       sig_child();
  162.  
  163.       close(newsockfd);         /* parent process */
  164.      }
  165. }
  166.  
  167. syntax(progname){
  168.     fprintf(stderr,"syntax: %s -p port -c config_file\n",progname);
  169.     exit(1);
  170. }
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177. /*
  178.  * Connect_To_Host Performs a connecting to socket 'service' on host
  179.  * 'host'.  Host can be a hostname or ip-address.  If 'host' is null, the
  180.  * local host is assumed.   The parameter full_hostname will, on return,
  181.  * contain the expanded hostname (if possible).  Note that full_hostname is a
  182.  * pointer to a char *, and is allocated by connect_to_gopher()
  183.  *
  184.  * Errors:
  185.  *
  186.  * -1 get service failed
  187.  *
  188.  * -2 get host failed
  189.  *
  190.  * -3 socket call failed
  191.  *
  192.  * -4 connect call failed
  193.  */
  194.  
  195. int connect_to_Host(port, host)
  196.   int port;
  197.   char *host;
  198. {
  199.      int s;
  200.      char buf[MAXSTR];
  201.      struct sockaddr_in server;
  202.  
  203.      struct hostent *hp;
  204.  
  205. /*
  206.      if (host == '\0') {
  207.       gethostname(buf, sizeof(buf));
  208.       host = buf;
  209.      }
  210. */
  211.  
  212.      if ((server.sin_addr.s_addr = inet_addr(host)) == -1) {
  213.       if ((hp = gethostbyname(host)) == NULL ) {
  214.                return(-2);
  215.       } else
  216.                bzero((char *) &server, sizeof(server));
  217.                bcopy(hp->h_addr, (char *) &server.sin_addr, hp->h_length);
  218.                server.sin_family = hp->h_addrtype;
  219.      } else
  220.       server.sin_family = AF_INET;
  221.  
  222.      server.sin_port = (unsigned short) htons(port);
  223.  
  224.      if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  225.       return (-3);
  226.  
  227.      setsockopt(s, SOL_SOCKET, ~SO_LINGER, 0, 0);
  228.      setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
  229.      setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
  230.      if (connect( s, &server, sizeof(server)) < 0) {
  231.       close(s);
  232.       return (-4);
  233.      }
  234.      return s;
  235. }
  236.  
  237.  
  238.  
  239. /* take the query the client passed us, and send it on to the slave index
  240.    servers, gather up their responses and return them to our client 
  241.  
  242.   still need to add code to handle the case where a slave dies on us
  243. */
  244. void
  245. HandleQuery(sockfd, queryline )
  246.   int  sockfd;
  247.   char *queryline;
  248. {
  249.      char answerline[512];
  250.      int  length_answer;
  251.      int  i;
  252.      int  childpid;
  253.  
  254.  
  255.      /* send queries to all the slaves and gather up responces*/
  256.      for (i = 0; i < ( LastSlave + 1); i++ ) {
  257.  
  258.         /* fork child processes to handle each of the slaves */
  259.         if ( (childpid = fork()) < 0)
  260.             err_dump("server: fork error");
  261.  
  262.         else if (childpid == 0) {     /* Child process */
  263.             slaves[i].sockfd = connect_to_Host( slaves[i].port, slaves[i].host);
  264.             writestring(slaves[i].sockfd, queryline );
  265.             writestring(slaves[i].sockfd, "\r\n");
  266.             if (sockfd > 0 )
  267.               for(;;) {
  268.                    length_answer = readline(slaves[i].sockfd, answerline, 512);
  269.                    if (length_answer > 0) {
  270.                         if (answerline[0] == '.') {
  271.                            exit(0);
  272.                         }
  273.                         else {
  274.                            writestring(sockfd, answerline);
  275.                         }
  276.                    }
  277.               }
  278.         }
  279.  
  280.      }
  281.  
  282.      /* make sure all the children are done */
  283.      while (wait((int * ) 0) != -1) 
  284.             ;
  285.  
  286.      /* all done now, tell the client we are finished */
  287.      writestring(sockfd, ".\r\n");
  288.  
  289. }
  290.  
  291.  
  292.  
  293.  
  294. int
  295. do_command(sockfd)
  296. int sockfd;
  297. {
  298.      char inputline[MAXLINE];
  299.      int length;        /* Length of the command line */
  300.      char out_line[MAXLINE];    /* for outgoing messages */
  301.      FILE *foofile;
  302.  
  303.      length = readline(sockfd, inputline, MAXLINE); /** Get the line **/
  304.  
  305.      ZapCRLF(inputline);
  306.  
  307.      if (length <= 0)
  308.       err_dump("getcommand: readline error");
  309.      
  310.      /** Get the command from the input line **/
  311.      
  312.      if (inputline[0] == '\0'){
  313.       /* Wants information about what we got... 
  314.              but we are an Index server, so complain */
  315.  
  316.           writestring(sockfd, "Leaping Lizards for the moons of Saturn!!!\r\n");
  317.           writestring(sockfd, "I am a middleman gopher index server...\r\n");
  318.           writestring(sockfd, "Don't send me blank lines!\r\n");
  319.       return(0);
  320.      }
  321.  
  322.      /* Okay, now we have the argument, let's process it. */
  323.      
  324.      HandleQuery(sockfd, inputline );
  325.      close(sockfd); 
  326.      return(0);
  327. }
  328.  
  329.