progman.exe^H^H^H^H
at master 138 lines 3.3 kB view raw
1/* 2 * Copyright 2020 joshua stein <jcs@jcs.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 18 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 19 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22#include <err.h> 23#include <stdlib.h> 24#include <string.h> 25#include "progman.h" 26#include "parser.h" 27#include "progman_ini.h" 28 29/* 30 * If the user specifies an ini file, return NULL immediately if it's not 31 * found; otherwise, search for the usual suspects. 32 */ 33FILE * 34open_ini(char *inifile) 35{ 36 FILE *ini = NULL; 37 char buf[BUF_SIZE]; 38 39 if (inifile) { 40 ini = fopen(inifile, "r"); 41 if (!ini) 42 err(1, "can't open config file %s", inifile); 43 44 return ini; 45 } 46 47 snprintf(buf, sizeof(buf), "%s/.config/progman/progman.ini", 48 getenv("HOME")); 49 if ((ini = fopen(buf, "r"))) 50 return ini; 51 52 /* load compiled-in defaults */ 53 ini = fmemopen(progman_ini, sizeof(progman_ini), "r"); 54 if (!ini || sizeof(progman_ini) == 0) 55 errx(1, "no compiled-in default config file"); 56 57 return ini; 58} 59 60int 61find_ini_section(FILE *stream, char *section) 62{ 63 char buf[BUF_SIZE], marker[BUF_SIZE]; 64 65 snprintf(marker, sizeof(marker), "[%s]\n", section); 66 67 fseek(stream, 0, SEEK_SET); 68 while (fgets(buf, sizeof(buf), stream)) { 69 if (buf[0] == '#' || buf[0] == '\n') 70 continue; 71 if (strncmp(buf, marker, strlen(marker)) == 0) 72 return 1; 73 } 74 75 return 0; 76} 77 78int 79get_ini_kv(FILE *stream, char **key, char **val) 80{ 81 char buf[BUF_SIZE], *tval; 82 long pos = ftell(stream); 83 int len; 84 85 buf[0] = '\0'; 86 87 /* find next non-comment, non-section line */ 88 while (fgets(buf, sizeof(buf), stream)) { 89 if (buf[0] == '#' || buf[0] == '\n') { 90 pos = ftell(stream); 91 continue; 92 } 93 94 if (buf[0] == '[') { 95 /* new section, rewind so find_ini_section can see it */ 96 fseek(stream, pos, SEEK_SET); 97 return 0; 98 } 99 100 break; 101 } 102 103 if (!buf[0]) 104 return 0; 105 106 tval = strchr(buf, '='); 107 if (tval == NULL) { 108 warnx("bad line in ini file: %s", buf); 109 return 0; 110 } 111 112 tval[0] = '\0'; 113 tval++; 114 115 /* trim trailing spaces from key */ 116 for (len = strlen(buf); len > 0 && buf[len - 1] == ' '; len--) 117 ; 118 buf[len] = '\0'; 119 120 /* trim leading spaces from val */ 121 while (tval[0] == ' ') 122 tval++; 123 124 /* and trailing spaces and newlines from val */ 125 len = strlen(tval) - 1; 126 while (len) { 127 if (tval[len] == ' ' || tval[len] == '\r' || tval[len] == '\n') 128 len--; 129 else 130 break; 131 } 132 tval[len + 1] = '\0'; 133 134 *key = strdup(buf); 135 *val = strdup(tval); 136 137 return 1; 138}