cfg.c (5892B)
1 /* 2 * Copy me if you can. 3 * by 20h 4 */ 5 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <stdarg.h> 10 #include <string.h> 11 #include <strings.h> 12 #include <errno.h> 13 #include <libgen.h> 14 #include <sys/stat.h> 15 #include <sys/types.h> 16 #include <dirent.h> 17 #include <ctype.h> 18 19 #include "ind.h" 20 #include "arg.h" 21 #include "llist.h" 22 #include "path.h" 23 #include "cfg.h" 24 25 config_t * 26 config_init(char *cfgn) 27 { 28 char *path; 29 config_t *cfg; 30 31 if (cfgn == NULL) 32 cfgn = "default"; 33 34 path = path_mkcfgfile(cfgn); 35 cfg = config_read(path); 36 if (cfg == NULL) 37 cfg = config_new(); 38 cfg->path = memdups(path); 39 free(path); 40 41 if (cfg->name == NULL) { 42 cfg->name = memdups("default"); 43 } else { 44 cfg->name = memdups(cfgn); 45 } 46 47 return cfg; 48 } 49 50 void 51 config_default(char *cfgn) 52 { 53 char *path, *cwd; 54 struct stat sbuf; 55 56 cwd = getcwd(NULL, 0); 57 if (cwd == NULL) 58 edie("getcwd"); 59 60 path = path_mkrppath(NULL); 61 if (chdir(path) < 0) 62 edie("chdir"); 63 if (lstat("default", &sbuf) >= 0) { 64 if (remove("default") < 0) 65 edie("remove"); 66 } 67 if (symlink(cfgn, "default") < 0) 68 edie("symlink"); 69 70 if (chdir(cwd) < 0) 71 edie("chdir"); 72 73 free(cwd); 74 free(path); 75 } 76 77 void 78 config_list(void) 79 { 80 char *path; 81 struct dirent **dirlist; 82 int ndir; 83 84 path = path_mkrppath(NULL); 85 86 ndir = scandir(path, &dirlist, NULL, alphasort); 87 free(path); 88 if (ndir < 0) 89 edie("scandir"); 90 for (--ndir; ndir >= 0; ndir--) { 91 if (!strcmp(dirlist[ndir]->d_name, ".")) 92 continue; 93 if (!strcmp(dirlist[ndir]->d_name, "..")) 94 continue; 95 if (!strcmp(dirlist[ndir]->d_name, "default")) 96 continue; 97 printf("%s\n", dirlist[ndir]->d_name); 98 } 99 free(dirlist); 100 } 101 102 void 103 config_stop(config_t *cfg) 104 { 105 char *path; 106 107 if (cfg->changed) { 108 path = path_mkcfgfile(cfg->name); 109 if (config_write(cfg, NULL) == NULL) 110 edie("config_write"); 111 free(path); 112 } 113 114 config_free(cfg); 115 } 116 117 llistelem_t * 118 config_checkget(config_t *cfg, char *key) 119 { 120 llistelem_t *result; 121 122 result = config_get(cfg, key); 123 if (result == NULL) 124 die("config_checkget: %s not found in config.\n", key); 125 126 return result; 127 } 128 129 char * 130 config_getstr(config_t *cfg, char *key) 131 { 132 llistelem_t *selitem; 133 char *rstr, *envval, *ukey; 134 int i; 135 136 /* 137 * The environment is: 138 * RP${KEY} 139 */ 140 ukey = smprintf("RP%s", key); 141 for (i = 2; i < strlen(ukey); i++) 142 ukey[i] = (char)toupper(ukey[i]); 143 144 envval = getenv(ukey); 145 free(ukey); 146 if (envval != NULL) 147 return memdups(envval); 148 149 if (cfg == NULL) 150 return NULL; 151 152 selitem = config_get(cfg, key); 153 if (selitem != NULL && selitem->data != NULL) { 154 rstr = memdup(selitem->data, selitem->datalen+1); 155 } else { 156 rstr = NULL; 157 } 158 159 return rstr; 160 } 161 162 char * 163 config_checkgetstr(config_t *cfg, char *key) 164 { 165 char *rstr; 166 167 rstr = config_getstr(cfg, key); 168 if (rstr == NULL) 169 die("config_checkgetstr: %s not found in config.\n", key); 170 171 return rstr; 172 } 173 174 void 175 configprintelem(llistelem_t *elem, int onlydata) 176 { 177 if (onlydata) { 178 llistelem_printdata(elem); 179 } else { 180 llistelem_print(elem); 181 } 182 } 183 184 void 185 configusage(char *argv0) 186 { 187 die("usage: %s [-hiqv] [-c cfg] [-e cfg|-l|key" 188 " [value]]|-d key|-s regex|-n]\n", argv0); 189 } 190 191 int 192 configmain(int argc, char *argv[]) 193 { 194 int status; 195 char *key, *value, *cfgn, *def, *argv0; 196 config_t *cfg; 197 llist_t *results; 198 llistelem_t *result, *elem; 199 200 enum { 201 BEQUIET = 0x01, 202 ONLYDATA = 0x02, 203 DOLIST = 0x04, 204 DODELETE = 0x08, 205 DOSEARCH = 0x10, 206 DOINIT = 0x20, 207 DODEFAULT = 0x40, 208 DONAMECFG = 0x80 209 }; 210 211 status = 0; 212 key = NULL; 213 value = NULL; 214 cfgn = NULL; 215 def = NULL; 216 217 ARGBEGIN(argv0) { 218 case 'c': 219 cfgn = EARGF(configusage(argv0)); 220 break; 221 case 'd': 222 status |= DODELETE; 223 break; 224 case 'e': 225 def = ARGF(); 226 status |= DODEFAULT; 227 break; 228 case 'i': 229 status |= DOINIT; 230 break; 231 case 'n': 232 status |= DONAMECFG; 233 break; 234 case 'q': 235 status |= BEQUIET; 236 break; 237 case 'v': 238 status |= ONLYDATA; 239 break; 240 case 'l': 241 status |= DOLIST; 242 break; 243 case 's': 244 status |= DOSEARCH; 245 break; 246 default: 247 configusage(argv0); 248 } ARGEND; 249 250 if (status & DODEFAULT) { 251 if (def) { 252 config_default(def); 253 if (!(status & BEQUIET)) { 254 printf("Default configuration set to '%s'.\n", 255 def); 256 } 257 return 0; 258 } else { 259 config_list(); 260 return 0; 261 } 262 } 263 264 cfg = config_init(cfgn); 265 266 if (status & DONAMECFG) { 267 if (cfg->name != NULL) 268 printf("%s\n", cfg->name); 269 return 0; 270 } 271 272 if (status & DOLIST) { 273 if (config_len(cfg) > 0) { 274 llist_sort(cfg->values); 275 forllist(cfg->values, elem) 276 configprintelem(elem, status & ONLYDATA); 277 } 278 return 0; 279 } 280 281 if (argc > 0) { 282 key = argv[0]; 283 if (argc > 1) 284 value = argv[1]; 285 } else { 286 configusage(argv0); 287 } 288 289 if (value != NULL) { 290 result = config_set(cfg, key, value); 291 if (!(status & BEQUIET)) 292 configprintelem(result, status & ONLYDATA); 293 config_stop(cfg); 294 return 0; 295 } 296 297 if ((status & DOSEARCH) && !(status & DODELETE)) { 298 results = config_find(cfg, key); 299 if (results == NULL) { 300 if (!(status & BEQUIET)) 301 printf("No matching key found.\n"); 302 return 1; 303 } 304 forllist(results, elem) 305 configprintelem(elem, status & ONLYDATA); 306 return 0; 307 } 308 if (status & DODELETE) { 309 if (status & DOSEARCH) { 310 results = config_find(cfg, key); 311 if (results == NULL) { 312 if (!(status & BEQUIET)) 313 printf("No such key in config.\n"); 314 return 1; 315 } 316 317 forllist(results, elem) 318 config_del(cfg, elem->key); 319 if (!(status & BEQUIET)) 320 printf("%d keys removed from config\n", 321 results->len); 322 config_stop(cfg); 323 } else { 324 result = config_del(cfg, key); 325 if (result == NULL) { 326 if (!(status & BEQUIET)) 327 printf("Nothing deleted.\n"); 328 return 1; 329 } else { 330 if (!(status & BEQUIET)) 331 printf("One key removed from " 332 "config.\n"); 333 config_stop(cfg); 334 } 335 } 336 return 0; 337 } 338 339 result = config_get(cfg, key); 340 if (result == NULL) { 341 if (!(status & BEQUIET)) 342 printf("No such key in config.\n"); 343 return 1; 344 } 345 configprintelem(result, status & ONLYDATA); 346 347 return 0; 348 } 349