1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  * copyright (c) '04-'21 Stian Skjelstad <stian.skjelstad@gmail.com>
4  *
5  * OCP.INI file and environment reading functions
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * revision history: (please note changes here)
22  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
23  *    -first release
24  *  -fd981014   Felix Domke <tmbinc@gmx.net>
25  *    -Bugfix at cfReadINIFile (first if-block, skips the filename in
26  *     the commandline, without these, funny errors occured.)
27  *  -fd981106   Felix Domke    <tmbinc@gmx.net>
28  *    -edited for new binfile
29  *  -ss040613   Stian Skjelstad <stian@nixia.no>
30  *    - rewritten for unix
31  *    - use argc and argv semantics
32  *  -ss040825   Stian Skjelstad <stian@nixia.no>
33  *    - added back the commandline stuff
34  */
35 
36 #include "config.h"
37 #include <ctype.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <unistd.h>
45 #include "psetting.h"
46 #include "stuff/compat.h"
47 
48 char *cfConfigDir;
49 char *cfDataDir;
50 char *cfProgramDir;
51 char *cfTempDir;
52 
53 #define KEYBUF_LEN 105
54 #define STRBUF_LEN 405
55 #define COMMENTBUF_LEN 256
56 
57 const char *cfConfigSec;
58 const char *cfSoundSec;
59 const char *cfScreenSec;
60 
61 struct profilekey
62 {
63   char *key;
64   char *str;
65   char *comment;
66   int linenum;
67 };
68 
69 struct profileapp
70 {
71   char *app;
72   char *comment;
73   struct profilekey *keys;
74   int nkeys;
75   int linenum;
76 };
77 
78 static struct profileapp *cfINIApps=NULL;
79 static int cfINInApps=0;
80 
readiniline(char * key,char * str,char * comment,const char * line)81 static int readiniline(char *key, char *str, char *comment, const char *line)
82 {
83 	const char *sol;
84 	const char *eol;
85 	const char *chk;
86 
87 	comment[0]=0;
88 
89   /* read until we get a line*/
90 	while (isspace(*line))
91 		line++;
92   /* this line is a comment ?*/
93 	if (((*line)==';')||((*line)=='#')||(!*line))
94 	{
95 		strncpy(comment, line, COMMENTBUF_LEN);
96 		comment[COMMENTBUF_LEN-1]=0;
97 		return 0;
98 	}
99 
100 	sol=line;
101 	eol=sol;
102 
103 	while ((*eol!='#')&&(*eol!=';')&&(*eol))
104 		eol++;
105 	if ((eol[0]==';')||(eol[0]=='#'))
106 	{
107 		strncpy(comment, eol, COMMENTBUF_LEN);
108 		comment[COMMENTBUF_LEN-1]=0;
109 	}
110 	while (isspace(eol[-1]))
111 	{
112 		if (sol==eol)
113 			return 0;
114 		eol--;
115 	}
116 	if ((*sol=='[')&&(eol[-1]==']'))
117 	{
118 		strcpy(key, "[]");
119 		if ((eol-sol)>400)
120 			return 0;
121 		memcpy(str, sol+1, eol-sol-2);
122 		str[eol-sol-2]=0;
123 		return 1;
124 	}
125 	if (!(chk=strchr(sol, '=')))
126 		return 0;
127 	while (isspace(chk[-1]))
128 	{
129 		if (chk==sol)
130 			return 0;
131 		chk--;
132 	}
133 
134 	if ((chk-sol)>=(KEYBUF_LEN-1))
135 		return 0;
136 	memcpy(key, sol, chk-sol);
137 	key[chk-sol]=0;
138 
139 	while (chk[-1]!='=')
140 		chk++;
141 
142 	while ((chk<eol)&&isspace(*chk))
143 		chk++;
144 
145 	if ((eol-chk)>=(STRBUF_LEN-1))
146 		return 0;
147 	memcpy(str, chk, eol-chk);
148 	str[eol-chk]=0;
149 
150 	return 2;
151 }
152 
cfReadINIFile(int argc,char * argv[])153 static int cfReadINIFile(int argc, char *argv[])
154 {
155 	char *path;
156 	FILE *f;
157 	int linenum=0;
158 	int cfINIApps_index=-1;
159 
160 	char keybuf[KEYBUF_LEN];
161 	char strbuf[STRBUF_LEN];
162 	char commentbuf[COMMENTBUF_LEN];
163 
164 	char linebuffer[1024];
165 	/*  int curapp=-1;*/
166 
167 	makepath_malloc (&path, 0, cfConfigDir, "ocp.ini", 0);
168 
169 	strcpy(keybuf, "");
170 
171 	cfINIApps=0;
172 	cfINInApps=0;
173 
174 	if (!(f=fopen(path, "r")))
175 	{
176 		fprintf (stderr, "fopen(\"%s\", \"r\"): %s\n", path, strerror (errno));
177 		free (path);
178 		return 1;
179 	}
180 	free (path); path=0;
181 
182 	while (fgets(linebuffer, sizeof(linebuffer), f))
183 	{
184 		linenum++;
185 		{
186 			char *tmp;
187 			if ((tmp=strchr(linebuffer, '\n')))
188 				*tmp=0;
189 			if ((tmp=strchr(linebuffer, '\r')))
190 				*tmp=0;
191 		}
192 
193 		commentbuf[0]=0;
194 		switch (readiniline(keybuf, strbuf, commentbuf, linebuffer))
195 		{
196 			case 0:
197 				if (commentbuf[0]&&(cfINIApps_index>=0))
198 				{
199 					int index=cfINIApps[cfINIApps_index].nkeys;
200 					cfINIApps[cfINIApps_index].nkeys++;
201 					cfINIApps[cfINIApps_index].keys=realloc(cfINIApps[cfINIApps_index].keys, sizeof(cfINIApps[cfINIApps_index].keys[0])*(index+1));
202 					cfINIApps[cfINIApps_index].keys[index].key=NULL;
203 					cfINIApps[cfINIApps_index].keys[index].str=NULL;
204 					cfINIApps[cfINIApps_index].keys[index].comment=strdup(commentbuf);
205 					cfINIApps[cfINIApps_index].keys[index].linenum=linenum;
206 				}
207 				break;
208 			case 1:
209 				cfINIApps_index=-1;
210 				{
211 					int n;
212 					for (n=0;n<cfINInApps;n++)
213 						if (!strcmp(cfINIApps[n].app, strbuf))
214 						{
215 							cfINIApps_index=n;
216 							break;
217 						}
218 				}
219 				if (cfINIApps_index<0)
220 				{
221 					cfINIApps_index=cfINInApps;
222 					cfINInApps++;
223 					cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
224 					cfINIApps[cfINIApps_index].app=strdup(strbuf);
225 					cfINIApps[cfINIApps_index].keys=NULL;
226 					cfINIApps[cfINIApps_index].nkeys=0;
227 					cfINIApps[cfINIApps_index].comment=(commentbuf[0]?strdup(commentbuf):NULL);
228 					cfINIApps[cfINIApps_index].linenum=linenum;
229 				}
230 				continue;
231 			case 2:
232 				if (cfINIApps_index>=0) /* Don't append keys if we don't have a section yet */
233 				{
234 					int index=cfINIApps[cfINIApps_index].nkeys;
235 					cfINIApps[cfINIApps_index].nkeys++;
236 					cfINIApps[cfINIApps_index].keys=realloc(cfINIApps[cfINIApps_index].keys, sizeof(cfINIApps[cfINIApps_index].keys[0])*(index+1));
237 					cfINIApps[cfINIApps_index].keys[index].key=strdup(keybuf);
238 					cfINIApps[cfINIApps_index].keys[index].str=strdup(strbuf);
239 					cfINIApps[cfINIApps_index].keys[index].comment=(commentbuf[0]?strdup(commentbuf):NULL);
240 					cfINIApps[cfINIApps_index].keys[index].linenum=linenum;
241 				}
242 				continue;
243 		}
244 	}
245 	{
246 		char *argvstat=0;
247 		int c;
248 
249 		for (c=1;c<argc;c++)
250 			if ((argv[c][0]=='-')&&argv[c][1])
251 			{
252 				if ((argv[c][1]=='-')&&(!argv[c][2])) /* Unix legacy */
253 					break;
254 				if (argv[c][1]=='-')
255 					continue;
256 
257 				cfINInApps++;
258 				cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
259 				cfINIApps[cfINInApps-1].app=strdup("commandline__");
260 				cfINIApps[cfINInApps-1].app[12]=argv[c][1];
261 				cfINIApps[cfINInApps-1].keys=NULL;
262 				cfINIApps[cfINInApps-1].nkeys=0;
263 				cfINIApps[cfINInApps-1].linenum=-1;
264 				cfINIApps[cfINInApps-1].comment=NULL;
265 
266 				argvstat=argv[c]+2;
267 				while (*argvstat)
268 				{
269 					char *temp=index(argvstat, ',');
270 					int index=cfINIApps[cfINInApps-1].nkeys;
271 
272 					if (!temp)
273 						temp=argvstat+strlen(argvstat);
274 
275 					cfINIApps[cfINInApps-1].nkeys++;
276 					cfINIApps[cfINInApps-1].keys=realloc(cfINIApps[cfINInApps-1].keys, sizeof(cfINIApps[cfINInApps-1].keys[0])*(index+1));
277 					cfINIApps[cfINInApps-1].keys[index].key=strdup("_");
278 					cfINIApps[cfINInApps-1].keys[index].key[0]=*argvstat;
279 					argvstat++;
280 					cfINIApps[cfINInApps-1].keys[index].str=malloc(temp-argvstat+1);
281 					strncpy(cfINIApps[cfINInApps-1].keys[index].str, argvstat, temp-argvstat);
282 					cfINIApps[cfINInApps-1].keys[index].str[temp-argvstat]=0;
283 					cfINIApps[cfINInApps-1].keys[index].linenum=-1;
284 					cfINIApps[cfINInApps-1].keys[index].comment=NULL;
285 					argvstat=temp;
286 					if (*argvstat)
287 						argvstat++;
288 				}
289 			}
290 
291 		cfINInApps++;
292 		cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
293 		cfINIApps[cfINInApps-1].app=strdup("CommandLine");
294 		cfINIApps[cfINInApps-1].keys=NULL;
295 		cfINIApps[cfINInApps-1].nkeys=0;
296 		cfINIApps[cfINInApps-1].linenum=-1;
297 		cfINIApps[cfINInApps-1].comment=NULL;
298 
299 		for (c=1;c<argc;c++)
300 			if ((argv[c][0]=='-')&&argv[c][1])
301 			{
302 				int index=cfINIApps[cfINInApps-1].nkeys;
303 
304 				if ((argv[c][1]=='-')&&(!argv[c][2])) /* Unix legacy */
305 					break;
306 
307 				cfINIApps[cfINInApps-1].nkeys++;
308 				cfINIApps[cfINInApps-1].keys=realloc(cfINIApps[cfINInApps-1].keys, sizeof(cfINIApps[cfINInApps-1].keys[0])*(index+1));
309 				cfINIApps[cfINInApps-1].keys[index].key=strdup("_");
310 				cfINIApps[cfINInApps-1].keys[index].key[0]=argv[c][1];
311 				cfINIApps[cfINInApps-1].keys[index].str=strdup(argv[c]+2);
312 				cfINIApps[cfINInApps-1].keys[index].linenum=-1;
313 				cfINIApps[cfINInApps-1].keys[index].comment=NULL;
314 			}
315 
316 		cfINInApps++;
317 		cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
318 		cfINIApps[cfINInApps-1].app=strdup("CommandLine--");
319 		cfINIApps[cfINInApps-1].keys=NULL;
320 		cfINIApps[cfINInApps-1].nkeys=0;
321 		cfINIApps[cfINInApps-1].linenum=-1;
322 		cfINIApps[cfINInApps-1].comment=NULL;
323 
324 		for (c=1;c<argc;c++)
325 			if ((argv[c][0]=='-')&&(argv[c][1]=='-'))
326 			{
327 				int index=cfINIApps[cfINInApps-1].nkeys;
328 
329 				if (!argv[c][2]) /* Unix legacy */
330 					break;
331 
332 				cfINIApps[cfINInApps-1].nkeys++;
333 				cfINIApps[cfINInApps-1].keys=realloc(cfINIApps[cfINInApps-1].keys, sizeof(cfINIApps[cfINInApps-1].keys[0])*(index+1));
334 				cfINIApps[cfINInApps-1].keys[index].key=strdup(argv[c]+2);
335 				cfINIApps[cfINInApps-1].keys[index].str=strdup("1");
336 				cfINIApps[cfINInApps-1].keys[index].linenum=-1;
337 				cfINIApps[cfINInApps-1].keys[index].comment=NULL;
338 			}
339 
340 		cfINInApps++;
341 		cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
342 		cfINIApps[cfINInApps-1].app=strdup("CommandLine_Files");
343 		cfINIApps[cfINInApps-1].keys=NULL;
344 		cfINIApps[cfINInApps-1].nkeys=0;
345 		cfINIApps[cfINInApps-1].linenum=-1;
346 		cfINIApps[cfINInApps-1].comment=NULL;
347 
348 		{
349 			int countin=0;
350 			int files = 0;
351 			int playlists = 0;
352 
353 			for (c=1;c<argc;c++)
354 			{
355 				if (!countin)
356 				{
357 					if (argv[c][0]=='-')
358 					{
359 						if (argv[c][1]=='-')
360 						{
361 							if (!argv[c][2])
362 								countin=1;
363 						}
364 						continue;
365 					}
366 				}
367 
368 				{
369 					int index=cfINIApps[cfINInApps-1].nkeys;
370 					char buffer[32];
371 					if (argv[c][0]!='@')
372 						sprintf(buffer, "file%d", files++);
373 					else
374 						sprintf(buffer, "playlist%d", playlists++);
375 					cfINIApps[cfINInApps-1].nkeys++;
376 					cfINIApps[cfINInApps-1].keys=realloc(cfINIApps[cfINInApps-1].keys, sizeof(cfINIApps[cfINInApps-1].keys[0])*(index+1));
377 					cfINIApps[cfINInApps-1].keys[index].key=strdup(buffer);
378 					cfINIApps[cfINInApps-1].keys[index].str=strdup(argv[c]+(argv[c][0]=='@'?1:0));
379 					cfINIApps[cfINInApps-1].keys[index].linenum=-1;
380 					cfINIApps[cfINInApps-1].keys[index].comment=NULL;
381 				}
382 			}
383 		}
384 	}
385 	fclose(f);
386 	return 0;
387 }
388 
cfFreeINI(void)389 static void cfFreeINI(void)
390 {
391 	int i, j;
392 	for (i=0;i<cfINInApps;i++)
393 	{
394 		for (j=0;j<cfINIApps[i].nkeys;j++)
395 		{
396 			if (cfINIApps[i].keys[j].key)
397 				free(cfINIApps[i].keys[j].key);
398 			if (cfINIApps[i].keys[j].str)
399 				free(cfINIApps[i].keys[j].str);
400 			if (cfINIApps[i].keys[j].comment)
401 				free(cfINIApps[i].keys[j].comment);
402 		}
403 		free(cfINIApps[i].app);
404 		if (cfINIApps[i].comment)
405 			free(cfINIApps[i].comment);
406 		if (cfINIApps[i].keys)
407 			free(cfINIApps[i].keys);
408 	}
409 	if (cfINIApps)
410 		free(cfINIApps);
411 }
412 
cfCloseConfig()413 void cfCloseConfig()
414 {
415 	cfFreeINI();
416 }
417 
cfGetProfileString(const char * app,const char * key,const char * def)418 const char *cfGetProfileString(const char *app, const char *key, const char *def)
419 {
420 	int i,j;
421 	for (i=0; i<cfINInApps; i++)
422 		if (!strcasecmp(cfINIApps[i].app, app))
423 			for (j=0; j<cfINIApps[i].nkeys; j++)
424 				if (cfINIApps[i].keys[j].key)
425 					if (!strcasecmp(cfINIApps[i].keys[j].key, key))
426 						return cfINIApps[i].keys[j].str;
427 	return def;
428 }
429 
cfGetProfileString2(const char * app,const char * app2,const char * key,const char * def)430 const char *cfGetProfileString2(const char *app, const char *app2, const char *key, const char *def)
431 {
432 	return cfGetProfileString(app, key, cfGetProfileString(app2, key, def));
433 }
434 
cfSetProfileString(const char * app,const char * key,const char * str)435 void cfSetProfileString(const char *app, const char *key, const char *str)
436 {
437 	int i, j;
438 	for (i=0; i<cfINInApps; i++)
439 		if (!strcasecmp(cfINIApps[i].app, app))
440 		{
441 			for (j=0; j<cfINIApps[i].nkeys; j++)
442 				if (cfINIApps[i].keys[j].key)
443 					if (!strcasecmp(cfINIApps[i].keys[j].key, key))
444 					{
445 						free(cfINIApps[i].keys[j].str);
446 						cfINIApps[i].keys[j].str = strdup (str);
447 						return;
448 					}
449 doappend:
450 			j=cfINIApps[i].nkeys;
451 			cfINIApps[i].nkeys++;
452 			cfINIApps[i].keys=realloc(cfINIApps[i].keys, sizeof(cfINIApps[i].keys[0])*(j+1));
453 			cfINIApps[i].keys[j].key=strdup(key);
454 			cfINIApps[i].keys[j].str=strdup(str);
455 			cfINIApps[i].keys[j].comment=NULL;
456 			cfINIApps[i].keys[j].linenum=9999;
457 			return;
458 		}
459 	cfINInApps++;
460 	cfINIApps=realloc(cfINIApps, sizeof(cfINIApps[cfINInApps])*cfINInApps);
461 	cfINIApps[i].app=strdup(app);
462 	cfINIApps[i].keys=NULL;
463 	cfINIApps[i].nkeys=0;
464 	cfINIApps[i].comment=NULL;
465 	cfINIApps[i].linenum=9999;
466 	goto doappend;
467 }
468 
cfGetProfileInt(const char * app,const char * key,int def,int radix)469 int cfGetProfileInt(const char *app, const char *key, int def, int radix)
470 {
471 	const char *s=cfGetProfileString(app, key, "");
472 	if (!*s)
473 		return def;
474 	return strtol(s, 0, radix);
475 }
476 
cfGetProfileInt2(const char * app,const char * app2,const char * key,int def,int radix)477 int cfGetProfileInt2(const char *app, const char *app2, const char *key, int def, int radix)
478 {
479 	return cfGetProfileInt(app, key, cfGetProfileInt(app2, key, def, radix), radix);
480 }
481 
cfSetProfileInt(const char * app,const char * key,int str,int radix)482 void cfSetProfileInt(const char *app, const char *key, int str, int radix)
483 {
484 	char buffer[64];
485 	if (radix==16)
486 		snprintf(buffer, sizeof(buffer), "0x%x", str);
487 	else
488 		snprintf(buffer, sizeof(buffer), "%d", str);
489 	cfSetProfileString(app, key, buffer);
490 }
491 
cfGetProfileBool(const char * app,const char * key,int def,int err)492 int cfGetProfileBool(const char *app, const char *key, int def, int err)
493 {
494 	const char *s=cfGetProfileString(app, key, 0);
495 	if (!s)
496 		return def;
497 	if (!*s)
498 		return err;
499 	if (!strcasecmp(s, "on")||!strcasecmp(s, "yes")||!strcasecmp(s, "+")||!strcasecmp(s, "true")||!strcasecmp(s, "1"))
500 		return 1;
501 	if (!strcasecmp(s, "off")||!strcasecmp(s, "no")||!strcasecmp(s, "-")||!strcasecmp(s, "false")||!strcasecmp(s, "0"))
502 		return 0;
503 	return err;
504 }
505 
cfGetProfileBool2(const char * app,const char * app2,const char * key,int def,int err)506 int cfGetProfileBool2(const char *app, const char *app2, const char *key, int def, int err)
507 {
508 	return cfGetProfileBool(app, key, cfGetProfileBool(app2, key, def, err), err);
509 }
510 
cfSetProfileBool(const char * app,const char * key,const int str)511 void cfSetProfileBool(const char *app, const char *key, const int str)
512 {
513 	cfSetProfileString(app, key, (str?"on":"off"));
514 }
515 
cfRemoveEntry(const char * app,const char * key)516 void cfRemoveEntry(const char *app, const char *key)
517 {
518 	int i, j;
519 	for (i=0; i<cfINInApps; i++)
520 		if (!strcasecmp(cfINIApps[i].app, app))
521 		{
522 			for (j=0; j<cfINIApps[i].nkeys; j++)
523 				if (cfINIApps[i].keys[j].key)
524 					if (!strcasecmp(cfINIApps[i].keys[j].key, key))
525 					{
526 						if (cfINIApps[i].keys[j].str)
527 							free(cfINIApps[i].keys[j].str);
528 						if (cfINIApps[i].keys[j].key)
529 							free(cfINIApps[i].keys[j].key);
530 						if (cfINIApps[i].keys[j].comment)
531 							free(cfINIApps[i].keys[j].comment);
532 						memmove(cfINIApps[i].keys + j, cfINIApps[i].keys + j + 1, (cfINIApps[i].nkeys - j  - 1) * sizeof(cfINIApps[i].keys[0]));
533 						cfINIApps[i].nkeys--;
534 						if (cfINIApps[i].nkeys)
535 						{
536 							void *temp = realloc(cfINIApps[i].keys, cfINIApps[i].nkeys*sizeof(cfINIApps[i].keys[0]));
537 							if (temp)
538 								cfINIApps[i].keys = temp;
539 							else
540 								fprintf(stderr, __FILE__ ": warning, realloc() failed #1\n");
541 						}
542 					}
543 		}
544 }
545 
cfRemoveProfile(const char * app)546 void cfRemoveProfile(const char *app)
547 {
548 	int i, j;
549 	for (i=0; i<cfINInApps; i++)
550 	{
551 		if (!strcasecmp(cfINIApps[i].app, app))
552 		{
553 			for (j=0; j<cfINIApps[i].nkeys; j++)
554 			{
555 				if (cfINIApps[i].keys[j].str)
556 					free(cfINIApps[i].keys[j].str);
557 				if (cfINIApps[i].keys[j].key)
558 					free(cfINIApps[i].keys[j].key);
559 				if (cfINIApps[i].keys[j].comment)
560 					free(cfINIApps[i].keys[j].comment);
561 			}
562 			if (cfINIApps[i].nkeys)
563 			{
564 				free (cfINIApps[i].keys);
565 			}
566 
567 			memmove (cfINIApps + i, cfINIApps + i + 1, sizeof (cfINIApps[0]) * (cfINInApps - i - 1));
568 			cfINInApps--;
569 			i--;
570 		}
571 	}
572 }
573 
cfCountSpaceList(const char * str,int maxlen)574 int cfCountSpaceList(const char *str, int maxlen)
575 {
576 	int i=0;
577 	while (1)
578 	{
579 		const char *fb;
580 
581 		while (isspace(*str))
582 			str++;
583 		if (!*str)
584 			return i;
585 		fb=str;
586 		while (!isspace(*str)&&*str)
587 			str++;
588 		if ((str-fb)<=maxlen)
589 			i++;
590 	}
591 }
592 
cfGetSpaceListEntry(char * buf,const char ** str,int maxlen)593 int cfGetSpaceListEntry(char *buf, const char **str, int maxlen)
594 {
595 	while (1)
596 	{
597 		const char *fb;
598 
599 		while (isspace(**str))
600 			(*str)++;
601 		if (!**str)
602 			return 0;
603 		fb=*str;
604 		while (!isspace(**str)&&**str)
605 			(*str)++;
606 		if (((*str)-fb)>maxlen)
607 			continue;
608 		memcpy(buf, fb, (*str)-fb);
609 		buf[(*str)-fb]=0;
610 		return 1;
611 	}
612 }
613 
cfGetConfig(int argc,char * argv[])614 int cfGetConfig(int argc, char *argv[])
615 {
616 	const char *t;
617 
618 	if (!argc)
619 		return -1; /* no config at all pigs! */
620 	if (cfReadINIFile(argc, argv))
621 	{
622 		fprintf(stderr, "Failed to read ocp.ini\nPlease put it in ~/.ocp/\n");
623 		return -1;
624 	}
625 
626 	t=cfGetProfileString("general", "datadir", NULL);
627 	if (t)
628 	{
629 		free (cfDataDir);
630 		cfDataDir = strdup (t);
631 	}
632 
633 	if ((t=cfGetProfileString("general", "tempdir", t)))
634 	{
635 		cfTempDir = strdup (t);
636 	} else if ((t=getenv("TEMP")))
637 	{
638 		cfTempDir = strdup (t);
639 	} else if ((t=getenv("TMP")))
640 	{
641 		cfTempDir = strdup (t);
642 	} else {
643 		cfTempDir = strdup ("/tmp/");
644 	}
645 
646 #ifdef PSETTING_DEBUG
647 	{
648 		int i, j;
649 		char buffer[2+KEYBUF_LEN+1+STRBUF_LEN+COMMENTBUF_LEN+32+1+1];
650 		for (i=0;i<cfINInApps;i++)
651 		{
652 			strcpy(buffer, "[");
653 			strcat(buffer, cfINIApps[i].app);
654 			strcat(buffer, "]");
655 			if (cfINIApps[i].comment)
656 			{
657 				while (strlen(buffer)<32)
658 					strcat(buffer, " ");
659 				strcat(buffer, cfINIApps[i].comment);
660 			}
661 			strcat(buffer, "\n");
662 
663 			fprintf(stderr, "% 4d:%s", cfINIApps[i].linenum, buffer);
664 			for (j=0;j<cfINIApps[i].nkeys;j++)
665 			{
666 				if (cfINIApps[i].keys[j].key)
667 				{
668 					strcpy(buffer, "  ");
669 					strcat(buffer, cfINIApps[i].keys[j].key);
670 					strcat(buffer, "=");
671 					strcat(buffer, cfINIApps[i].keys[j].str);
672 					if (cfINIApps[i].keys[j].comment)
673 					{
674 						while (strlen(buffer)<32)
675 							strcat(buffer, " ");
676 						strcat(buffer, cfINIApps[i].keys[j].comment);
677 					}
678 				} else
679 					strcpy(buffer, cfINIApps[i].keys[j].comment);
680 				strcat(buffer, "\n");
681 				fprintf(stderr, "% 4d:%s", cfINIApps[i].keys[j].linenum, buffer);
682 			}
683 		}
684 	}
685 #endif
686 	return 0;
687 }
688 
cfStoreConfig(void)689 int cfStoreConfig(void)
690 {
691 	char *path;
692 	FILE *f;
693 	int i, j;
694 	char buffer[2+KEYBUF_LEN+1+STRBUF_LEN+COMMENTBUF_LEN+32+1+1];
695 
696 	makepath_malloc (&path, 0, cfConfigDir, "ocp.ini", 0);
697 
698 	if (!(f=fopen(path, "w")))
699 	{
700 		fprintf (stderr, "fopen(\"%s\", \"w\"): %s\n", path, strerror (errno));
701 		free (path);
702 		return 1;
703 	}
704 	free (path); path=0;
705 
706 	for (i=0;i<cfINInApps;i++)
707 		if (cfINIApps[i].linenum>=0)
708 		{
709 			strcpy(buffer, "[");
710 			strcat(buffer, cfINIApps[i].app);
711 			strcat(buffer, "]");
712 			if (cfINIApps[i].comment)
713 			{
714 				int n=strlen(buffer)-32;
715 				if (n>0)
716 					strncat(buffer, "                                ", n);
717 				strcat(buffer, cfINIApps[i].comment);
718 			}
719 			strcat(buffer, "\n");
720 
721 			fprintf(f, "%s", buffer);
722 			for (j=0;j<cfINIApps[i].nkeys;j++)
723 				if (cfINIApps[i].keys[j].linenum>=0)
724 				{
725 					if (cfINIApps[i].keys[j].key)
726 					{
727 						strcpy(buffer, "  ");
728 						strcat(buffer, cfINIApps[i].keys[j].key);
729 						strcat(buffer, "=");
730 						strcat(buffer, cfINIApps[i].keys[j].str);
731 						if (cfINIApps[i].keys[j].comment)
732 						{
733 							while (strlen(buffer)<32)
734 								strcat(buffer, " ");
735 							strcat(buffer, cfINIApps[i].keys[j].comment);
736 						}
737 					} else
738 						strcpy(buffer, cfINIApps[i].keys[j].comment);
739 					strcat(buffer, "\n");
740 					fprintf(f, "%s", buffer);
741 				}
742 		}
743 	fclose(f);
744 	return 0;
745 }
746