📄 config.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 + -