rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | README | LICENSE

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