1: /*
2: * $Id: iniconf.c,v 1.3 2025/03/09 19:14:25 snw Exp $
3: * Function implementations for reading
4: * FreeM configuration files
5: *
6: *
7: * Author: Serena Willis <snw@coherent-logic.com>
8: * Copyright (C) 1998 MUG Deutschland
9: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
10: *
11: *
12: * This file is part of FreeM.
13: *
14: * FreeM is free software: you can redistribute it and/or modify
15: * it under the terms of the GNU Affero Public License as published by
16: * the Free Software Foundation, either version 3 of the License, or
17: * (at your option) any later version.
18: *
19: * FreeM is distributed in the hope that it will be useful,
20: * but WITHOUT ANY WARRANTY; without even the implied warranty of
21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22: * GNU Affero Public License for more details.
23: *
24: * You should have received a copy of the GNU Affero Public License
25: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
26: *
27: * $Log: iniconf.c,v $
28: * Revision 1.3 2025/03/09 19:14:25 snw
29: * First phase of REUSE compliance and header reformat
30: *
31: *
32: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
33: * SPDX-License-Identifier: AGPL-3.0-or-later
34: **/
35:
36: #define FALSE 0
37: #define TRUE 1
38: #include <stddef.h>
39: #include "iniconf.h"
40: #include "libfill.h"
41: #include <stdio.h>
42: #include <unistd.h>
43: #include <sys/types.h>
44: #include <pwd.h>
45: #include <string.h>
46: #include <limits.h>
47: #include "mpsdef.h"
48:
49: extern char config_file[4096];
50:
51: #if !defined(PATH_MAX) && defined(_SCO_DS)
52: # define PATH_MAX 4096
53: #endif
54:
55: #if !defined(PATH_MAX) && defined(__gnu_hurd__)
56: # define PATH_MAX 1024
57: #endif
58:
59: #if !defined(PATH_MAX) && defined(_AIX)
60: # define PATH_MAX 1024
61: #endif
62:
63: #if defined(__NetBSD__) || defined(__FreeBSD__)
64: # include <sys/syslimits.h>
65: #endif
66:
67: ini_keyvalue *ini_head;
68:
69: /* prototypes for internal-use-only functions */
70: int read_profile_string(char *file, char *section, char *key, char *value);
71:
72: int get_conf(char *section, char *key, char *value)
73: {
74: char *etcfile;
75: char *dotfile;
76: char *homedir;
77:
78: int exists_in_etc = FALSE;
79: int exists_in_dotfile = FALSE;
80: int dotexists;
81: int etcexists;
82:
83: char *etc_value;
84: char *dot_value;
85:
86: etc_value = (char *) malloc(CONF_BUFSIZE);
87: NULLPTRCHK(etc_value,"get_conf");
88: dot_value = (char *) malloc(CONF_BUFSIZE);
89: NULLPTRCHK(dot_value,"get_conf");
90:
91: etcfile = config_file;
92:
93:
94: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
95: uid_t uid = geteuid();
96: struct passwd *pw = getpwuid(uid);
97:
98: if (pw == NULL) {
99: free (etc_value);
100: free (dot_value);
101:
102: return (FALSE);
103: }
104:
105: homedir = (char *) calloc(strlen(pw->pw_dir) + 1, sizeof(char));
106: NULLPTRCHK(homedir,"get_conf");
107:
108: (void) strcpy(homedir, pw->pw_dir);
109:
110: dotfile = calloc(PATH_MAX, sizeof(char));
111: NULLPTRCHK(dotfile,"get_conf");
112:
113: (void) strcat(dotfile, homedir);
114: (void) strcat(dotfile, "/.freemrc");
115:
116: etcexists = file_exists(etcfile);
117: dotexists = file_exists(dotfile);
118: #else
119:
120: #if defined(__AMIGA)
121: strcpy (etcfile, "./freem.conf");
122: etcexists = TRUE;
123: dotexists = FALSE;
124: #else
125: strcpy (etcfile, SYSCONFDIR"/freem.conf");
126:
127: etcexists = TRUE;
128: dotexists = FALSE;
129: #endif
130:
131: #endif
132:
133: if (etcexists == TRUE) {
134: exists_in_etc = read_profile_string(etcfile, section, key, etc_value);
135: }
136: else {
137: exists_in_etc = FALSE;
138: }
139:
140: if (dotexists == TRUE) {
141: exists_in_dotfile = read_profile_string(dotfile, section, key, dot_value);
142: }
143: else {
144: exists_in_dotfile = FALSE;
145: }
146:
147: if (exists_in_dotfile) {
148: strcpy (value, dot_value);
149:
150: free (etc_value);
151: free (dot_value);
152: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
153: free (homedir);
154: free (dotfile);
155: #endif
156:
157: return (TRUE);
158: }
159:
160: if (exists_in_etc) {
161: strcpy(value, etc_value);
162:
163: free (etc_value);
164: free (dot_value);
165: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
166: free (homedir);
167: free (dotfile);
168: #endif
169:
170: return (TRUE);
171: }
172:
173: free (etc_value);
174: free (dot_value);
175: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
176: free (homedir);
177: free (dotfile);
178: #endif
179:
180: return (FALSE); /* didn't exist anywhere */
181: }
182:
183: int read_profile_string(char *file, char *section, char *key, char *value)
184: {
185:
186: register int i;
187:
188: FILE *fp;
189:
190: char *curkey;
191: char *curval;
192: char *fullsec;
193: char *cursec;
194: char *line;
195: int lnum = 0;
196:
197: fullsec = (char *) malloc(CONF_BUFSIZE);
198: NULLPTRCHK(fullsec,"read_profile_string");
199:
200: cursec = (char *) malloc(CONF_BUFSIZE);
201: NULLPTRCHK(cursec,"read_profile_string");
202:
203: line = (char *) malloc(CONF_BUFSIZE);
204: NULLPTRCHK(line,"read_profile_string");
205:
206:
207:
208:
209: snprintf(fullsec, CONF_BUFSIZE, "[%s]%c", section, '\0');
210:
211: strcpy(cursec, "[]");
212:
213:
214: fp = fopen(file, "r");
215:
216: while(fgets(line, CONF_BUFSIZE, fp) != NULL) {
217: ++lnum;
218:
219: if(line[0] == '[') {
220: strcpy(cursec, line);
221:
222: for(i = 0; i < CONF_BUFSIZE; i++) {
223: if(cursec[i] == ']') {
224: cursec[i + 1] = '\0';
225: break;
226: }
227: }
228: }
229: else {
230: if ((line[0] != '[') && (strchr(line, '=') != NULL)) {
231: curkey = strtok(line, "=");
232: curval = strtok(NULL, "=");
233: curval = strtok(curval, "\n");
234:
235:
236: if((strcmp(curkey, key) == 0) && (strcmp(cursec, fullsec) == 0)) {
237: strcpy(value, curval);
238: (void) fclose(fp);
239:
240: free (fullsec);
241: free (curkey);
242: free (cursec);
243:
244: return(TRUE);
245: }
246: }
247: }
248:
249: }
250:
251: if (fp != NULL) {
252: (void) fclose(fp);
253: }
254:
255: /* if we've gotten here, the section and/or key was not found */
256: sprintf (value, "\0");
257:
258: free (fullsec);
259: free (curkey);
260: free (cursec);
261:
262: return(FALSE);
263:
264: }
265:
266: int file_exists(char *filename)
267: {
268: FILE *fp;
269:
270: if ((fp = fopen(filename, "r")) != NULL) {
271: (void) fclose(fp);
272:
273: return(TRUE);
274: }
275: else {
276: return(FALSE);
277: }
278: }
279:
280: void write_profile_string(char *file, char *section, char *key, char *value)
281: {
282: ini_keyvalue *ini_head;
283:
284: }
285:
286: ini_keyvalue *ini_insert(ini_section *s, char *section, char *key, char *value)
287: {
288: ini_section *t;
289:
290: for (t = s; t != NULL; t = t->next) {
291:
292: if (strcmp (t->name, section) == 0) {
293:
294: /* this section already exists. update. */
295: return ini_kv_insert (s, key, value);
296:
297: }
298:
299: }
300:
301: /* section does not exist. insert. */
302: t = (ini_section *) malloc (sizeof (ini_section));
303: NULLPTRCHK(t,"ini_insert");
304:
305: t->name = (char *) malloc ((strlen (section) + 1) * sizeof (char));
306: NULLPTRCHK(t->name,"ini_insert");
307:
308: strcpy (t->name, section);
309:
310: t->next = s;
311: s = t;
312:
313: return ini_kv_insert (s, key, value);
314:
315: }
316:
317: ini_keyvalue *ini_kv_insert(ini_section *s, char *key, char *value)
318: {
319: ini_keyvalue *t;
320:
321: for (t = s->head; t != NULL; t = t->next) {
322:
323: if (strcmp (t->key, key) == 0) {
324:
325: /* this is an update */
326: free (t->value);
327: t->value = (char *) malloc ((strlen (value) + 1) * sizeof (char));
328: NULLPTRCHK(t->value,"ini_kv_insert");
329:
330: strcpy (t->value, value);
331:
332: return t;
333:
334: }
335:
336: }
337:
338: /* this is an insert */
339: t = (ini_keyvalue *) malloc (sizeof (ini_keyvalue));
340: NULLPTRCHK(t,"ini_kv_insert");
341:
342: t->key = (char *) malloc ((strlen (key) + 1) * sizeof (char));
343: NULLPTRCHK(t->key,"ini_kv_insert");
344:
345: t->value = (char *) malloc ((strlen (value) + 1) * sizeof (char));
346: NULLPTRCHK(t->value,"ini_kv_insert");
347:
348: strcpy (t->key, key);
349: strcpy (t->value, value);
350:
351: t->next = s->head;
352: s->head = t;
353:
354: return t;
355:
356: }
357:
358: void ini_section_delete(ini_section *head, char *name)
359: {
360: ini_section *t = head;
361: ini_section *p = NULL;
362:
363: if ((t != (ini_section *) NULL) && (strcmp (t->name, name) == 0)) {
364: head = t->next;
365:
366: free (t->name);
367: free (t);
368: return;
369: }
370:
371: while ((t != NULL) && (strcmp (t->name, name) != 0)) {
372: p = t;
373: t = t->next;
374: }
375:
376: if (t == NULL) return;
377:
378: free (t->name);
379: free (t);
380:
381: return;
382: }
383:
384: void ini_key_delete(ini_section *head, char *key)
385: {
386:
387: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>