| #include <ctype.h> |
| /* |
| * Simple ini file parser |
| * |
| * This should be copied from somewhere but, unfortunately is reinvented. |
| * |
| * Copyright (C) 2019 James.Bottomley@HansenPartnership.com |
| * |
| * SPDX-License-Identifier: LGPL-2.1-only |
| */ |
| |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <unistd.h> |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| |
| #include "openssl-pkcs11.h" |
| |
| #define BUF_SIZE 4096 |
| |
| static char *conf_buf = NULL; |
| static ssize_t conf_size; |
| static char *read_pos; |
| |
| static char *trim(char *line) |
| { |
| int len; |
| |
| while (isspace(*line)) |
| line++; |
| |
| len = strlen(line); |
| if (len == 0) |
| return line; |
| |
| for (--len; isspace(line[len]); --len) |
| ; |
| line[len + 1] = '\0'; |
| |
| return line; |
| } |
| |
| static char *read_line(void) |
| { |
| char *eol; |
| char *ret; |
| |
| eol = strchr(read_pos, '\n'); |
| ret = read_pos; |
| |
| if (!eol) |
| return NULL; |
| |
| *eol = '\0'; |
| read_pos = eol + 1; |
| |
| return ret; |
| } |
| |
| static void parse_mem(void) |
| { |
| char *line, *delim; |
| char *section = GLOBAL_SECTION, *key, *value; |
| |
| read_pos = conf_buf; |
| while ((line = read_line()) != NULL) { |
| int end; |
| |
| line = trim(line); |
| end = strlen(line) - 1; |
| if (line[0] == '#' || line[0] == '\0') |
| continue; |
| if (line[0] == '[' && line[end] == ']') { |
| line[end] = '\0'; |
| section = ++line; |
| continue; |
| } |
| delim = strchr(line, '='); |
| if (!delim) { |
| fprintf(stderr, "illegal line in config file '%s'\n", |
| line); |
| continue; |
| } |
| *delim = '\0'; |
| key = trim(line); |
| value = trim(delim + 1); |
| |
| cache_add(section, key, value, 0); |
| } |
| } |
| |
| int parse_ini_file(void) |
| { |
| char *home = getenv("HOME"); |
| char *conf = getenv(ENV_CONFIG); |
| char *end; |
| char config[PATH_MAX]; |
| int fd,len; |
| struct stat st; |
| |
| config[0] = '\0'; |
| if (conf) { |
| strncpy(config, conf, sizeof(config) - 1); |
| } else { |
| strncpy(config, home, sizeof(config) - 1); |
| strcat(config, "/"); |
| strcat(config, CONFIG_FILE); |
| } |
| |
| fd = open(config, O_RDONLY); |
| |
| if (fd < 0) { |
| fprintf(stderr, "failed to open config file %s: %s\n", |
| config, strerror(errno)); |
| return 0; |
| } |
| if (fstat(fd, &st)) { |
| fprintf(stderr, "failed to stat config file %s: %s\n", |
| config, strerror(errno)); |
| return 0; |
| } |
| conf_size = st.st_size; |
| if (conf_size == 0) { |
| fprintf(stderr, "conf file %s is empty\n", config); |
| return 0; |
| } |
| |
| conf_buf = malloc(conf_size + 2); |
| if (!conf_buf) { |
| fprintf(stderr, "failed to allocate %d bytes for con file %s\n", |
| (int)conf_size, config); |
| return 0; |
| } |
| |
| len = read(fd, conf_buf, conf_size); |
| if (len < 0) { |
| fprintf(stderr, "failed to read config file %s: %s\n", |
| config, strerror(errno)); |
| return 0; |
| } |
| if (len != conf_size) { |
| fprintf(stderr, "Config file %s changed while being read\n", |
| config); |
| free(conf_buf); |
| return 0; |
| } |
| close(fd); |
| |
| /* the parser requires the file end with a newline, |
| * so add one if needed */ |
| end = &conf_buf[conf_size - 1]; |
| if (*end++ != '\n') |
| *end++ = '\n'; |
| *end = '\0'; |
| parse_mem(); |
| cache_load_crypto_keys(); |
| return 1; |
| } |
| |
| void free_ini_file(void) |
| { |
| free(conf_buf); |
| } |