⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.c

📁 网络端口的服务程序
💻 C
字号:
/*
    Portserver - Use RTERM protocol to serve serial ports over a network
    Copyright (C) 1998 Kenn Humborg

    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; either version 2 of the License, or
    (at your option) any later version.

    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
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


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

#include "portserver.h"
#include "port.h"
#include "status.h"
#include "config.h"

struct global_config config;


static STATUS GetBooleanSetting(char *value, int *result);
static STATUS GetParitySetting(char *value, enum parity_types *result);
static STATUS TrimLine(FILE *file, char *line);
static STATUS GetConfigItem(FILE *file, char *file_name, int *line_num,
   char *item, int item_buf_len, char *value, int value_buf_len);


#define CONFIG_ITEM(item_name) (strcasecmp(item, item_name) == 0)
#define CONFIG_ERROR(msg) \
   syslog(LOG_WARNING, msg ": file %s, line %d", file_name, line_num);
#define CONFIG_ERROR_STATUS(msg, status) \
   syslog(LOG_WARNING, msg ": file %s, line %d: %s", \
             file_name, line_num, ErrorMsg(status));


STATUS ParseConfigFile(char *file_name)
{
   STATUS status;
   FILE *file;
   char item[1024];
   char value[1024];
   int line_num;
   struct Port *port;
   struct Port *new_port;
   int setting;
   int retval;
   int using_template;

   /* Until we get a 'port' line in the config file, all port
      settings get applied to the template port */
   port = FindPort(TEMPLATE_PORT_NAME);
   if (port == NULL) {
      syslog(LOG_ERR, "Cannot find template port");
      return ERR_NOTEMPLATE;
   }


   file = fopen(file_name, "r");
   if (file == NULL) {
      syslog(LOG_ERR, "Cannot open config file %s: %m", file_name);
      return ERR_OPENFILE;
   }

   line_num = 0;
   using_template = TRUE;

   while (1) {

      status = GetConfigItem(file, file_name, &line_num, item, sizeof(item),
                       value, sizeof(value));
      if (status == ERR_EOF) {
         break;
      } else if (IS_FAILURE(status)) {
         fclose(file);
         return status;
      }

      if CONFIG_ITEM("Port") {
         status = CreatePort(value, &new_port);
         if (IS_FAILURE(status)) {
            CONFIG_ERROR_STATUS("Unable to create new port entry", status);
            fclose(file);
            return status;
         }
         AddPort(new_port);
         port = new_port;
         using_template = FALSE;

      } else if CONFIG_ITEM("Device") {
         if (using_template) {
            CONFIG_ERROR("Device setting found before any Port setting");
            continue;
         }
         status = SetPortDevice(port, value);
         if (IS_FAILURE(status)) {
            CONFIG_ERROR_STATUS("Cannot set device name for port", status);
         }

      } else if CONFIG_ITEM("Description") {
         if (using_template) {
            CONFIG_ERROR("Description setting found before any Port setting");
            continue;
         }
         status = SetPortDescription(port, value);
         if (IS_FAILURE(status)) {
            CONFIG_ERROR_STATUS("Cannot set description for port", status);
         }

      } else if CONFIG_ITEM("TCPPort") {
         retval = sscanf(value, "%d", &config.tcp_port);
         if (retval != 1) {
            CONFIG_ERROR("Invalid TCPPort setting");
         }

      } else if CONFIG_ITEM("UUCPLock") {
         status = GetBooleanSetting(value, &setting);
         if (IS_FAILURE(status)) {
            CONFIG_ERROR("Invalid UUCPLock setting");
         } else {
            if (setting) {
               port->flags |= PORT_USELOCKFILE;
            } else {
               port->flags &= ~PORT_USELOCKFILE;
            }
         }

      } else if CONFIG_ITEM("Speed") {
         retval = sscanf(value, "%d", &port->speed);
         if (retval != 1) {
            CONFIG_ERROR("Invalid Speed setting");
         }

      } else if CONFIG_ITEM("DataBits") {
         retval = sscanf(value, "%d", &port->data_bits);
         if (retval != 1) {
            CONFIG_ERROR("Invalid DataBits setting");
         }

      } else if CONFIG_ITEM("StopBits") {
         retval = sscanf(value, "%d", &port->stop_bits);
         if (retval != 1) {
            CONFIG_ERROR("Invalid StopBits setting");
         }

      } else if CONFIG_ITEM("Parity") {
         status = GetParitySetting(value, &port->parity);
         if (IS_FAILURE(status)) {
            CONFIG_ERROR("Invalid Parity setting");
         }

      } else {
#if 0
         syslog(LOG_WARNING, "Unknown config item %s: file %s, line %d",
                   item, file_name, line_num);
#endif
      }
   }

   fclose(file);

   return SUCCESS;
}


static STATUS GetBooleanSetting(char *value, int *result)
{
   int status;
   int i;

   /* assume success */
   status = SUCCESS;

   if ((strcasecmp(value, "yes") == 0) || 
       (strcasecmp(value, "true") == 0)) {

      *result = TRUE;

   } else if ((strcasecmp(value, "no") == 0) ||
       (strcasecmp(value, "false") == 0)) {

      *result = FALSE;

   } else if (sscanf(value, "%d", &i) == 1) {
      if (i == 0) {
         *result = FALSE;
      } else {
         *result = TRUE;
      }
   } else {
      /* couldn't convert it */
      status = ERR_SYNTAX;
   }

   return status;
}


/* Return 0 if value successfully converted */

static int GetParitySetting(char *value, enum parity_types *result)
{
   STATUS status;

   /* assume success */
   status = SUCCESS;

   if ((strcasecmp(value, "none") == 0) || 
       (strcasecmp(value, "n") == 0)) {

      *result = none;

   } else if ((strcasecmp(value, "even") == 0) ||
       (strcasecmp(value, "e") == 0)) {

      *result = even;

   } else if ((strcasecmp(value, "odd") == 0) ||
       (strcasecmp(value, "o") == 0)) {

      *result = odd;

   } else if ((strcasecmp(value, "mark") == 0) ||
       (strcasecmp(value, "m") == 0)) {

      *result = mark;

   } else if ((strcasecmp(value, "space") == 0) ||
       (strcasecmp(value, "s") == 0)) {

      *result = space;

   } else {
      /* couldn't convert it */
      status = ERR_SYNTAX;
   }

   return status;
}
         


static STATUS TrimLine(FILE *file, char *line)
{
   int len;
   int c;

   len = strlen(line);

   if (line[len-1] == '\n') {
      line[len-1] = '\0';
      return SUCCESS;
   }

   while (1) {
      c = fgetc(file);
      if ((c == EOF) || (c == '\n')) {
         break;
      }
   }
   return ERR_LINETOOLONG;
}

static int GetConfigItem(FILE *file, char *file_name, int *line_num,
   char *item, int item_buf_len, char *value, int value_buf_len)
{
   char line[1024];
   int i;
   int end;
   int eq;
   int first_non_space;
   int item_end;
   int item_len;
   int value_start;
   int value_end;
   int value_len;

   while (!feof(file)) {
      if (fgets(line, sizeof(line), file) == NULL) {
         break;
      }

      (*line_num)++;

      if (TrimLine(file, line) == ERR_LINETOOLONG) {
         syslog(LOG_WARNING, "Line %d too long in config file %s",
                   *line_num, file_name);
      }


      /* first strip away any comment */
      end = strlen(line);
      for (i=0; i < end; i++) {
         if (line[i] == '#') {
            end = i;
            break;
         }
      }

      /* Are we left with just whitespace? */
      for (i=0; i<end; i++) {
         if (!isspace(line[i])) {
            first_non_space = i;
            break;
         }
      }
      if (i == end) {
         /* only whitespace */
         continue;
      }

      /* Now look for an equals sign */
      for (i=0; i < end; i++) {
         if (line[i] == '=') {
            break;
         }
      }
      eq = i;

      if (eq == end) {
         /* no equals sign */
         syslog(LOG_WARNING, "Missing '=' in file %s, line %d", 
                   file_name, *line_num);
         continue;
      }

      /* start at the first non-space and find the first space */
      item_end = eq;
      for (i=first_non_space; i<eq; i++) {
         if (isspace(line[i])) {
            item_end = i;
            break;
         }
      }
      if (item_end == eq) {
         /* no config item name */
         syslog(LOG_WARNING, "Missing config item in file %s, line %d", 
                   file_name, *line_num);
         continue;
      }

      /* We've isolated the config item part */

      item_len = item_end - first_non_space;
      if (item_len > item_buf_len - 1) {
         syslog(LOG_WARNING, "Config item too long in file %s, line %d", 
                   file_name, *line_num);
         continue;
      }

      strncpy(item, line + first_non_space, item_len); 
      item[item_len] = '\0';

      /* Now examine the value side */

      for (i=eq+1; i<end; i++) {
         if (!isspace(line[i])) {
            value_start = i;
            break;
         }
      }
      if (i == end) {
         syslog(LOG_WARNING, "Missing value in file %s, line %d", 
                   file_name, *line_num);
         continue;
      }

      value_end = end;
      for (i=end-1; i>value_start; i--) {
         if (!isspace(line[i])) {
            value_end = i+1;
            break;
         }
      }

      /* We've isolated the value part */

      value_len = value_end - value_start;
      if (value_len > value_buf_len - 1) {
         syslog(LOG_WARNING, "Config value too long in file %s, line %d", 
                   file_name, *line_num);
         continue;
      }

      strncpy(value, line + value_start, value_len); 
      value[value_len] = '\0';

      /* If we've gotten to here, we have a valid item=value pair */
      return SUCCESS;
   }

   return ERR_EOF;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -