Linux C代码实现读取配置文件示例

最近在看hostapd,该程序使用了conf配置文件,本文参考hostapd代码抽取出读取配置文件的示例,由于配置选项和业务密切相关,实际使用中仍需要做修改。

下面是代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
读配置文件示例
注:配置文件必须为unix格式,即\n结尾
*/

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

// 结构体
struct hostapd_config
{
char iface[16];
uint16_t beacon_int;

uint8_t channel;

char country[3]; /* first two octets: country code as described in
* ISO/IEC 3166-1. Third octet:
* ' ' (ascii 32): all environments
* 'O': Outdoor environemnt only
* 'I': Indoor environment only
*/
};

// 默认值
struct hostapd_config * config_defaults(void)
{
struct hostapd_config *conf = NULL;

conf = (struct hostapd_config *)calloc(1, sizeof(*conf));
if (conf == NULL)
{
return NULL;
}

// set default value
conf->beacon_int = 100;
conf->channel = 1;

return conf;
}

// 根据读取到的信息填充结构体
static int config_defaults(struct hostapd_config *conf, const char *buf, char *pos, int line)
{
if (strcmp(buf, "interface") == 0)
{
strncpy(conf->iface, pos, sizeof(conf->iface));
}
else if (strcmp(buf, "channel") == 0)
{
int val = atoi(pos);
conf->channel = val;
}
else if (strcmp(buf, "beacon_int") == 0)
{
int val = atoi(pos);
conf->beacon_int = val;
}
else if (strcmp(buf, "country_code") == 0)
{
memcpy(conf->country, pos, 2);
conf->country[2] = ' ';
}
// more ...
return 0;
}

//////////////////////////////////////
// 读配置文件
struct hostapd_config* config_read(const char *fname)
{
struct hostapd_config *conf = NULL;
FILE *f = NULL;
char buf[1024] = {0};
char *pos = NULL;
int line = 0;
int errors = 0;

f = fopen(fname, "r");
if (f == NULL)
{
printf("Could not open configuration file '%s' for reading.\n", fname);
return NULL;
}

conf = config_defaults();
if (conf == NULL)
{
fclose(f);
return NULL;
}

while (fgets(buf, sizeof(buf), f))
{
line++;

if (buf[0] == '#')
continue;
pos = buf;
while (*pos != '\0')
{
if (*pos == '\n')
{
*pos = '\0';
break;
}
pos++;
}
if (buf[0] == '\0')
continue;

pos = strchr(buf, '=');
if (pos == NULL) {
printf("Line %d: invalid line '%s'\n", line, buf);
errors++;
continue;
}
*pos = '\0';
pos++;
errors += config_defaults(conf, buf, pos, line);
}

fclose(f);

return conf;
}

/////////////////////////////////////

int main(int argc, char *argv[])
{
const char* conf_file = "foo.conf";

if (argc == 2)
{
conf_file = argv[1];
}

struct hostapd_config *conf = NULL;

conf = config_read(conf_file);
if (conf == NULL)
{
printf("failed to read file: %s\n", conf_file);
return -1;
}
printf("%d %s %s\n", conf->channel, conf->country, conf->iface);

return 0;
}

李迟 2016.8.21 周日