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

config.c

/*
 * In this file is the stuff related to configuration, such as command
 * line parsing and config file parsing.
 *
 * This file was previously called startup.c.
 */

#include "ledd.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <getopt.h>

/* HELPTEXT and VERSIONTEXT */
#include "help.h"


static void config_parse(options *opts,gchar *file);
static void config_add_file(GSList *list,gchar *name,gint type);


/*
 * Parse command line options and, if not overriden, read the configuration
 * files.
 */
void config_cmdline(options *opts,int argc,char **argv) {
      signed char c;
      gint config_parsed=0;
/* Long args that have no short arg: */
#define ARG_PIDFILE 1
      struct option longopts[] = {
            {"help",no_argument,NULL,'h'},
            {"version",no_argument,NULL,'v'},
            {"config",required_argument,NULL,'c'},
            {"pipe",required_argument,NULL,'p'},
            {"daemon",no_argument,NULL,'d'},
            {"no-daemon",no_argument,NULL,'D'},
            {"startup",required_argument,NULL,'s'},
            {"pidfile",required_argument,NULL,ARG_PIDFILE}};


      while((c=getopt_long(argc,argv,"hvVc:p:dDs:",longopts,NULL))!=EOF) {
            switch (c) {
            case 0:
                  break;
            case 'h':
                  fprintf(stdout,HELPTEXT);
                  exit(0);
            case 'v':
            case 'V':
                  fprintf(stdout,VERSIONTEXT);
                  exit(0);
            case 'c':
                  config_parse(opts,optarg);
                  config_parsed=1;
                  break;
            case 'p':
                  config_add_file(opts->pipes,optarg,TYPE_CMDLINE);
                  break;
            case 'd':
                  if (abs(opts->daemon)>=2)
                        G_ERROR("only one -d or -D allowed");

                  opts->daemon=2;  /* config_parse won't change it */
                  break;
            case 'D':
                  if (abs(opts->daemon)>=2)
                        G_ERROR("only one -d or -D allowed");

                  opts->daemon=-2; /* config_parse won't change it */
                  break;
            case 's':
                  config_add_file(opts->startup,optarg,TYPE_CMDLINE);
                  break;
            case ARG_PIDFILE:
                  if (opts->pidfile->type==TYPE_CMDLINE)
                        G_ERROR("only one pidfile can be defined");

                  if (opts->pidfile->name)
                        g_free(opts->pidfile->name);
                  opts->pidfile->name=g_strdup(optarg);
                  opts->pidfile->type=TYPE_CMDLINE;
                  break;
            case '?':
                  fprintf(stderr,"Try %s -h for help.\n",argv[0]);
                  abort();
            }
      }
      if (optind < argc) {
            fprintf(stderr,"Trailing garbage on command line.\n");
            fprintf(stderr,"Try %s -h for help.\n",argv[0]);
            exit(1);
      }

      if (!config_parsed) {
            /* Is default config file readable */
            /* We don't want ledd running without any options anymore... */
            config_parse(opts,DEFAULTCONFIG_LEDD);
      }

      /* Default to syslog/stderr logging. */
      if (opts->logging->type==TYPE_NONE) {
#ifdef HAVE_SYSLOG
            opts->logging->type=TYPE_LOG_SYSLOG;
#else
            opts->logging->type=TYPE_LOG_STDERR;
#endif
      }

      return;
}





/*
 * Parses a configuration file and stores the stuff in opts.
 * If abs(opts->daemon)>=2, then it won't change that value.
 */
#define ERRORINFILE() G_ERROR("error in configuration file %s, line %d", \
                        file,lineno);
static void config_parse(options *opts,gchar *file) {
      gchar line[MAXPIECELENGTH*2];
      gchar buf[MAXPIECELENGTH];
      gchar *str;
      FILE *fp;
      gint lineno=0;
      gint i;

      if (parse_eol(file))
            return;
      if ((fp=fopen(file,"rt"))==NULL)
            G_ERROR("%s: %s",file,STRERROR);

      while (fgets(line,MAXPIECELENGTH*2,fp)) {
            lineno++;
            str=parse_jumpspace(line);
            if (str[0]=='#' || str[0]==0)
                  continue;
            str=parse_getpiece(str,buf);
            if (str==NULL)
                  ERRORINFILE();

            if (strcasecmp(buf,"tty")==0) {
                  /*** TTY LINE ***/   /* tty-change */
                  File *f;
                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  f=g_new0(File,1);
                  f->name=g_strdup(buf);
                  g_slist_append(opts->ttys,f);

            } else if (strcasecmp(buf,"fixtty")==0) {
                  /*** TTY FIX LINE ***/ /* tty-change */
                  File *f;
                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  f=g_new0(File,1);
                  f->name=g_strdup(buf);
                  g_slist_append(opts->fixttys,f);

            } else if (strcasecmp(buf,"daemon")==0) {
                  /*** DAEMON MODE ***/
                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  /* Add your favourite here: */
                  if (strcasecmp(buf,"yes")==0 ||
                      strcasecmp(buf,"y")==0 ||
                      strcasecmp(buf,"true")==0 ||
                      strcasecmp(buf,"on")==0 ||
                      strcasecmp(buf,"1")==0) {
                        if (abs(opts->daemon)<2)
                              opts->daemon=1;
                  } else if (strcasecmp(buf,"no")==0 ||
                           strcasecmp(buf,"n")==0 ||
                           strcasecmp(buf,"false")==0 ||
                           strcasecmp(buf,"off")==0 ||
                           strcasecmp(buf,"0")==0) {
                        if (abs(opts->daemon)<2)
                              opts->daemon=-1;
                  } else {
                        ERRORINFILE();
                  }

            } else if (strcasecmp(buf,"pipefile")==0) {
                  /*** PIPEFILE LINE ***/
                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  config_add_file(opts->pipes,buf,TYPE_CONFIG);

            } else if (strcasecmp(buf,"startup")==0) {
                  /*** STARTUP LINE ***/
                  str=parse_jumpspace(str);
                  for (i=strlen(str)-1; i>=0 && isspace(str[i]); i--)
                        ;
                  str[i+1]=0;

                  if (parse_eol(str))
                        ERRORINFILE();

                  config_add_file(opts->startup,str,TYPE_CONFIG);

            } else if (strcasecmp(buf,"pidfile")==0) {
                  /*** PIDFILE LINE ***/
                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  if (opts->pidfile->type==TYPE_CONFIG) {
                        g_warning("multiple pidfiles defined, "
                                "ignoring %s",buf);
                  } else if (opts->pidfile->type!=TYPE_CMDLINE) {
                        opts->pidfile->name=g_strdup(buf);
                        opts->pidfile->type=TYPE_CONFIG;
                  }
            } else if (strcasecmp(buf,"log")==0) {
                  /*** LOG LINE ***/
                  FileType t=TYPE_NONE;   /* Avoid warning from gcc */

                  str=parse_getpiece(str,buf);
                  if (str==NULL || !parse_eol(str))
                        ERRORINFILE();

                  if (strcasecmp(buf,"syslog")==0) {
#ifndef HAVE_SYSLOG
                        G_ERROR("syslog logging facility not available"
                              " (unavailable when compiling ledd)");
#endif
                        t=TYPE_LOG_SYSLOG;
                  } else if (strcasecmp(buf,"stderr")==0)
                        t=TYPE_LOG_STDERR;
                  else if (strcasecmp(buf,"none")==0)
                        t=TYPE_LOG_NONE;
                  else
                        ERRORINFILE();

                  if (opts->logging->type!=TYPE_NONE &&
                      t!=opts->logging->type) {
                        g_warning("multiple logging types defined, "
                                "ignoring \"%s\"",buf);
                  } else {
                        opts->logging->type=t;
                  }

            } else {
                  ERRORINFILE();
            }
      }
      fclose(fp);
      return;
}


/*
 * File STRUCTURE HANDLING ROUTINES:
 *
 * Handles the ->type variable as one of the following:
 *  TYPE_DEFAULT     A default setting 
 *  TYPE_CONFIG      Setting from config file 
 *  TYPE_CMDLINE     Setting from command line 
 * (from ledd.h)
 */

/*
 * Adds name into the list with ->type type. name is g_strdup'ed.
 */
static void config_add_file(GSList *list,gchar *name,gint type) {
      File *file;

      file=g_new(File,1);
      file->name=g_strdup(name);
      file->type=type;
      file->fd=-1;
      file->pid=0;
      g_slist_append(list,file);
      return;
}


/*
 * Remove all entries with ->type==type. We probably don't need this...
 */
#if 0
static void config_remove_file_type(GSList *list, gint type) {
      GSList *lst;

      for (lst=list; lst; lst=g_slist_next(lst)) {
            if (lst->data==NULL)
                  continue;
            if (((File *)lst->data)->type==type) {
                  /* This wastes a bit memory, but is much simpler...
                   * Just remember to check for NULL's everywhere. */
                  if (((File *)lst->data)->name)
                        g_free(((File *)lst->data)->name);
                  g_free(lst->data);  
                  lst->data=NULL;
            }
      }
      return;
}
#endif


Generated by  Doxygen 1.6.0   Back to index