config.c (3630B)
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <fcntl.h> 5 #include <dirent.h> 6 #include <string.h> 7 #include <ini.h> 8 9 #include "util.h" 10 #include "config.h" 11 12 #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 13 14 int cfg_handler(void *user, const char *section, 15 const char *name, const char *value) 16 { 17 scout_cfg_t *pcfg = (scout_cfg_t *) user; 18 19 if (MATCH("menu", "name")) { 20 pcfg->name = strdup(value); 21 } else if (MATCH("theme", "bg")) { 22 int32_t color = parse_hex_color(value); 23 if (color >= 0) 24 pcfg->bg = convert_hex_color(color); 25 } else { 26 return 0; 27 } 28 29 return 1; 30 } 31 32 int card_handler(void *user, const char *section, 33 const char *name, const char *value) 34 { 35 scout_card_t *pcard = (scout_card_t *) user; 36 37 if (strcmp(section, "card") == 0) { 38 if (strcmp(name, "title") == 0) 39 pcard->title = strdup(value); 40 else if (strcmp(name, "description") == 0) 41 pcard->description = strdup(value); 42 else if (strcmp(name, "command") == 0) 43 pcard->command = strdup(value); 44 else if (strcmp(name, "image") == 0) 45 pcard->image_path = strdup(value); 46 else 47 return 0; 48 } else { 49 return 0; 50 } 51 52 return 1; 53 } 54 55 int is_ini(struct dirent *entry) 56 { 57 if (entry->d_type == DT_REG) { 58 size_t len_name = strlen(entry->d_name); 59 60 if (len_name < 5) { 61 return 0; 62 } 63 64 if (strcmp(entry->d_name + (len_name - 4), ".ini") == 0) { 65 return 1; 66 } 67 } 68 69 return 0; 70 } 71 72 /* 73 * Load and parse configuration from the configuration file. Values found in the 74 * config file will override the existing values in the passed configuration. 75 * > $XDG_CONFIG_HOME/scout/scout.ini 76 * 77 * Also load and parse card files in the configuration directory. 78 * > $XDG_CONFIG_HOME/scout/cards/card.ini 79 */ 80 void load_config(scout_cfg_t *pcfg, unsigned int *num_cards, 81 scout_card_t **pcards) 82 { 83 const char *path = getenv("XDG_CONFIG_HOME"); 84 if (!path) { 85 fprintf(stderr, "XDG_CONFIG_HOME not set\n"); 86 return; 87 } 88 89 int xdg_dir_fd = open(path, O_RDONLY | O_DIRECTORY); 90 if (xdg_dir_fd < 0) { 91 fprintf(stderr, "Unable to open XDG_CONFIG_HOME\n"); 92 return; 93 } 94 95 int dir_fd = openat(xdg_dir_fd, "scout", O_RDONLY | O_DIRECTORY); 96 if (dir_fd < 0) { 97 fprintf(stderr, "Unable to open scout config directory\n"); 98 return; 99 } 100 101 close(xdg_dir_fd); 102 103 /* Load and parse config file */ 104 int config_fd = openat(dir_fd, "scout.ini", O_RDONLY); 105 if (config_fd < 0) { 106 fprintf(stderr, "Unable to open scout.ini\n"); 107 close(dir_fd); 108 return; 109 } 110 111 char *buf = fdreadfile(config_fd); 112 ini_parse_string(buf, cfg_handler, pcfg); 113 free(buf); 114 115 close(config_fd); 116 117 /* Load and parse card files */ 118 int subdir_fd = openat(dir_fd, "cards", O_RDONLY | O_DIRECTORY); 119 if (subdir_fd < 0) { 120 fprintf(stderr, "Unable to open scout/cards\n"); 121 close(dir_fd); 122 return; 123 } 124 DIR *cards_dir = fdopendir(subdir_fd); 125 126 struct dirent *entry; 127 128 /* Count card entries */ 129 size_t count = 0; 130 while ((entry = readdir(cards_dir)) != NULL) 131 if (is_ini(entry)) 132 count++; 133 134 /* Allocate space for each card */ 135 *num_cards = (unsigned int) count; 136 *pcards = malloc(count * sizeof(scout_card_t)); 137 138 /* Rewind and parse card entries */ 139 rewinddir(cards_dir); 140 141 count = 0; 142 while ((entry = readdir(cards_dir)) != NULL) 143 if (is_ini(entry)) { 144 int fd = openat(subdir_fd, entry->d_name, O_RDONLY); 145 char *buf = fdreadfile(fd); 146 scout_card_t card = DEFAULT_CARD; 147 ini_parse_string(buf, card_handler, &card); 148 free(buf); 149 150 (*pcards)[count++] = card; 151 } 152 153 closedir(cards_dir); 154 155 close(dir_fd); 156 }