/*
** ServerConfigd for OS/2 and Unix/Linux systems, v1.3
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>

#define MAXDATASIZE 1024
#define BACKLOG 2

int sockfd, new_fd;
int sin_size, numbytes, buf_size=0;
char buf[MAXDATASIZE], buf1[MAXDATASIZE];

void Send(void) {
 if (send(new_fd, buf, buf_size, 0) == -1)
  perror("send");
}

void Receive(void) {
 if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
  perror("recv");
 }
 if (numbytes > 0) buf[numbytes] = '\0';
}

int main(int argc, char *argv[])
{
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
char PAZZ[80], APACHECONFIG[80], PIDCONFIG[80];
int ALLOWRESET=0, ALLOWSHUTDOWN=0, MYPORT=0, Recv_size=0, Pazz_ok=0;
char Config_buffer[1024], Config_Label[80], Config_Setting[80];
FILE *ConfigFile, *ApacheFile, *PidFile, *Config_read;

#ifdef __EMX__
 strcpy(Config_buffer,"ServerConfigd.cfg");
#else
 strcpy(Config_buffer,"/etc/ServerConfigd.cfg");
#endif

if(argc > 1) {
 strcpy(Config_buffer, *++argv);
}

    if((ConfigFile = fopen(Config_buffer, "r")) == NULL) {
     printf("Error opening configuration file.\n");
     exit(1);
    }
    else
     while(!feof(ConfigFile)) {
      fgets(Config_buffer, sizeof(Config_buffer), ConfigFile);
      if(Config_buffer[0]!='#' && Config_buffer[0]!='\n') {
       sscanf(Config_buffer, "%s %s", Config_Label, Config_Setting);
       if(!strcmp(Config_Label,"Port")) {
        MYPORT=atoi(Config_Setting);
       }
       if(!strcmp(Config_Label,"Password")) {
        strcpy(PAZZ,Config_Setting);
       }
       if(!strcmp(Config_Label,"ApacheConfig")) {
        strcpy(APACHECONFIG,Config_Setting);
       }
       if(!strcmp(Config_Label,"PidFile")) {
        strcpy(PIDCONFIG,Config_Setting);
       }
       if(!strcmp(Config_Label,"AllowReset")) {
        ALLOWRESET=1;
       }
       if(!strcmp(Config_Label,"AllowShutDown")) {
        ALLOWSHUTDOWN=1;
       }
      }
     }
    fclose(ConfigFile);

    if(MYPORT==0) { printf("Error, no port found.\n"); exit(1); }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     perror("socket");
     exit(1);
    }

    my_addr.sin_family = AF_INET;         /* host byte order */
    my_addr.sin_port = htons(MYPORT);     /* short, network byte order */
    my_addr.sin_addr.s_addr = INADDR_ANY; /* automatically fill with my IP */
    bzero(&(my_addr.sin_zero), 8);        /* zero the rest of the struct */

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
     perror("bind");
     exit(1);
    }

    if (listen(sockfd, BACKLOG) == -1) {
     perror("listen");
     exit(1);
    }

    while(1) {
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
         perror("accept");
         continue;
        }
        //printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));

        Receive();
        if(strcmp(buf,"[RemoteSC] Hello")==0) {
         strcpy(buf,"[RemoteD] Welcome");
         buf_size=strlen(buf);
         Send();
         Receive();

         strcpy(buf1,"[RemoteSC] LOAD ");
         if(strcmp(buf,strcat(buf1, PAZZ))==0) {
          Pazz_ok=1;
          if((Config_read = fopen(APACHECONFIG, "rb")) == NULL) {
           strcpy(buf, "[RemoteD] BAD");
           buf_size=strlen(buf);
           Send();
          } else {
           fseek(Config_read,0l,SEEK_END);
           sprintf(buf, "%d", ftell(Config_read));
           buf_size=strlen(buf);
           fclose(Config_read);
           Send();
          }
          if((ApacheFile = fopen(APACHECONFIG, "rb")) == NULL) { }
           //printf("Error opening configuration file.\n");
          else {
           while(!feof(ApacheFile)) {
            buf_size=fread(Config_buffer, 1, 1024, ApacheFile);
            strcpy(buf, Config_buffer);
            /*buf_size=strlen(buf);*/
            Send();
           }
          }
         }

         strcpy(buf1,"[RemoteSC] SAVE ");
         if(strcmp(buf,strcat(buf1, PAZZ))==0) {
          Pazz_ok=1;
          if((ApacheFile=fopen(APACHECONFIG, "wb")) == NULL) {
           strcpy(buf, "[RemoteD] BAD");
           buf_size=strlen(buf);
           Send();
          } else {
           strcpy(buf, "[RemoteD] OK");
           buf_size=strlen(buf);
           Send();
           Receive();
           Recv_size=atoi(buf);
           strcpy(buf, "[RemoteD] OK");
           buf_size=strlen(buf);
           Send();
           buf_size=0;
           while (buf_size < Recv_size) {
            Receive();
            fwrite(buf, strlen(buf), 1, ApacheFile);
            buf_size = buf_size + strlen(buf);
           }
           fclose(ApacheFile);
           strcpy(buf, "[RemoteD] OK");
           buf_size=strlen(buf);
           Send();
          }
         }

         strcpy(buf1,"[RemoteSC] RESET ");
         if(strcmp(buf,strcat(buf1, PAZZ)) == 0) {
          Pazz_ok=1;
          if((PidFile=fopen(PIDCONFIG, "rb")) == NULL || ALLOWRESET==0) {
           strcpy(buf, "[RemoteD] BAD");
           buf_size=strlen(buf);
           Send();
          } else {
           fread(Config_buffer, 1, 1024, PidFile);
           fclose(PidFile);
           buf_size=atoi(Config_buffer);
           if((kill(buf_size,1)) == 0) {
            strcpy(buf, "[RemoteD] OK");
            buf_size=strlen(buf);
            Send();
           } else {
            strcpy(buf, "[RemoteD] BAD");
            buf_size=strlen(buf);
            Send();
           }
          }
         }

         strcpy(buf1,"[RemoteSC] SHUTDOWN ");
         if(strcmp(buf,strcat(buf1, PAZZ)) == 0) {
          Pazz_ok=1;
          if((PidFile = fopen(PIDCONFIG, "rb")) == NULL || ALLOWSHUTDOWN==0) {
           strcpy(buf, "[RemoteD] BAD");
           buf_size=strlen(buf);
           Send();
          } else {
           fread(Config_buffer, 1, 1024, PidFile);
           fclose(PidFile);
           buf_size=atoi(Config_buffer);
           kill(buf_size,15);
           strcpy(buf, "[RemoteD] OK");
           buf_size=strlen(buf);
           Send();
          }
         }

         if(Pazz_ok==0) {
           strcpy(buf, "[RemoteD] BAD");
           buf_size=strlen(buf);
           Send();
         }

        }
        while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up all child processes */
    }
    close(new_fd);
}

