#include "main.h"


/*************************************************************************
  CHECK_USER
  *****************************************************************************/
/*
  checks to see if user is root so that they can edit /etc/services file
  returns -1 on failure
  */

int check_user()
{
       int uid,euid;
       
       
       
       if(geteuid() !=0) {
	      printf("USER IS NOT ROOT /etc/services unchanged\n");
	      printf("you must now edit the file by hand\n");
	      return(-1);
       }
       
       
       printf("USER IS ROOT proceeding\n");
       return(1);
       
}
/**************************************************************************
 *                     extract_current_ports
 ***************************************************************************/
/* greps /etc/services for the qmaster_service and dqs_execd_service
   and extracts the port nums that were assigned to the out.               */

void extract_current_ports()
{

       char *tmpstr;
       FILE *pfd;
       char buf[MAXLEN];
       char *ptr;


       MALLOC_STR(tmpstr);
       bzero(buf,MAXLEN);

       sprintf(tmpstr, "grep %s /etc/services",qmaster_service);
       PUT_NULL(tmpstr);
       
       if((pfd = popen(tmpstr,"r"))==NULL){
	      fprintf(stderr,"Can't open pipe\n");
	      return;
       }
       
       while(fgets(buf,MAXLEN,pfd)){
	      DPRINTF(("pipe_buf ==:%s:\n",buf));
	      ptr = strtok(buf," \t");
	      /*ptr now has qmaster service*/
	      if(strcmp(ptr,qmaster_service)!=0)
	        continue;

	      ptr = strtok((char*)NULL,"/");
	      DPRINTF(("Service num == :%s:\n",ptr));
	      qmaster_service_num = atoi(ptr);
	      DPRINTF(("Service num == :%d:\n",qmaster_service_num));
	      break;
       }

       fclose(pfd);

       sprintf(tmpstr, "grep %s /etc/services",dqs_execd_service);
       PUT_NULL(tmpstr);

       if((pfd = popen(tmpstr,"r"))==NULL){
              fprintf(stderr,"Can't open pipe\n");
              return;
       }

       while(fgets(buf,MAXLEN,pfd)){
              DPRINTF(("pipe_buf ==:%s:",buf));
              ptr = strtok(buf," \t");
              /*ptr now has dqs_execd*/
              if(strcmp(ptr,dqs_execd_service)!=0)
                continue;
              ptr = strtok((char*)NULL,"/");
              DPRINTF(("Service num == :%s:\n",ptr));
	      dqs_execd_service_num  = atoi(ptr);
              break;
       }
       fclose(pfd);
       free(tmpstr);
       return;
}

/**************************************************************************
  FIND_GOOD_PORTS 
  ***************************************************************************/
/*keeps checking /etc/services for three consecutive numbers to use as ports*/

void find_good_ports()
{
       int start_num=0;
       int good1=0,good2=0,good3=0;
       char *tstr;
       char * line;
       
       MALLOC_STR(tstr);
       MALLOC_STR(line);

       if(already_has_port_nums==1){
	      DPRINTF(("Already has port nums finding them\n"));
	      extract_current_ports();
	      return;
       }
       
       
       if(!(strcmp(reserved_port,"TRUE"))) 
       start_num=607;
       else
       start_num=2062;
       
       while(  (good1 ==0) &&  (good2 ==0)  && (good3==0)  ){ /* loop till we get 3 unused ports*/
	      printf("Trying to find unused port numbers.....\n");
	      DPRINTF(("############################################################################\n\n"));
	      DPRINTF((" find_good_ports: checking %d\n",start_num));
	      sprintf(line,"grep  %d /etc/services",start_num);
	      PUT_NULL(line);
	      DPRINTF(("checking for port %d  in /etc/services \n",start_num));
	      DPRINTF(("execing :%s: to check\n",line));
	      DPRINTF(("====================================\n"));
	      good1 = exec_it(line); /* returns 0 if match found*/
	      DPRINTF(("====================================\n"));
	      
	      DPRINTF(("good1 returns %d\n",good1));
	      
	      if(good1 !=0) { /* 1st entry not in services..now check for second*/
		     sprintf(line,"grep %d /etc/services ",(start_num+1));
		     PUT_NULL(line);
		     DPRINTF(("1st entry not in services..now check for second\n"));
		     DPRINTF(("execing :%s: to check\n",line));
		     DPRINTF(("====================================\n"));
		     good2 = exec_it(line);
		     DPRINTF(("====================================\n"));
		     DPRINTF(("good2 returns %d\n",good2));
		     
		     if (good2 ==0){
			    good1 =0;
			    good3 =0;
			    start_num++; /* this will cause it to jump 2 places*/
		     }                     
		     else{
			    sprintf(line,"grep %d /etc/services ",(start_num+1));
			    PUT_NULL(line);
			    DPRINTF(("2nd entry not in services..now check for third\n"));
			    DPRINTF(("execing :%s: to check\n",line));
			    DPRINTF(("====================================\n"));
			    good3 = exec_it(line);
			    DPRINTF(("====================================\n"));
			    DPRINTF(("good3 returns %d\n",good2));
			    if(good3==0){
				   good1 =0;
				   good3 =0;
				   start_num++; /* this will cause it to jump 2 places*/
			    }
		     }
	      }
	      
	      
	      start_num++;
       }
       start_num--;
       qmaster_service_num   = start_num;
       dqs_execd_service_num = start_num+1;
       intercell_service_num = start_num+2;
       
       DPRINTF(("qmaster_service_num   = %d\n",qmaster_service_num));
       DPRINTF(("dqs_execd_service_num = %d\n",dqs_execd_service_num));
       DPRINTF((" intercell_service_num = %d\n",intercell_service_num));
       free(line);  
       free(tstr);
       
       printf("############################################################################\n\n");
       printf(" Found ports %d and %d an %d \n",
                   qmaster_service_num, dqs_execd_service_num, intercell_service_num);
       
}

/*************************************************************************
  ADD_SERVICES
  *****************************************************************************/
/* pulls qmaster_service names out of globals array and  qmaster_service_num,
    dqs_execd_service name, dqs_execd_service_num, intercell_service name,
   and intercell_service_num  and  writes to 
   scriptfile called addservice.sh which when exec'd will append the services
   to /etc/services                                                     */


void add_services()
{
       FILE* fd;
       FILE* serv;
       char *qmstr;
       char *dqstr;
       char *icstr;
       
       int  result=0;
       char *ans;
       struct stat sbuf;
       char c;
       
       
       
       
       
       if(!(fd = fopen("addservice.sh","w"))) {
	      err_cont("Can't open addservice.sh for writing\n"); 
	      return;
       }
       
       MALLOC_STR(qmstr);
       MALLOC_STR(dqstr);
       MALLOC_STR(icstr);
       
       sprintf(qmstr,"%s     %d/tcp",qmaster_service,qmaster_service_num); 
       sprintf(dqstr,"%s     %d/tcp",dqs_execd_service,dqs_execd_service_num);    
       sprintf(icstr,"%s     %d/tcp",intercell_service,intercell_service_num);
       
       DPRINTF(("add_services:  qmstr entry ==:%s:\n",qmstr));
       DPRINTF(("add_services:  dqstr entry ==:%s:\n",dqstr));
       DPRINTF(("add_services:  icstr entry ==:%s:\n",icstr));
       
       fprintf(fd,"%s\n","#!/bin/sh");
       fprintf(fd,"ser1=%s\n", qmaster_service);
       fprintf(fd,"ser2=%s\n",dqs_execd_service);
       fprintf(fd,"ser3=%s\n",intercell_service);       
       fprintf(fd,"port1=%d\n",qmaster_service_num);
       fprintf(fd,"port2=%d\n\n\n",dqs_execd_service_num);
       fprintf(fd,"port3=%d\n\n\n",intercell_service_num);

       fprintf(fd,"echo \"___Test1_________\"\n");
       fprintf(fd," echo \" grep $ser1 /etc/services \"\n");
       fprintf(fd,"grep $ser1 /etc/services \n");
       fprintf(fd,"result1=$?\n\n");
       fprintf(fd,"if [ $result1 -eq 0 ]  \n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n");
       fprintf(fd,"echo \"___Test1 successful_________\"\n\n");

       fprintf(fd,"echo \"___Test2_________\"\n");
       fprintf(fd," echo \" grep $ser2 /etc/services \"\n");
       fprintf(fd,"grep $ser2 /etc/services \n");
       fprintf(fd,"result2=$?\n");
       fprintf(fd,"if [ $result2 -eq 0 ]  \n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n");
       fprintf(fd,"echo \"___Test2 successful_________\"\n");

       fprintf(fd,"echo \"___Test3_________\"\n");
       fprintf(fd," echo \" grep $ser3 /etc/services \"\n");
       fprintf(fd,"grep $ser3 /etc/services \n");
       fprintf(fd,"result3=$?\n");
       fprintf(fd,"if [ $result3 -eq 0 ]  \n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n");
       fprintf(fd,"echo \"___Test3 successful_________\"\n");

       fprintf(fd,"echo \"___Test4_________\"\n\n\n");
       fprintf(fd," echo \" grep $port1 /etc/services \"\n");
       fprintf(fd,"grep $port1 /etc/services  \n");
       fprintf(fd,"result4=$?\n");
       fprintf(fd,"if [ $result4 -eq 0 ]  \n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n");
       fprintf(fd,"echo \"___Test4 successful_________\"\n");

       fprintf(fd,"echo \"___Test5_________\"\n");
       fprintf(fd," echo \" grep $port2 /etc/services \"\n");
       fprintf(fd,"grep $port2 /etc/services\n");
       fprintf(fd,"result5=$?\n");
       fprintf(fd,"if [ $result5 -eq 0 ]\n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n\n");
       fprintf(fd,"echo \"___Test5 successful_________\"\n\n");
       
       fprintf(fd,"echo \"___Test6_________\"\n");
       fprintf(fd," echo \" grep $port3 /etc/services \"\n");
       fprintf(fd,"grep $port3 /etc/services\n");
       fprintf(fd,"result6=$?\n");
       fprintf(fd,"if [ $result6 -eq 0 ]\n");
       fprintf(fd,"then\n");
       fprintf(fd,"echo \"Can't add ports to /etc/services\"\n");
       fprintf(fd,"exit 1\n");
       fprintf(fd,"fi\n\n");
       fprintf(fd,"echo \"___Test6 successful_________\"\n\n");

       
       fprintf(fd,"echo \"---TESTING DONE....adding to /etc/services\"\n\n\n");
       
       fprintf(fd,"%s\n","cp /etc/services /etc/services.dqs.orig");
       fprintf(fd,"echo \"%s\" >>  /etc/services\n", qmstr);
       fprintf(fd,"echo \"%s\" >>  /etc/services\n", dqstr);
       fprintf(fd,"echo \"%s\" >>  /etc/services\n", icstr);
       
       fflush(fd);
       fclose(fd);
       
       chmod("addservice.sh",0755);
       
       printf("Created addservice.sh which will append ports to /etc/services. \n");
       printf("This should be run on all machines that will use DQS\n");

}

/******************************************************************
  exec_it
  *******************************************************************/
/*
  Will exec what is in global exec_matrix, returns exit status  */

int exec_it(cmd)
char * cmd;
{
       pid_t pid=0;
       int i,status=0;
       int npid;
       
       parse_to_exec_matrix(cmd);
       /*dump_exec_matrix();*/
       
       if(pid = fork()){ /*parent*/
	      errno =0 ;
	      if  (wait(&status)!=pid) err_crit("wait error\n");
	      DPRINTF(("in parent status ==%d\n",status));
	      DPRINTF(("======KID end=====================\n"));
	      
	      free_exec_matrix();
	      return(status);
	      
       }
       else{  /* kids*/
	      DPRINTF(("=======KID BEG====================\n")); 
	      close(1);
	      close(2);
	      
	      execvp(exec_matrix[0],exec_matrix);
	      err_crit("\n\n##############Couldn't exec##########\n");
	      
       }
       
       
}/* exec_it */




/******************************************************************
  PARSE_TO_EXEC_MATRIX
  *******************************************************************/
/* chops a line delimeted by spaces and puts the pieces in the
   global exec matrix mallocs space for exec_matrix                 */
void parse_to_exec_matrix(str)
char * str;
{
       int i=0;
       char *ptr;
       char buf[MAXSTR];
       
       strcpy(buf,str);
       PUT_NULL(buf);
       
       ptr = strtok(buf," ");
       
       MALLOC_STR(exec_matrix[i]);
       
       strcpy(exec_matrix[i],ptr);
       i++;
       
       while((ptr =strtok((char*)NULL," "))!=NULL){
	      MALLOC_STR(exec_matrix[i]);
	      strcpy(exec_matrix[i],ptr);
	      i++;
	      
       }
       
       /*  DPRINTF((" num of elements parsed ==%d\n",i-1));  */
       /*  if (i==1){ 
	   strcpy(exec_matrix[i],exec_matrix[0]);
	   PUT_NULL(exec_matrix[i]);
	   i++;
	   }
	   */
       
       exec_matrix[i]=NULL;
       num_in_exec_matrix = i-1;
       
       
}
/******************************************************************
  DUMP_EXEC_MATRIX
  *******************************************************************/
/* prints contents of exec matrix, used for debugging             */

void dump_exec_matrix()
{
       int i=0;
       DTRACE;
       DPRINTF(("\n\n"));
       for(i=0;exec_matrix[i]!=0;i++)
       DPRINTF(("\texec matrix[%d]-->%s\n",i,exec_matrix[i]));
       
}

/******************************************************************
  free_exec_matrix
  *******************************************************************/
/* frees memory allocated in parse to exec_matrix resets global
   num_in_exec_matrix                                              */
void free_exec_matrix()
{
       int i;
       for(i=0;i<num_in_exec_matrix;i++)
       free(exec_matrix[i]);
       
       num_in_exec_matrix=0;
       
}
