/*

                                   _JNJ`                        
                               .JNMH`                           
                              JMMF`       `;.                   
                            .NMM)          `MN.                 
                            MMM)            (MML                
                           (MMM`             MMML               
                     M  I  D  N  I  G  H  T    C  o  D  E       
                           (NMMF             MHNH               
                            NMML            .MMM                
                             NMML          .NMH                 
                              4MMNL       .#F                   
                               `4HNNL_   `                      
                                   `"""`                        

                          Copyright (C) 2004-2005
       "Ian (Larry) Latter" <ian dot latter at midnightcode dot org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, and mirrored at the Midnight Code web
    site; as at version 2 of the License only.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    (version 2) along with this program; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA, or see http://midnightcode.org/gplv2.txt

*/

/* midnightcode-switch.c :: Midnight Code command-line switch library	*/


#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>

#include "midnightcode-colour.h"
#include "midnightcode-switch.h"


int
midnightcode_switch_usage(int style, char * execname,
                          struct midnightcode_switch_t * switches) {
  struct midnightcode_switch_t* this_switch;
  char param[10];
  int  switchn;


  fprintf(stdout, "    Usage: %s [switch [value]] ..\n", execname);
  for(this_switch = switches, switchn = 0;
      this_switch[switchn].variable != NULL;
      switchn++) {

    memset(param, 0, 10);
    switch(this_switch[switchn].type) {
      case MIDNIGHTCODE_SWITCH_TYPE_NONE:
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_STRING:
        strncpy(param, "{string}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_INT:
        strncpy(param, "{int}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_LONG:
        strncpy(param, "{long}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_VAL:
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_FLOAT:
        strncpy(param, "{float}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_DOUBLE:
        strncpy(param, "{double}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_HOST:
        strncpy(param, "{host}", 8);
        break;

      case MIDNIGHTCODE_SWITCH_TYPE_IP:
        strncpy(param, "{ip}", 8);
        break;

      default:
        break;
    }
    switch(style) {
      case MIDNIGHTCODE_SWITCH_STYLE_SOFT:
        fprintf(stdout, MIDNIGHTCODE_COLOUR_DK_GREY
                        "      --%-12.12s -%-3.3s %-8.8s %-45.45s\n"
                        MIDNIGHTCODE_COLOUR_NORMAL,
                        this_switch[switchn].long_s,
                        this_switch[switchn].short_s, param,
                        this_switch[switchn].descript_s);
        fflush(stdout);
        break;

      case MIDNIGHTCODE_SWITCH_STYLE_NORMAL:
        fprintf(stdout, MIDNIGHTCODE_COLOUR_NORMAL
                        "      --%-12.12s -%-3.3s %-8.8s %-45.45s\n"
                        MIDNIGHTCODE_COLOUR_NORMAL,
                        this_switch[switchn].long_s,
                        this_switch[switchn].short_s, param,
                        this_switch[switchn].descript_s);
        fflush(stdout);
        break;

      case MIDNIGHTCODE_SWITCH_STYLE_STRONG:
        fprintf(stdout, MIDNIGHTCODE_COLOUR_WHITE
                        "      --%-12.12s -%-3.3s %-8.8s %-45.45s\n"
                        MIDNIGHTCODE_COLOUR_NORMAL,
                        this_switch[switchn].long_s,
                        this_switch[switchn].short_s, param,
                        this_switch[switchn].descript_s);
        fflush(stdout);
        break;

      default:
        fprintf(stdout, MIDNIGHTCODE_COLOUR_YELLOW
                        "      --%-12.12s -%-3.3s %-8.8s %-45.45s\n"
                        MIDNIGHTCODE_COLOUR_NORMAL,
                        this_switch[switchn].long_s,
                        this_switch[switchn].short_s, param,
                        this_switch[switchn].descript_s);
        fflush(stdout);
        break;
    }
  }
  fprintf(stdout, "\n");
  fflush(stdout);

  return 0;
}



int
midnightcode_switch_process(int argc, char** argv,
                            struct midnightcode_switch_t * switches) {
  struct midnightcode_switch_t* this_switch;
  char long_s[64], short_s[4];
  int  argn, switchn, chrn, dotn;
  int  matched, offset;
  char equal_buf[1024];
  int  equal_check;
  int  *int_p;
  char *char_p;
  long  *long_p;
  u_long *u_long_p;
  float *float_p;
  double *double_p;
  struct hostent *host_ent;
  struct in_addr in_adr;


  for(argn = 1; argn < argc && argv[argn][0] == '-'; argn++) {
    for(this_switch = switches, switchn = 0;
        this_switch[switchn].variable != NULL;
        switchn++) {

      memset(long_s, 0, 64);
      memset(short_s, 0, 4);
      if(this_switch[switchn].long_s != NULL) {
        strncpy(long_s, "--", 63);
        strncat(long_s, this_switch[switchn].long_s, 61);
      }
      if(this_switch[switchn].short_s != NULL) {
        strncpy(short_s, "-", 3);
        strncat(short_s, this_switch[switchn].short_s, 2);
      }

      matched = 0;
      offset = 0;
      equal_check = 0;

      if(strcmp(argv[argn], long_s) == 0) {
        matched = 1;
      } else if(strcmp(argv[argn], short_s) == 0) {
        matched = 1;
      } else if(strncmp(argv[argn], long_s, strlen(long_s)) == 0) {
        matched = 1;
        offset = strlen(long_s);
      } else if(strncmp(argv[argn], short_s, strlen(short_s)) == 0) {
        matched = 1;
        offset = strlen(short_s);
      }

      if(offset) {
        if(argv[argn][offset] == '=') {
          offset++;
          memset(equal_buf, 0, 1024);
          strncpy(equal_buf, &argv[argn][offset], 1023);
          equal_check = 1;
        } else {
          offset = 0;
          matched = 0;
        }
      }

      if(matched) {

        switch(this_switch[switchn].type) {
          case MIDNIGHTCODE_SWITCH_TYPE_NONE:
            int_p = this_switch[switchn].variable;
            *int_p = 1;
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_STRING:
            char_p = this_switch[switchn].variable;
            memset(char_p, 0, this_switch[switchn].length);
            if(equal_check) {
              strncpy(char_p, equal_buf, this_switch[switchn].length - 1);
            } else {
              if(this_switch[switchn].length == 0 || argn + 1 >= argc)
                break;
	      argn++;
              strncpy(char_p, argv[argn], this_switch[switchn].length - 1);
            }
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_INT:
            int_p = this_switch[switchn].variable;
            if(equal_check) {
              *int_p = (int)strtol(equal_buf, (char **)NULL, 10);
            } else {
              if(argn + 1 >= argc)
                break;
	      argn++;
              *int_p = (int)strtol(argv[argn], (char **)NULL, 10);
            }
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_LONG:
            long_p = this_switch[switchn].variable;
            if(equal_check) {
              *long_p = strtol(equal_buf, (char **)NULL, 10);
            } else {
              if(argn + 1 >= argc)
                break;
	      argn++;
              *long_p = strtol(argv[argn], (char **)NULL, 10);
            }
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_VAL:
            int_p = this_switch[switchn].variable;
            *int_p = this_switch[switchn].value;
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_FLOAT:
            float_p = this_switch[switchn].variable;
            if(equal_check) {
              *float_p = (float)strtod(equal_buf, (char **)NULL);
            } else {
              if(argn + 1 >= argc)
                break;
	      argn++;
              *float_p = (float)strtod(argv[argn], (char **)NULL);
            }
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_DOUBLE:
            double_p = this_switch[switchn].variable;
            if(equal_check) {
              *double_p = strtod(equal_buf, (char **)NULL);
            } else {
              if(argn + 1 >= argc)
                break;
	      argn++;
              *double_p = strtod(argv[argn], (char **)NULL);
            }
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_HOST:
            u_long_p = this_switch[switchn].variable;
            if(equal_check) {
              if((host_ent = gethostbyname(equal_buf)) == NULL)
                return argn;
            } else {
              if(argn + 1 >= argc)
                break;
	      argn++;
              if((host_ent = gethostbyname(argv[argn])) == NULL)
                return argn;
            }
            if(host_ent->h_addrtype != AF_INET)
              return argn;
            memcpy(&in_adr.s_addr, host_ent->h_addr, host_ent->h_length);
            *u_long_p = in_adr.s_addr;
            break;

          case MIDNIGHTCODE_SWITCH_TYPE_IP:
            u_long_p = this_switch[switchn].variable;
            if(!equal_check) {
              if(argn + 1 >= argc)
                break;
	      argn++;
              memset(equal_buf, 0, 17);
              strncpy(equal_buf, argv[argn], 17);
            }
            if(strlen(equal_buf) > 16)
              return argn;
            char_p = equal_buf;
            for(dotn = 0, chrn = 0; chrn < 17; chrn++) {
              char_p = equal_buf;
              char_p += chrn;
              if(*char_p == '\0')
                break;
              if(!(*char_p >= 48 && *char_p <= 57) && *char_p != 46)
                return argn;
              if(*char_p == '.')
                dotn++;
            }
            if(dotn != 3)
              return argn;
            if((host_ent = gethostbyname(equal_buf)) == NULL)
              return argn;
            if(host_ent->h_addrtype != AF_INET)
              return argn;
            memcpy(&in_adr.s_addr, host_ent->h_addr, host_ent->h_length);
            *u_long_p = in_adr.s_addr;
            break;

          default:
            return argn;
            break;
        }

        break;
      }
    }
    if(this_switch[switchn].variable == NULL)
      return argn;
 
  }
  if(argn != argc)
    return argn;

  return 0;
}


