Add system-wide config support for wsssht with proper precedence

- Update read_config_value_from_file() to support config precedence:
  1. ~/.config/wsssh/wssht.conf (user config)
  2. /etc/wsssht.conf (system config)
- Update man page to document config file precedence order
- Command line options still have highest priority
parent 28dccf5b
......@@ -108,9 +108,20 @@ Press Ctrl+C to close the tunnel and exit.
.RE
.SH CONFIGURATION
.B wsssht
supports a configuration file at
supports configuration files with the following precedence order:
.RS
.IP 1. 3
Command line options (highest priority)
.IP 2. 3
User configuration:
.I ~/.config/wsssh/wssht.conf
with the following options:
.IP 3. 3
System configuration:
.I /etc/wsssht.conf
(lowest priority)
.RE
.PP
Configuration options:
.PP
.RS
.nf
......@@ -130,10 +141,15 @@ Note: Unlike
and
.BR wsscp (1),
.B wsssht
uses its own configuration file
uses its own configuration files
.I wssht.conf
instead of sharing
.I wsssh.conf.
System administrators can provide default settings in
.I /etc/wsssht.conf
which will be overridden by user settings in
.I ~/.config/wsssh/wssht.conf
and command line options.
.SH SEE ALSO
.BR wsssh (1),
.BR wsscp (1),
......
......@@ -92,47 +92,96 @@ char *read_config_value(const char *key) {
}
char *read_config_value_from_file(const char *key, const char *config_file) {
char *result = NULL;
// First try user config: ~/.config/wsssh/{config_file}.conf
char *home = getenv("HOME");
if (!home) return NULL;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/.config/wsssh/%s.conf", home, config_file);
FILE *f = fopen(path, "r");
if (!f) return NULL;
char line[256];
char section[64] = "";
while (fgets(line, sizeof(line), f)) {
// Check for section headers
if (line[0] == '[') {
sscanf(line, "[%63[^]]", section);
continue;
if (home) {
char user_path[PATH_MAX];
snprintf(user_path, sizeof(user_path), "%s/.config/wsssh/%s.conf", home, config_file);
FILE *f = fopen(user_path, "r");
if (f) {
char line[256];
char section[64] = "";
while (fgets(line, sizeof(line), f)) {
// Check for section headers
if (line[0] == '[') {
sscanf(line, "[%63[^]]", section);
continue;
}
// Skip comments and empty lines
if (line[0] == '#' || line[0] == ';' || line[0] == '\n') continue;
char *equals = strchr(line, '=');
if (equals) {
*equals = '\0';
char *config_key = line;
char *value = equals + 1;
// Trim whitespace
while (*config_key == ' ' || *config_key == '\t') config_key++;
char *end = config_key + strlen(config_key) - 1;
while (end > config_key && (*end == ' ' || *end == '\t')) *end-- = '\0';
while (*value == ' ' || *value == '\t') value++;
end = value + strlen(value) - 1;
while (end > value && (*end == ' ' || *end == '\t' || *end == '\n')) *end-- = '\0';
// Check if key matches
if (strcmp(config_key, key) == 0) {
result = strdup(value);
break;
}
}
}
fclose(f);
}
// Skip comments and empty lines
if (line[0] == '#' || line[0] == ';' || line[0] == '\n') continue;
char *equals = strchr(line, '=');
if (equals) {
*equals = '\0';
char *config_key = line;
char *value = equals + 1;
// Trim whitespace
while (*config_key == ' ' || *config_key == '\t') config_key++;
char *end = config_key + strlen(config_key) - 1;
while (end > config_key && (*end == ' ' || *end == '\t')) *end-- = '\0';
while (*value == ' ' || *value == '\t') value++;
end = value + strlen(value) - 1;
while (end > value && (*end == ' ' || *end == '\t' || *end == '\n')) *end-- = '\0';
}
// Check if key matches (case-insensitive for section names)
if (strcmp(config_key, key) == 0) {
fclose(f);
return strdup(value);
// If not found in user config, try system config: /etc/{config_file}.conf
if (!result) {
char system_path[PATH_MAX];
snprintf(system_path, sizeof(system_path), "/etc/%s.conf", config_file);
FILE *f = fopen(system_path, "r");
if (f) {
char line[256];
char section[64] = "";
while (fgets(line, sizeof(line), f)) {
// Check for section headers
if (line[0] == '[') {
sscanf(line, "[%63[^]]", section);
continue;
}
// Skip comments and empty lines
if (line[0] == '#' || line[0] == ';' || line[0] == '\n') continue;
char *equals = strchr(line, '=');
if (equals) {
*equals = '\0';
char *config_key = line;
char *value = equals + 1;
// Trim whitespace
while (*config_key == ' ' || *config_key == '\t') config_key++;
char *end = config_key + strlen(config_key) - 1;
while (end > config_key && (*end == ' ' || *end == '\t')) *end-- = '\0';
while (*value == ' ' || *value == '\t') value++;
end = value + strlen(value) - 1;
while (end > value && (*end == ' ' || *end == '\t' || *end == '\n')) *end-- = '\0';
// Check if key matches
if (strcmp(config_key, key) == 0) {
result = strdup(value);
break;
}
}
}
fclose(f);
}
}
fclose(f);
return NULL;
return result;
}
void print_trans_flag(void) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment