
// PostgreSQL チェック用コマンド

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in_systm.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<fcntl.h>

#include<sys/stat.h>
#include<errno.h>

#include"sitar_scan.h"
#include"sitar_com.h"
#include <almemsys/almemsys.h>
#include"jpreturn.h"
#include "version.h"

#include<libpq-fe.h>



// DE BUG 用
// #define PSQL_BUG


int main(int argc, char * argv[])
{
char i;

PGconn * conn = 0;
PGresult * res;

int st;
int port;
int timeout;
int db_select;
char * database;
char * passwd;
char * username;
char * server;
char * query;
char * dns_data;
char * connect_data;
extern char *optarg;

port = 5432;
timeout = 2;
db_select = 0;
st = 0;

if((database = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((passwd = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((username = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((server = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((query = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((dns_data = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((connect_data = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}

// defaultのDNSを設定
dns_data = safe_memcpy(dns_data, "127.0.0.1", 1024);

// optionの処理
while((i=getopt(argc,argv,"y:p:P:d:u:s:q:t:o"))!= EOF){
   switch(i){
      case 'P': if(0 == ch_int2(optarg)){
                   port = strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 't': if(0 == ch_int2(optarg)){
                   timeout = strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 'p': if(optarg != NULL){
                   passwd = safe_memcpy(passwd, optarg, 256);
                   }
                else{
                   passwd = safe_memcpy(passwd, "", 2);
                   }
              break;
      case 'd': if(optarg != NULL){
                   database = safe_memcpy(database, optarg, 256);
                   db_select = 1;
                   }
                else{
                   database = safe_memcpy(database, "", 256);
                   db_select = 0;
                   }
              break;
      case 'u': if(optarg != NULL){
                   username = safe_memcpy(username, optarg, 256);
                   }
                else{
                   username = safe_memcpy(username, "postgres", 256);
                   }
              break;
      case 's': if(optarg != NULL){
                   server = safe_memcpy(server, optarg, 256);
                   }
                else{
                   server = safe_memcpy(server, "127.0.0.1", 256);
                   }
              break;
      case 'q': if(optarg != NULL){
                   query = safe_memcpy(query, optarg, 256);
                   }
                else{
                   query = safe_memcpy(query, "SHOW data_directory;", 256);
                   }
              break;


      default : printf("scanpgsql-%s $scanpgsql -t <timeout> -s <server> -u <username> -p <passwd> -d <database> -P <port> -q <query>\n",VERSION);
              free(database);
              free(passwd);
              free(username);
              free(server);
              free(query);
              free(connect_data);
              exit(1);
              break;
      }
   }


if(0 == strlen(query)){
   query = safe_memcpy(query, "SHOW data_directory;", 256);
   }

if(0 == strlen(database)){
   database = safe_memcpy(database, "postgres", 256);
   }


#ifdef PSQL_BUG
printf("PSQL_BUG: scanpgsql main():\n server=<-s %s>\n username=<-u %s>\n passwd=<-p %s>\n database=<-d %s>\n port=<-P %d>\n query=<-q %s>\n timeout=<-t %d>\n",
        server,
        username,
        passwd,
        database,
        port,
        query,
        timeout);
#endif


// postgres 用 text data を作る

if(timeout < 2){
   timeout = 2;
   }

if(0 != strlen(server)){
   connect_data = safe_sprintf(connect_data, BUF_LEN,"hostaddr='%s' port='%d' connect_timeout='%d' dbname='%s' ",
    server, port, timeout, database);
   }
else{
   connect_data = safe_sprintf(connect_data, BUF_LEN,"hostaddr='%s' port='%d' connect_timeout='%d' dbname='%s' ",
    "127.0.0.1", port, timeout, database);
   }

if(0 != strlen(username)){
   connect_data = safe_strncat(connect_data, "user='", BUF_LEN);
   connect_data = safe_strncat(connect_data, username, BUF_LEN);
   connect_data = safe_strncat(connect_data, "' ", BUF_LEN);
   }

if(0 != strlen(passwd)){
   connect_data = safe_strncat(connect_data, "password='", BUF_LEN);
   connect_data = safe_strncat(connect_data, passwd, BUF_LEN);
   connect_data = safe_strncat(connect_data, "' ", BUF_LEN);
   }


#ifdef PSQL_BUG
printf("PSQL_BUG: scanpgsql main(): connect_data ->  (%s)\n", connect_data);
#endif


// 接続してみる
conn = PQconnectdb(connect_data);

// 正常な接続かの確認
if(CONNECTION_BAD == PQstatus(conn)){
   // postgreSQLに接続出来ない
   printf("PQconnecttdb(): %s: %s\n", PGSQL_ERR1, PQerrorMessage(conn));
   PQfinish(conn);
   free(database);
   free(passwd);
   free(username);
   free(server);
   free(query);
   free(connect_data);
   exit(1);
   }
else{
   #ifdef PSQL_BUG
   fprintf(stderr, "POSTGRES_DEBUG: scanpgsql(): postgreSQLに正常に接続できました\n");
   #endif
   }



// 正常に問い合わせが出来るか

res = PQexec(conn, query);

switch(PQresultStatus(res)){

   case PGRES_EMPTY_QUERY:
        // サーバに送信された文字列が空
        printf("PQresultStatus(): %s: %s\n", PGSQL_ERR2, PQresultErrorMessage(res));
        st = -1;
        break;
   case PGRES_BAD_RESPONSE:
        // サーバが不明な応答を返した
        printf("PQresultStatus(): %s: %s\n", PGSQL_ERR3, PQresultErrorMessage(res));
        st = -1;
        break;
   case PGRES_NONFATAL_ERROR:
        // エラーではなく警告を返した
        printf("PQresultStatus(): %s: %s\n", PGSQL_ERR4, PQresultErrorMessage(res));
        st = -1;
        break;
   case PGRES_FATAL_ERROR:
        // 生命にかかわるエラーを返した
        printf("PQresultStatus(): %s: %s\n", PGSQL_ERR5, PQresultErrorMessage(res));
        st = -1;
        break;
   default:
        #ifdef PSQL_BUG
        printf("PQresultStatus(): ステータスは正常です\n");
        #endif
        st = 0;
        break;
   }

if(st < 0){
   PQclear(res);
   PQfinish(conn);
   free(database);
   free(passwd);
   free(username);
   free(server);
   free(query);
   free(connect_data);
   exit(1);
   }


   // レコード数が0かそれ以下の場合
if(1 > PQntuples(res)){
   // 問い合わせに該当する行数が0です
   printf("PQntuples(): %s\n", PGSQL_ERR6);
   PQclear(res);
   PQfinish(conn);
   free(database);
   free(passwd);
   free(username);
   free(server);
   free(query);
   free(connect_data);
   exit(1);
   }
else{
   #ifdef PSQL_BUG
   printf("PQntuples(): 問い合わせに該当する行数が1個以上ありました\n");
   #endif
   }


PQclear(res);
PQfinish(conn);
free(database);
free(passwd);
free(username);
free(server);
free(query);
free(connect_data);

return 0;
}



