rohrpost

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

cfg.c (5869B)


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