modules/pc/protocol_config.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. find_command
  2. show_commands
  3. command_help
  4. command_quit
  5. show_const
  6. show_consts
  7. show_props
  8. show_thread
  9. show_whois
  10. command_execute
  11. command_show
  12. command_repeat
  13. set_const
  14. set_consts
  15. set_props
  16. command_set
  17. command_sql
  18. process_input
  19. log_config
  20. echo_off
  21. echo_on
  22. authenticate_user
  23. PC_interact

/***************************************
  $Revision: 1.7 $

  Protocol config module (pc).  This is the protocol that the admin uses to
  talk to the server.

  Status: NOT REVUED, NOT TESTED

  ******************/ /******************
  Filename            : protocol_config.c
  Author              : ottrey@ripe.net
  OSs Tested          : Solaris
  To Do               : Add a facility to take callbacks instead of
                        hard-coding menu options.
  ******************/ /******************
  Copyright (c) 1999                              RIPE NCC
 
  All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of the author not be
  used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.
  
  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  ***************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>       /* Time stuff */
#include <sys/ioctl.h>      /* Terminal control stuff */
#include <termio.h>      /* Terminal control stuff */

#include "mysql_driver.h"
#include "constants.h"
#include "properties.h"
#include "thread.h"
#include "protocol_config.h"

/*+ Each command has a +*/
typedef struct _command {
  const char *name;                          /*+ Name to be invoked. +*/
  char *(*function)(char *);      /*+ Function to be invoked. +*/
  const char *help;                                /*+ Command help. +*/
} Command;

/*
 * Forward declarations
 */
static char *command_help(char *input);
static char *command_quit(char *input);
static char *command_show(char *input);
static char *command_repeat(char *input);
static char *show_const(char *input);
static char *show_consts(char *input);
static char *show_props(char *input);
static char *show_thread(char *input);
static char *show_whois(char *input);
static char *command_set(char *input);
static char *set_const(char *input);
static char *set_consts(char *input);
static char *set_props(char *input);
static char *command_sql(char *input);

/*+
 * Contains the command definitions
+*/
static struct _command command[] = {
  {"help"   , command_help   , HELP_HELP   },
  {"quit"   , command_quit   , HELP_QUIT   },
  {"show"   , command_show   , HELP_SHOW   },
  {"repeat" , command_repeat , HELP_REPEAT },
  {"set"    , command_set    , HELP_SET    },
  {"sql"    , command_sql    , HELP_SQL    },
  NULL
};

/*+
 * Contains the show commands
+*/
static struct _command show[] = {
  {"const"   , show_const   , HELP_SHOW_CONST   },
  {"consts"  , show_consts  , HELP_SHOW_CONSTS  },
  {"props"   , show_props   , HELP_SHOW_PROPS   },
  {"thread"  , show_thread  , HELP_SHOW_THREAD  },
  {"whois"   , show_whois   , HELP_SHOW_WHOIS   },
  NULL
};

/*+
 * Contains the set commands
+*/
static struct _command set[] = {
  {"const"  , set_const  , HELP_SET_CONST  },
  {"consts" , set_consts , HELP_SET_CONSTS },
  {"props"  , set_props  , HELP_SET_PROPS  },
  NULL
};

static int find_command(char *comm_name, Command *comm) {
/* [<][>][^][v][top][bottom][index][help] */
  int i, index;
  char comm_buffer[STR_L];

  if (comm_name != NULL) {
    strcpy(comm_buffer, comm_name);
    strtok(comm_buffer, " \t");
    for (i=0, index=-1; comm[i].name != NULL; i++) {
      if ( strcmp(comm_buffer, comm[i].name) == 0) {
        index = i;
        break;
      }
    }
  }
  else {
    index = -2;
  }

  return index;
} /* find_command() */

static char *show_commands(Command *comm) {
/* [<][>][^][v][top][bottom][index][help] */
  char *str;
  char help_buffer[STR_XL];
  char help_comm[STR_M];
  int i;

  sprintf(help_buffer, " commands are:\n\n");
  i = 0;
  while (comm[i].name != NULL) {
    sprintf(help_comm, "%s\t%s\n", comm[i].name, comm[i].help);
    strcat(help_buffer, help_comm);
    i++;
  }

  str = (char *)calloc(1, strlen(help_buffer)+1);
  strcpy(str, help_buffer);

  return str;
} /* show_commands() */


/*
 * Command functions
 */
static char *command_help(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  char *str;
  char *str1;
  char output_buffer[STR_XXL];
  char *command_name;
  int index;

  strcpy(output_buffer, "");

  strtok(input, " \t");
  command_name = (char *)strtok(NULL, " \t");

  index = find_command(command_name, command);

  switch (index) {
    case -2:
      strcat(output_buffer, "Main");
      str1 = show_commands(command);
      strcat(output_buffer, str1);
      free(str1);
      break;

    case -1:
      strcat(output_buffer, HELP_ERROR);
      strcat(output_buffer, command_name);
      break;

    default: 
      strcat(output_buffer, command[index].help);
  }

  /*
  str = (char *)CopyString(output_buffer);
  */
  str = (char *)calloc(1, strlen(output_buffer)+1);
  strcpy(str, output_buffer);

  return str;
} /* command_help() */

static char *command_quit(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
    /* Client wishes to quit. */
  return NULL;
} /* command_quit() */

static char *show_const(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to show constants. */
  char *result;
  char *name;
  char *tmp_input;

  tmp_input = (char *)calloc(1, strlen(input)+1);
  strcpy(tmp_input, input);

  /* The name will be the third token in stuff */
  strtok(tmp_input, " ");
  strtok(NULL, " ");
  name = (char *)strtok(NULL, " ");

  result = CO_const_to_string(name);

  free(tmp_input);
  return result;

} /* show_const() */

static char *show_consts(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to show constants. */
  return CO_to_string();

} /* show_consts() */

static char *show_props(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to show properties. */
  return PR_to_string();

} /* show_props() */

static char *show_thread(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to show thread information. */
  return TH_to_string();

} /* show_thread() */

static char *show_whois(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to show whois query information. */
  return "WQ_to_string();";

} /* show_thread() */

static char *command_execute(char *input, char *comm_name, Command *comm) {
/* [<][>][^][v][top][bottom][index][help] */
  char *str;
  char *str1;
  char output_buffer[STR_XXL];
  char tmp[STR_L];
  char *name;
  int index;
  char *tmp_input;

  /* Make a copy of the input */
  tmp_input = (char *)calloc(1, strlen(input)+1);
  strcpy(tmp_input, input);

  strtok(tmp_input, " \t");
  name = (char *)strtok(NULL, " \t");

  index = find_command(name, comm);

  switch (index) {
    case -2:
      str1 = show_commands(comm);
      sprintf(output_buffer, "%s%s", comm_name, str1);
      free(str1);
      break;

    case -1:
      sprintf(output_buffer, "%s invalid command: %s", comm_name, name);
      break;

    default: 
      sprintf(output_buffer, "%s", comm[index].function(input));
  }

  /*
  str = (char *)CopyString(output_buffer);
  */
  str = (char *)calloc(1, strlen(output_buffer)+1);
  strcpy(str, output_buffer);

  free(tmp_input);

  return str;
} /* command_execute() */

static char *command_show(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  return command_execute(input, "Show", show);
} /* command_show() */

static char *command_repeat(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  char *command_ptr;

  /* Goto the bit after "repeat n " */
  for (command_ptr=input+7; command_ptr[0] != ' ' || (command_ptr[0] >= '0' && command_ptr[0] <= '9'); command_ptr++);

  return command_ptr+1;

} /* command_show() */

static char *set_const(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to set a constant. */
  char *result;
  char result_buf[STR_M];
  char *tmp_input;
  char *name;
  char *value;
  int value_len;
  char *stuff;
  char *str;

  tmp_input = (char *)calloc(1, strlen(input)+1);
  strcpy(tmp_input, input);

  stuff = (char *)strtok(tmp_input, "=");

  /* The value will be after the '=' */
  value = (char *)strtok(NULL, "=");

  /* The name will be the third token in stuff */
  strtok(stuff, " ");
  strtok(NULL, " ");
  name = (char *)strtok(NULL, " ");

  /* Remove any quotes */
  if (value[0] == '"') {
    value++;
  }
  value_len=strlen(value);
  if (value[value_len-1] == '"') {
    value[value_len-1]='\0';
  }

  printf("set_const name=(%s), value=(%s)\n", name, value);
  if (CO_set_const(name, value) == 0) {
    strcpy(result_buf, "Constant successfully set\n");
  }
  else {
    str = CO_const_to_string(name);
    sprintf(result_buf, "Constant not successfully set\nReverting to:   %s=%s\n", name, str);
    free(str);
  }

  result = (char *)calloc(1, strlen(result_buf)+1);
  strcpy(result, result_buf);

  free(tmp_input);
  return result;
} /* set_const() */

static char *set_consts(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to set constants. */
  return CO_set();
} /* set_consts() */

static char *set_props(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  /* Client wishes to set properties. */
  return PR_set();
} /* set_props() */

static char *command_set(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  return command_execute(input, "Set", set);
} /* command_set() */

static char *command_sql(char *input) {
/* [<][>][^][v][top][bottom][index][help] */
  char *str;
  char output_buffer[STR_XXL];
  char *current_character;
  char *whois_query;
  char *sql_str;

  char *res=NULL;

  SQ_result_set_t *sql_result=NULL;
  SQ_connection_t *sql_connection;

  sql_connection = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password() );

  if (sql_connection == NULL) {
    printf("/* Check for errors */\n");
  }

  /* skip over the "sql" */
  sql_str = input+3;
  /* skip over white space */
  while (sql_str[0] == ' ') {
    sql_str++;
  }

  strcpy(output_buffer, "");

  if (sql_connection != NULL) {
    if (strcmp(sql_str, "status") == 0) {
      /* Get the status of the database */
      res = SQ_info_to_string(sql_connection);
    }
    else {
      if (strcmp(sql_str, "") == 0) {
        /* Execute the default query (from the properties file) */
        sql_result = SQ_execute_query(sql_connection, CO_get_query());
      }
      else {
        /* Execute an sql query */
        sql_result = SQ_execute_query(sql_connection, sql_str);
      }
      if (sql_result != NULL) {
        res = SQ_result_to_string(sql_result);
      }
      else {
        printf("no results\n");
      }
    }
    if (res != NULL) {
      sprintf(output_buffer, "%s", res);
    }
    else {
      printf("empty results\n");
    }
  }
  else {
    printf("Failed to make connection\n");
  }

  /*
  strcat(output_buffer, mysql_info(sql_connection));
  */

  strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here.  But it's not working!");

  /*
  str = (char *)CopyString(output_buffer);
  */
  str = (char *)calloc(1, strlen(output_buffer)+1);
  strcpy(str, output_buffer);

  free(res);
  SQ_free_result(sql_result);

  SQ_close_connection(sql_connection);

  return str;

} /* command_sql() */


/* process_input() */
/*++++++++++++++++++++++++++++++++++++++

  Process the input.

  int sock  The socket to connect to.

  More:
  +html+ <PRE>
  Author:
        ottrey
  +html+ </PRE>
  ++++++++++++++++++++++++++++++++++++++*/
static int process_input(char *input, int sock) {
/* [<][>][^][v][top][bottom][index][help] */
  int connected = 1;
  char *input_ptr;
  char *output;
  char *command_name;
  int  index;
  int repeat=0;

  input_ptr = input;

  if (strncmp(input, "repeat", 6) == 0) {
    /* XXX This is a really dodgy call, that hopefully converts
    the string to the value of the first found integer. */
    repeat = atoi(input+7);
    input_ptr= command_repeat(input);
  }

  index = find_command(input_ptr, command);

  do {
    switch (index) {
      case -1:
        /* Command not found */
        output = command_help(NULL);
        break;

      default: 
        output = command[index].function(input_ptr);
    }

    if(output == NULL) {
      connected = 0;
    } else {
      /*
      printf("thread output=\n%s\n", output);
      */
      if ( CO_get_clear_screen() == 1 ) {
        SK_puts(sock, CLEAR_SCREEN);
      }
      SK_puts(sock, output);
      SK_puts(sock, "\n");
      SK_puts(sock, CO_get_prompt());
    }

    free(output);

    if (repeat > 0) {
      repeat--;
      sleep(CO_get_sleep_time());
    }

  } while (repeat > 0);

  return connected;

} /* process_input() */

static void log_config(const char *user, const char *status) {
/* [<][>][^][v][top][bottom][index][help] */
  FILE *logf;
  char *str;
  time_t now;

  time(&now);

  if (CO_get_config_logging() == 1) {
    
    if (strcmp(CO_get_config_logfile(), "stdout") == 0) {
      printf(LOG_CONFIG, TH_get_id(), user, status, ctime(&now));
    }
    else {
      logf = fopen(CO_get_config_logfile(), "a");
      fprintf(logf, LOG_CONFIG, TH_get_id(), user, status, ctime(&now));
      fclose(logf);
    }
  }

} /* log_config() */
 
/* XXX Doh! These only change the server's terminal.  We need some
   tricky escape sequence to send over the socket. */ 
static void echo_off(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
  struct termio state;

  ioctl(0, TIOCGETP, &state);
  state.c_lflag &= ~ECHO;
  ioctl(0, TIOCSETP, &state);
} /* echo_off() */

/* XXX Doh! These only change the server's terminal.  We need some
   tricky escape sequence to send over the socket. */ 
static void echo_on(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
  struct termio state;

  ioctl(0, TIOCGETP, &state);
  state.c_lflag |= ECHO;
  ioctl(0, TIOCSETP, &state);
} /* echo_on() */

static char *authenticate_user(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
  char *user = NULL;
  char Salt[2] = "DB";
  char input[MAX_INPUT_SIZE];
  int read_result;
  char *password=NULL;
  char *user_password=NULL;
  char user_buf[10];

  SK_puts(sock, LOGIN_PROMPT);
  read_result = SK_gets(sock, input, MAX_INPUT_SIZE);

  strncpy(user_buf, input, 10);

  SK_puts(sock, PASSWD_PROMPT);
  /* XXX These aren't working.
  SK_puts(sock, ECHO_ON);
  echo_off(sock);
  */
  read_result = SK_gets(sock, input, MAX_INPUT_SIZE);
  /* XXX These aren't working.
  echo_on(sock);
  SK_puts(sock, ECHO_OFF);
  */

  password = (char *)crypt(input, Salt);

  user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);

  if (user_password != NULL) {
    if (strcmp(password, user_password) == 0) {
      user = (char *)calloc(1, strlen(user_buf)+1);
      strcpy(user, user_buf);
    }
  }

  if (user == NULL) {
    log_config(user_buf, "unsuccesful login attempt");
  }

  return user;

} /* authenticate_user() */

void PC_interact(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
  char input[MAX_INPUT_SIZE];
  int connected = 1;
  int read_result;
  char *welcome;
  char *user=NULL;

  /* Welcome the client */
  SK_puts(sock, CO_get_welcome());

  /* Authenticate the user */
  if (CO_get_authenticate() == 1) {
    user = authenticate_user(sock);
  }
  else {
    user="nobody";
  }

  if (user != NULL) {
    /* Log admin logging on */
    log_config(user, "logged on");

    SK_puts(sock, CO_get_prompt());

    while (connected) {
      /* Read input */
      read_result = SK_gets(sock, input, MAX_INPUT_SIZE);
      if (read_result == -1) {
        connected = 0;
      }
      else if (read_result == -2) {
        printf("Thread received a control-c\n");
        connected = 0;
      }
      connected = process_input(input, sock);
    }

    /* Log admin logging off */
    log_config(user, "logged off");
  }

  /* Close the socket */
  SK_close(sock);

} /* PC_interact() */


/* [<][>][^][v][top][bottom][index][help] */