Logo Search packages:      
Sourcecode: fbgetty version File versions  Download package

options.c

/*
 * fbgetty : a getty for framebuffer 
 * Copyright (C) 1999 2000 2001 Yann Droneaud <ydroneaud@meuh.eu.org>. 
 *
 * fbgetty 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; either version 2, or (at your option)
 * any later version.
 *
 * fbgetty 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
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 *
 */


/*
 * in some function, there are some pointer arithmetics
 * it was used some void* pointers, GCC assume those to point on 1 byte data
 * To be more ANSI, these pointers were replaced by (unsigned char *) ones
 * Be sure that (char) is a one byte data
 */

#include <fbgetty/global.h>


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

#include <paths.h>

#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include <fbgetty/getopt.h>
#endif

#include <fbgetty/options.h>
#include <fbgetty/errors.h>
#include <fbgetty/canonicalize.h>
#include <fbgetty/kbd.h>

static void usage (void);
static void help (void);
static void version (void);
static void compile (void);
static void dump_config(void);
static int parse_binary(const char *);
static int merge_options(void);

/* the global options structure */
fbgetty_options_t *fgoptions;

/* all parsed options are stored here */
static fbgetty_options_t *fgoptions_parsed[4] = { NULL, NULL, NULL, NULL };

#define FGOPTIONS_OPTIONS 0
#define fgoptions_options fgoptions_parsed[FGOPTIONS_OPTIONS]
#define FGOPTIONS_ARGUMENTS 1
#define fgoptions_arguments fgoptions_parsed[FGOPTIONS_ARGUMENTS]
#define FGOPTIONS_ENVIRONMENT 2
#define fgoptions_environment fgoptions_parsed[FGOPTIONS_ENVIRONMENT]

static int show_version = 0;
static int show_help = 0;
static int show_error = 0;
static int show_compile = 0;
static int show_config = 0;

#define OPTION_LONG(major, minor) ((major << 8) + minor)

#define OPTION_TTY     't'
#ifdef USE_FRAME_BUFFER
#define OPTION_FB      'f'
#endif
#define OPTION_ISSUE   'i'
#define OPTION_REFRESH 'r'
#define OPTION_PROGRAM 'l'
#define OPTION_PROMPT  'p'
#define OPTION_TIMEOUT 'o'

  /* 'c' like clear */ 
#define OPTION_CLEAR   OPTION_LONG('c','y')

  /* 'm' for misc */
#define OPTION_VERSION OPTION_LONG('m','v') 
#define OPTION_COMPILE OPTION_LONG('m','c')
#define OPTION_HELP    OPTION_LONG('m','h')
#define OPTION_DUMP    OPTION_LONG('m','d')

  /* 'k' for keyboard */
#define OPTION_KBD  OPTION_LONG('k','s')
 
#ifdef USE_FRAME_BUFFER
#define SHORT_OPTIONS "t:f:p:l:i:o:"
#else
#define SHORT_OPTIONS "t:p:l:i:o:"
#endif /* USE_FRAME_BUFFER */

static struct option long_options[] =
  {
    /* devices */
    { "tty",           required_argument, NULL, OPTION_TTY },
#ifdef USE_FRAME_BUFFER
    { "framebuffer",   required_argument, NULL, OPTION_FB },
    { "fb",            required_argument, NULL, OPTION_FB },
#endif 

    { "issue",         required_argument, NULL, OPTION_ISSUE }, 

    { "login-program", required_argument, NULL, OPTION_PROGRAM },
    { "login-prompt",  required_argument, NULL, OPTION_PROMPT },
    { "login-timeout", required_argument, NULL, OPTION_TIMEOUT },

    { "clear-screen",  optional_argument, NULL, OPTION_CLEAR }, 
    { "refresh",       required_argument, NULL, OPTION_REFRESH }, 

    { "kbd",           required_argument, NULL, OPTION_KBD },
    { "keyboard",      required_argument, NULL, OPTION_KBD },

    /* informations */
    { "version",       no_argument,       NULL, OPTION_VERSION },
    { "compile",       no_argument,       NULL, OPTION_COMPILE },
    { "dump-config",   no_argument,       NULL, OPTION_DUMP },
    { "help",          no_argument,       NULL, OPTION_HELP },
    { NULL, 0, NULL, 0}
  };


#define ENV_STRING  0x01
#define ENV_INTEGER 0x02
#define ENV_BINARY  0x04
#define ENV_LEDS    0x08

#define ENV_ENTRY(name, type, ptr) { name, type, OFFSET_ ## ptr }

static struct env_entry
{
  char *name;
  int type;
  unsigned long offset;
}
env_options[] = 
{
  ENV_ENTRY("tty", ENV_STRING, tty_device),
  ENV_ENTRY("line", ENV_STRING, tty_device),

#ifdef USE_FRAME_BUFFER
  ENV_ENTRY("fb", ENV_STRING, fb_device),
  ENV_ENTRY("framebuffer", ENV_STRING, fb_device),
  ENV_ENTRY("frame_buffer", ENV_STRING, fb_device),
#endif

  ENV_ENTRY("clear_screen", ENV_BINARY, screen_clear),
  ENV_ENTRY("login_hide", ENV_BINARY, login_hide),

  ENV_ENTRY("issue", ENV_STRING, issue_filename),
  ENV_ENTRY("issue_refresh", ENV_INTEGER, issue_refresh),
  ENV_ENTRY("refresh", ENV_INTEGER, issue_refresh),
  
  ENV_ENTRY("login_program", ENV_STRING, login_program),
  ENV_ENTRY("login_prompt", ENV_STRING, login_prompt),
  ENV_ENTRY("login_timeout", ENV_INTEGER, login_timeout),

  ENV_ENTRY("kbd", ENV_LEDS, leds),
  ENV_ENTRY("keyboard", ENV_LEDS, leds),

  { NULL, 0, 0 }
};



/* parse_binary:
 *  read a string and return TRUE|FALSE|-1
 */
static int 
parse_binary(const char *str)
{
  if (str == NULL)
    return(TRUE);

  if (strcasecmp(str,"no") == 0)
    return(FALSE);

  if (strcasecmp(str,"yes") == 0)
    return(TRUE);

  if (strlen(str) == 1)
    {
      if (*str == '0' || 
        *str == 'N' || 
        *str == 'n')
      return(FALSE);

      if (*str == '1' || 
        *str == 'Y' || 
        *str == 'y')
        return(TRUE);
    }

  return(-1);
}


static int option_leds(const char *value, unsigned int *ptr)
{
  if (leds_parse(value, ptr) == -1)
    return -1;

  return 0;
}

static int option_string(const char *value, char **ptr)
{
  if (*ptr != NULL) 
    free(*ptr); /* cancel a previously set value */

  *ptr = strdup(value);

  if (*ptr == NULL)
    return -1;

  return(0);
}

static int option_integer(const char *value, int *ptr)
{
  *ptr = strtol(value, NULL, 0);

  return(0);
}

/* env_binary:
 *  set an 'int' pointed by ptr according to value
 *  return 0 or -1
 */
static int option_binary(const char *value, int *ptr)
{
  *ptr = parse_binary(value);

  if (*ptr == -1)
    return(-1);

  return 0;
}

/* parse_environment:
 *  read all known variable
 */
static int 
parse_environment(void)
{
  int i;
  char *value;

  i = 0;
  while(env_options[i].name != NULL)
    {
      value = getenv(env_options[i].name);
      if (value != NULL)
      {
        switch(env_options[i].type)
          {
          case ENV_INTEGER:
            option_integer(value, (int *) ((unsigned char *) fgoptions_environment + env_options[i].offset));
            break;

          case ENV_STRING:
            option_string(value, (char **) ((unsigned char *) fgoptions_environment + env_options[i].offset));
            break;

          case ENV_BINARY:
            if (option_binary(value, (int *) ((unsigned char *) fgoptions_environment + env_options[i].offset)) != -1)
            break;

          env_error:
            error("unexpected value for '%s' option: '%s'", env_options[i].name, value);
            return(-1);
            break;

          case ENV_LEDS:
            if (option_leds(value, (unsigned int *) ((unsigned char *) fgoptions_environment + env_options[i].offset)) == -1)
            goto env_error;
            break;
          }
      }

      i ++;
    }

  return(0);
}


static void
parse_cmdline(int argc, char *argv[])
{
  int count;
  int arg;

  int option_index = 0;
  int option = -1 ;

  /* Parse command line */
  do
    {
      option = getopt_long (argc, argv, SHORT_OPTIONS, long_options, &option_index);

      switch (option)
        {
        case OPTION_VERSION:
          show_version = 1;
        continue;

        case OPTION_HELP:
          show_help = 1;
          continue;

      case OPTION_COMPILE:
          show_compile = 1;
          continue;

        case OPTION_DUMP:
          show_config = 1;
          continue;

      case OPTION_TIMEOUT:
          option_integer(optarg, &fgoptions_options->login_timeout); /* convert timeout */
          continue;

      case OPTION_REFRESH:
          option_integer(optarg, &fgoptions_options->issue_refresh);  /* convert refresh */
          continue;

      case OPTION_PROMPT:
          option_string(optarg, &fgoptions_options->login_prompt);  /* login prompt */
          continue;

      case OPTION_PROGRAM:
          option_string(optarg, &fgoptions_options->login_program);  /* login program */
          continue;

      case OPTION_ISSUE:
          option_string(optarg, &fgoptions_options->issue_filename);  /* issue file */
          continue;

#ifdef USE_FRAME_BUFFER
      case OPTION_FB:
          option_string(optarg, &fgoptions_options->fb_device);  /* frame buffer device */
          continue;
#endif

      case OPTION_TTY:
          option_string(optarg, &fgoptions_options->tty_device);  /* tty device */
          continue;

      case OPTION_CLEAR:
        if (option_binary(optarg, &fgoptions_options->screen_clear) == -1)
          goto option_error;
        continue;
        
      case OPTION_KBD:
        if (option_leds(optarg, &fgoptions_options->leds) != -1)
          continue;

        /* print an error */
      option_error:
        fprintf(stderr,"%s: syntax error in argument of option --%s=%s\n",
              program_invocation_name,
              long_options[option_index].name,
              optarg);
        show_error = 1;
        return;

        case EOF: /* -1 */
          break;

        case '?': /* unknown option */
          show_error = 1;
          return;

        case ':':
          fprintf (stderr, "Missing argument\n");
          show_error = 1;
          return;

        default: /* unhandled options */
#ifdef FB_GETTY_DEBUG
          error ("%s:%i Error in getopt_long : %c", __FILE__, __LINE__, option);
#endif
          break;
        }
    }
  while(option != EOF && show_error == 0);

  /*
   * Get the arguments 
   */
#ifdef FB_GETTY_DEBUG
  error(" parsing arguments");
#endif

  count = 0;
  for (arg = optind; arg < argc; arg ++)
    {
      if (strchr(argv[arg],'=') != NULL)
      { 
        putenv(argv[arg]);
        continue;
      }

      switch(count)
      {
      case 0: 
        option_string(argv[arg], &fgoptions_arguments->tty_device);
        count++;
        continue;
        
#ifdef USE_FRAME_BUFFER           
      case 1:
        option_string(argv[arg], &fgoptions_arguments->fb_device);
        count++;
        continue;
#endif /* USE_FRAME_BUFFER */

      default:
        fprintf(stderr, "unknown argument '%s'\n",argv[arg]);
        show_error = 1;
        return;
        
      }
    }
}

/* parse_options
 *  read all form of configuration for fbgetty
 *
 */
void 
parse_options (int argc, char *argv[])
{
  struct stat st;
  char *dev_name;
  char *issue_name;
  char *language;
  char *p;

  /* create the temporaly structures */
  fgoptions_arguments = fgoptions_create();
  fgoptions_options = fgoptions_create(); 
  fgoptions_environment = fgoptions_create();
 
#ifdef FB_GETTY_DEBUG
  error(" parsing options");
#endif

  /* parse the cmdline */
  parse_cmdline(argc, argv);

  /* those value are only used for cmdline */
  if (show_error)
    usage ();

  if (show_help)
    help();

  if (show_version)
    version ();

  if (show_compile)
   compile ();

  /* 
   * Get parameter from environment 
   */
#ifdef FB_GETTY_DEBUG
  error(" parsing environment");
#endif

  /* read the environment */
  parse_environment();
 
#ifdef FB_GETTY_DEBUG
  error(" merging differents options");
#endif

  /* merge all different kind of options */
  merge_options();

  /* free the structures */
  free(fgoptions_free(fgoptions_environment));
  free(fgoptions_free(fgoptions_arguments));
  free(fgoptions_free(fgoptions_options));

#ifdef FB_GETTY_DEBUG
  error("Analizing options");
#endif

  if (fgoptions->issue_filename != NULL && 
      strcasecmp(fgoptions->issue_filename,"none") == 0)
    {
      free(fgoptions->issue_filename);
      fgoptions->issue_filename=NULL;
    }
  
  if (fgoptions->login_prompt != NULL
      && strcasecmp(fgoptions->login_prompt,"none") == 0)
    {
      free(fgoptions->login_prompt);
      fgoptions->login_prompt=NULL;
    }
  
  if (fgoptions->login_timeout < 0)
    error("Invalid login timeout");
   
  if (fgoptions->issue_refresh < 0)
    error("Invalid issue refresh interval");

#ifdef FB_GETTY_DEBUG
  {
    int count;

    count = 0;
    while (environ[count] != NULL)
      error("%s",environ[count++]);
    
    error("options parsing finish");
    
    error("Options :");
    error("tty device    : %s",fgoptions->tty_device);
#ifdef USE_FRAME_BUFFER
    error("fb device     : %s",fgoptions->fb_device);
#endif
    error("login program : %s",fgoptions->login_program);
    error("login prompt  : %s",fgoptions->login_prompt);
    error("login timeout : %d",fgoptions->login_timeout);
    error("issue file    : %s",fgoptions->issue_filename);
    error("issue refresh : %d",fgoptions->issue_refresh);
    error("screen clear  : %d",fgoptions->screen_clear);
  }
#endif
  
  if (fgoptions->tty_device  == NULL)
    {
      fprintf(stderr,"You must specify a tty device\n");
      usage();
    }

  /* show the current configuration, used for debugging purpose 
   *  could be used to generate a template for a configuration file
   */
  if (show_config)
    dump_config();

  if (*(fgoptions->tty_device) != '/')
    {
      dev_name = fgoptions->tty_device; /* save the device name */
      /* allocate memory for new tty_device
       * /dev/[tty_device] (about 11 characters long)
       */
      fgoptions->tty_device = (char *) malloc((strlen(_PATH_DEV) + 1 + strlen(dev_name) + 1) * sizeof(char));
      if (fgoptions->tty_device != NULL)
      {
        sprintf(fgoptions->tty_device,"%s/%s",_PATH_DEV, dev_name);
        free(dev_name);
      }
      else
      {
        fatal_error("cannot allocate memory for device name");
      }
    }

  /* resolve the device name */
  dev_name = canonicalize_filename(fgoptions->tty_device);
  if (dev_name != NULL)
    {
      free(fgoptions->tty_device);
      fgoptions->tty_device = dev_name;
    }
  
#ifdef USE_FRAME_BUFFER
  if (fgoptions->fb_device != NULL)
    {
      if (*(fgoptions->fb_device) != '/')
        {
          dev_name = fgoptions->fb_device; /* save the device name */
          /* allocate memory for new fb_device
           * /dev/[fb_device] (about 11 characters long)
           */
          fgoptions->fb_device = (char *) malloc((strlen(_PATH_DEV) + 1 + strlen(dev_name) + 1) * sizeof(char));
        if (fgoptions->fb_device != NULL)
          {
            sprintf(fgoptions->fb_device,"%s/%s",_PATH_DEV,dev_name);
            free(dev_name);
          }
        else
          {
            fatal_error("cannot allocate memory for device name");
          }
        }

      dev_name = canonicalize_filename(fgoptions->fb_device);
      if (dev_name != NULL)
      {
        free(fgoptions->fb_device);
        fgoptions->fb_device = dev_name;
      }
    }
#endif

  /* locale issue handling */
  language = getenv("LANG");
  if (language != NULL)
    language = strdup(language);

  while (language != NULL)
    {
      issue_name = fgoptions->issue_filename; /* save the issue name */
      /*
       * allocate memory for new issue file
       */
      fgoptions->issue_filename = (char *) malloc((strlen(issue_name) + 1 + strlen(language) + 1) * sizeof(char));
      sprintf(fgoptions->issue_filename,"%s.%s",issue_name,language);

      /* then verify the existence of this file */
      if (stat (fgoptions->issue_filename, &st) == -1)
        {
          free(fgoptions->issue_filename);
          fgoptions->issue_filename = issue_name;

        /* handle LANG=fr_FR
         *  first try the full name, after try the short name : LANG=fr
         */
        p = strchr(language, '_');
        if (p == NULL)
          {
            /* not in form fr_FR */
            free(language);
            language = NULL;
          }
        else
          *p = '\0'; /* cut to the major */
        }
      else
      {
        /* found */
        free(issue_name);
        free(language);
        language = NULL;
      }
    }

}

static void
dump_config(void)
{
  printf("# Options for fbgetty\n");
  printf("tty_device= %s\n",fgoptions->tty_device ? fgoptions->tty_device : "none");
#ifdef USE_FRAME_BUFFER
  printf("fb_device= %s\n",fgoptions->fb_device ? fgoptions->fb_device : "none" );
#endif
  printf("clear_screen= %s\n",fgoptions->screen_clear ? "yes" : "no");
  printf("issue_filename= %s\n",fgoptions->issue_filename ? fgoptions->issue_filename : "none");
  printf("issue_refresh= %d\n",fgoptions->issue_refresh);
  printf("login_prompt= %s\n",fgoptions->login_prompt ? fgoptions->login_prompt : "none");
  printf("login_hide= %s\n",fgoptions->login_hide ? "yes" : "no");
  printf("login_timeout= %d\n",fgoptions->login_timeout);
  printf("login_program= %s\n",fgoptions->login_program ? fgoptions->login_program : "none");

  printf("leds = %d\n", fgoptions->leds);

#if 0
  /* for the future, perhaps */
  printf("config_filename= %s\n",fgoptions->config_filename ? fgoptions->config_filename : "none");
  printf("modeb_filename= %s\n",fgoptions->modedb_filename ? fgoptions->modedb_filename : "none");
#endif

  fgexit(EXIT_SUCCESS);
}


static void help(void)
{
  fprintf(stdout,
        "Usage: %s [options] [tty]"
#ifdef USE_FRAME_BUFFER
        " [framebuffer]"
#endif
        "\n"
        "\n"
        "with options in\n"
        "  -t, --tty=TTY                use tty device `TTY'\n"
#ifdef USE_FRAME_BUFFER
        "  -f, --fb=FB\n"
        "      --framebuffer=FB         use frame buffer device `FB'\n"
#endif
        "      --clear-screen=[no|yes]  clear screen when launched\n"
        "      --kbd=[flag,...]\n"
        "      --keyboard=[flag,...]    set the keyboard mode\n"
        "                               flags could be num,caps with\n"
        "                               modifiers + and -\n"
        "  -i, --issue=ISSUE            display ISSUE\n"
        "  -l, --login-program=LOGIN    use LOGIN program\n"
        "  -p, --login-prompt=PROMPT    use login PROMPT\n"
        "  -o, --login-timeout=SECONDS  set login timeout to SECONDS\n"
        "      --dump-config            show the current config variables\n"
        "      --compile                display compilation information\n"
        "      --help                   display this help and exit\n"
        "      --version                display version information and exit\n"
        "\n"
        "Report bugs, comment, or what you want to " PACKAGE_MAIL "\n"
        "\n", program_invocation_short_name);

  fgexit(EXIT_SUCCESS);
}


static void 
usage (void)
{
  fprintf (stderr, "Try `%s --help' for more information.\n", program_invocation_short_name);

  fgexit (EXIT_SUCCESS);
}

static void 
version (void)
{
  fprintf(stdout,
        PACKAGE_NAME " version " PACKAGE_VERSION
#ifdef PACKAGE_NICKNAME
        " (" PACKAGE_NICKNAME ")"
#endif
        "\n"
        "Copyright (C) 1999 2000 2001 " PACKAGE_AUTHOR "\n"
        "This is free software, and you are welcome to redistribute it under\n"
        "the GNU General Public License.\n"
        PACKAGE_NAME " comes with ABSOLUTELY NO WARRANTY.\n"
        "\n"
        "see info page or man page for more information\n"
        "go to " PACKAGE_HOMEPAGE " for new release\n"
        "\n");

  fgexit(EXIT_SUCCESS);
}
 
static void 
compile (void)
{
  printf ("%s version %s compilation informations\n", 
                  PACKAGE_NAME, PACKAGE_VERSION);

#ifdef BUILD_USER
  printf("\n"
       "compiled by         : " BUILD_USER);
#ifdef BUILD_HOSTNAME
  printf("@" BUILD_HOSTNAME);
#endif
#endif

#ifdef __DATE__
  printf("\n"
       "compile date        : " __DATE__ " " __TIME__ );
#endif

#ifdef TARGET_SYSTEM
  printf("\n"
       "target              : " TARGET_SYSTEM ); 
#endif 

#ifdef __linux__
#include <linux/version.h>
#ifdef UTS_RELEASE
  printf("\n"
       "kernel version      : " UTS_RELEASE);
#endif
#endif

#ifdef __GNUC__
  printf("\n"
       "C compiler          : GNU CC " __VERSION__);
#endif

#ifdef __GLIBC__
  printf("\n"
       "C library           : GNU C library %d.%d", __GLIBC__, __GLIBC_MINOR__);
#endif

  printf("\n\n" "Configuration defaults:\n");

  /* framebuffer */
  printf("\n"
       "framebuffer support      : ");

#ifdef USE_FRAME_BUFFER
  printf("enabled");
#else
  printf("disabled");
#endif

  /* framebuffer */
  printf("\n"
       "virtual terminal\n"
       "switching support        : ");
#ifdef USE_VT_SWITCHING
  printf("enabled");
#else
  printf("disabled");
#endif

  /* Debug support */
  printf("\n"
       "debug support (verbose)  : ");
#ifdef FB_GETTY_DEBUG
  printf("enabled");
#else
  printf("disabled");
#endif
  printf("\n"
       "wait for debugger        : ");
#ifdef DEBUGGER_SUPPORT
  printf("enabled");
#else
  printf("disabled");
#endif


  /* Exec support */
  printf("\n"
       "exec support             : ");
#ifdef USE_EXEC_SUPPORT
  printf("enabled");

  printf("\n"
       "secure exec support      : ");
# ifdef USE_SECURE_MODE
  printf("enabled");

#  ifdef SECURE_USERNAME
  printf("\n" " secure user name  : %s", SECURE_USERNAME);
#  endif
#  ifdef SECURE_GROUPNAME
  printf("\n" " secure group name : %s", SECURE_GROUPNAME);
#  endif
#  ifdef SECURE_USER
  printf("\n" " secure user       : %d", SECURE_USER);
#  endif
#  ifdef SECURE_GROUP
  printf("\n" " secure group      : %d", SECURE_GROUP);
#  endif

# else /* !USE_SECURE_MODE */
  printf("disabled");
# endif /* !USE_SECURE_MODE */

#else /* !USE_EXEC_SUPPORT */
  printf("disabled");
#endif /* !USE_EXEC_SUPPORT */

  printf("\n" 
       "default issue file       : %s", ISSUE_FILE);

  printf("\n" 
       "login login prompt file  : \"%s\"", LOGIN_PROMPT);

  printf("\n" 
       "login login program      : %s", LOGIN_PROGRAM);

  puts("\n");

  fgexit(EXIT_SUCCESS);
}


/*
 * Merge functions
 *  merge the different fbgetty_options_t structure in one
 */

#define MERGE_STR (1 << 0)
#define MERGE_INT (1 << 1)

static struct merge_option
{
  unsigned long offset;
  int type;
  char *ptr; /* MERGE_STR */
  int value; /* MERGE INT */
} 
merge_option_list[] = 
{
  { OFFSET_tty_device ,    MERGE_STR, NULL, -1 },
#ifdef USE_FRAME_BUFFER
  { OFFSET_fb_device,      MERGE_STR, NULL, -1 },
#endif

  { OFFSET_login_program,  MERGE_STR, LOGIN_PROGRAM, -1 },
  { OFFSET_login_prompt,   MERGE_STR, LOGIN_PROMPT, -1 },
  { OFFSET_issue_filename, MERGE_STR, ISSUE_FILE, -1 },

  { OFFSET_login_timeout,  MERGE_INT, NULL, LOGIN_TIMEOUT },
  { OFFSET_issue_refresh,  MERGE_INT, NULL, ISSUE_REFRESH },
  { OFFSET_screen_clear,   MERGE_INT, NULL, TRUE },

  { OFFSET_leds,           MERGE_INT, NULL, 0 },
  { 0, 0, NULL, -1 }
};

static char *
merge_option_str(fbgetty_options_t *options[], unsigned long offset, 
             char *clear, char *deflt)
{
  char **string;

  int i;
  
  for(i = 0; options[i] != NULL; i++)
    {
      string = (char **) ((unsigned char *) options[i] + offset);
      if (*string != clear)
      return *string;
    }

  return deflt;
}

static int
merge_option_int(fbgetty_options_t *options[], unsigned long offset, 
             int clear, int deflt)
{
  int *integer;

  int i;
  
  for(i = 0; options[i] != NULL; i++)
    {
      integer = (int *) ((unsigned char *) options[i] + offset);
      if (*integer != clear)
      return *integer;
    }

  return deflt;
}

/* merge_options:
 *  merge all type of option...
 */
static int 
merge_options(void)
{
  int i;

  char **string;
  int *integer;

  for(i = 0; merge_option_list[i].type != 0; i++)
    {
      switch(merge_option_list[i].type)
      {
      case MERGE_STR:
        string = (char **) ((unsigned char *) fgoptions + merge_option_list[i].offset);
        *string = merge_option_str (fgoptions_parsed, merge_option_list[i].offset,
                               NULL, merge_option_list[i].ptr);
        if (*string != NULL)
          *string = strdup(*string);
        break;

      case MERGE_INT: 
        integer = (int *) ((unsigned char *) fgoptions + merge_option_list[i].offset);
        *integer = merge_option_int (fgoptions_parsed, merge_option_list[i].offset,
                               -1, merge_option_list[i].value);
        break;

      default:
        error("Houston, we have a problem here !");
        return(-1);
        break;
      }
    }

  return(0);
}

/* fgoptions_create:
 *  allocate a new fgoption structure
 */
fbgetty_options_t *
fgoptions_create(void)
{
  fbgetty_options_t *fgop;  
  
  fgop = (fbgetty_options_t *) malloc(sizeof(struct fbgetty_options_t));
  if (fgop == NULL)
    fatal_error("can't allocate memory to fbgetty config");
  
  fgoptions_init(fgop);

  return(fgop);
}


/* fgoptions_init:
 *  reset an fgoptions structure
 */
int
fgoptions_init(fbgetty_options_t *op)
{
#define FGINIT_INT(name) op->name = -1  
#define FGINIT_STR(name) 

  memset(op, 0x00, sizeof (fbgetty_options_t));

  FGINIT_INT(master);

  FGINIT_STR(tty_device);
  FGINIT_INT(tty_fd);
  FGINIT_INT(tty_number);

#ifdef USE_FRAME_BUFFER
  FGINIT_STR(fb_device);
  FGINIT_INT(fb_fd);
  FGINIT_INT(fb_number);
#endif

  FGINIT_INT(screen_clear);
  FGINIT_STR(issue_filename); 
  FGINIT_INT(issue_refresh);
  FGINIT_STR(login_prompt);

  FGINIT_INT(login_hide);
  FGINIT_INT(login_timeout);

  FGINIT_STR(login_program);
  FGINIT_STR(login_name);

  FGINIT_INT(login_name_valid);

  /* set/clear leds states */
  FGINIT_INT(leds);

  return(0);

#undef FGINIT_INT
#undef FGINIT_STR
}


/*
 * fgoptions_free: free the contents of the structure
 * return the structure.
 */
fbgetty_options_t *
fgoptions_free(fbgetty_options_t *op)
{
#define FGFREE(name)   \
if (op->name != NULL)  \
  {                    \
    free(op->name);    \
    op->name = NULL;   \
  }
  
#ifdef USE_FRAME_BUFFER
  FGFREE(fb_device);
#endif
 
  FGFREE(tty_device);
  FGFREE(issue_filename);
  FGFREE(login_prompt);
  FGFREE(login_program);
  FGFREE(login_name);

  return(op);

#undef FGFREE
}

Generated by  Doxygen 1.6.0   Back to index