Repository navigation
Expand file tree
/
Copy pathconfig.c
More file actions
122 lines (114 loc) · 3.76 KB
/
Copy pathconfig.c
File metadata and controls
122 lines (114 loc) · 3.76 KB
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
#include "config.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *trim(char *s) {
char *end;
while (isspace((unsigned char)*s)) s++;
end = s + strlen(s);
while (end > s && isspace((unsigned char)end[-1])) end--;
*end = '\0';
return s;
}
static int set_value(char **destination, const char *value) {
char *copy = strdup(value);
if (!copy) return -1;
free(*destination);
*destination = copy;
return 0;
}
int load_settings(const char *path, struct settings *out) {
FILE *file;
char line[4096];
memset(out, 0, sizeof(*out));
file = fopen(path, "r");
if (!file) return -1;
while (fgets(line, sizeof(line), file)) {
char *key = trim(line), *equals, *value;
if (*key == '\0' || *key == '#') continue;
equals = strchr(key, '=');
if (!equals) goto invalid;
*equals = '\0';
value = trim(equals + 1);
key = trim(key);
if (strcmp(key, "address") == 0) {
if (set_value(&out->address, value) < 0) goto invalid;
} else if (strcmp(key, "port") == 0) {
if (set_value(&out->port, value) < 0) goto invalid;
} else if (strcmp(key, "password") == 0) {
if (set_value(&out->password, value) < 0) goto invalid;
} else if (strcmp(key, "commands_file") == 0) {
if (set_value(&out->commands_file, value) < 0) goto invalid;
}
}
fclose(file);
if (!out->port || !out->password || !out->commands_file) goto invalid_closed;
return 0;
invalid:
fclose(file);
invalid_closed:
free_settings(out);
return -1;
}
void free_settings(struct settings *s) {
free(s->address); free(s->port); free(s->password); free(s->commands_file);
memset(s, 0, sizeof(*s));
}
int load_commands(const char *path, struct command_list *out) {
FILE *file;
char line[4096];
memset(out, 0, sizeof(*out));
file = fopen(path, "r");
if (!file) return -1;
while (fgets(line, sizeof(line), file)) {
char *name = trim(line), *equals, *token, *save = NULL;
struct command *command;
size_t argc = 0;
if (*name == '\0' || *name == '#') continue;
if (out->count == MAX_COMMANDS) goto invalid;
equals = strchr(name, '=');
if (!equals) goto invalid;
*equals = '\0';
name = trim(name);
if (*name == '\0' || strchr(name, ' ') || find_command(out, name)) goto invalid;
command = &out->items[out->count];
command->name = strdup(name);
if (!command->name) goto invalid;
token = strtok_r(trim(equals + 1), " \t", &save);
if (token && strcmp(token, "@stream") == 0) {
command->stream = 1;
token = strtok_r(NULL, " \t", &save);
}
while (token && argc < MAX_ARGS) {
command->argv[argc] = strdup(token);
if (!command->argv[argc]) goto invalid;
argc++;
token = strtok_r(NULL, " \t", &save);
}
if (argc == 0 || token != NULL) goto invalid;
command->argv[argc] = NULL;
out->count++;
}
fclose(file);
return 0;
invalid:
fclose(file);
free_commands(out);
return -1;
}
void free_commands(struct command_list *commands) {
size_t i, j;
for (i = 0; i <= commands->count && i < MAX_COMMANDS; i++) {
free(commands->items[i].name);
for (j = 0; j < MAX_ARGS; j++) free(commands->items[i].argv[j]);
}
memset(commands, 0, sizeof(*commands));
}
const struct command *find_command(const struct command_list *commands,
const char *name) {
size_t i;
for (i = 0; i < commands->count; i++)
if (strcmp(commands->items[i].name, name) == 0) return &commands->items[i];
return NULL;
}