Annotation of freem/src/iniconf.c, revision 1.8
1.1 snw 1: /*
1.8 ! snw 2: * $Id: iniconf.c,v 1.7 2025/04/10 15:27:39 snw Exp $
1.1 snw 3: * Function implementations for reading
4: * FreeM configuration files
5: *
6: *
1.2 snw 7: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 8: * Copyright (C) 1998 MUG Deutschland
1.3 snw 9: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 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: *
1.4 snw 27: * $Log: iniconf.c,v $
1.8 ! snw 28: * Revision 1.7 2025/04/10 15:27:39 snw
! 29: * Detect Devuan distribution and fix OS/2 problem with iniconf.c
! 30: *
1.7 snw 31: * Revision 1.6 2025/04/10 01:24:38 snw
32: * Remove C++ style comments
33: *
1.6 snw 34: * Revision 1.5 2025/04/09 19:52:02 snw
35: * Eliminate as many warnings as possible while building with -Wall
36: *
1.5 snw 37: * Revision 1.4 2025/04/02 19:59:38 snw
38: * Automatically modify env.conf from fmadm reconfigure
39: *
1.4 snw 40: * Revision 1.3 2025/03/09 19:14:25 snw
41: * First phase of REUSE compliance and header reformat
42: *
1.3 snw 43: *
44: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
45: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 46: **/
47:
48: #define FALSE 0
49: #define TRUE 1
50: #include <stddef.h>
51: #include "iniconf.h"
52: #include "libfill.h"
53: #include <stdio.h>
54: #include <unistd.h>
55: #include <sys/types.h>
56: #include <pwd.h>
57: #include <string.h>
58: #include <limits.h>
1.4 snw 59: #include <fs.h>
1.1 snw 60: #include "mpsdef.h"
61:
1.7 snw 62: #if defined(__OS2__)
63: # include <os2.h>
64: #endif
65:
1.1 snw 66: extern char config_file[4096];
67:
68: #if !defined(PATH_MAX) && defined(_SCO_DS)
69: # define PATH_MAX 4096
70: #endif
71:
72: #if !defined(PATH_MAX) && defined(__gnu_hurd__)
73: # define PATH_MAX 1024
74: #endif
75:
76: #if !defined(PATH_MAX) && defined(_AIX)
77: # define PATH_MAX 1024
78: #endif
79:
80: #if defined(__NetBSD__) || defined(__FreeBSD__)
81: # include <sys/syslimits.h>
82: #endif
83:
1.6 snw 84: #if !defined(PATH_MAX)
85: # define PATH_MAX 4096
86: #endif
87:
88:
1.5 snw 89: /* ini_keyvalue *ini_head; */
1.1 snw 90:
91: int get_conf(char *section, char *key, char *value)
92: {
93: char *etcfile;
94: char *dotfile;
95: char *homedir;
96:
97: int exists_in_etc = FALSE;
98: int exists_in_dotfile = FALSE;
99: int dotexists;
100: int etcexists;
101:
102: char *etc_value;
103: char *dot_value;
104:
105: etc_value = (char *) malloc(CONF_BUFSIZE);
106: NULLPTRCHK(etc_value,"get_conf");
107: dot_value = (char *) malloc(CONF_BUFSIZE);
108: NULLPTRCHK(dot_value,"get_conf");
109:
110: etcfile = config_file;
111:
112:
113: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
114: uid_t uid = geteuid();
115: struct passwd *pw = getpwuid(uid);
116:
117: if (pw == NULL) {
118: free (etc_value);
119: free (dot_value);
120:
121: return (FALSE);
122: }
123:
124: homedir = (char *) calloc(strlen(pw->pw_dir) + 1, sizeof(char));
125: NULLPTRCHK(homedir,"get_conf");
126:
127: (void) strcpy(homedir, pw->pw_dir);
128:
129: dotfile = calloc(PATH_MAX, sizeof(char));
130: NULLPTRCHK(dotfile,"get_conf");
131:
132: (void) strcat(dotfile, homedir);
133: (void) strcat(dotfile, "/.freemrc");
134:
135: etcexists = file_exists(etcfile);
136: dotexists = file_exists(dotfile);
137: #else
138:
139: #if defined(__AMIGA)
140: strcpy (etcfile, "./freem.conf");
141: etcexists = TRUE;
142: dotexists = FALSE;
143: #else
144: strcpy (etcfile, SYSCONFDIR"/freem.conf");
145:
146: etcexists = TRUE;
147: dotexists = FALSE;
148: #endif
149:
150: #endif
151:
152: if (etcexists == TRUE) {
153: exists_in_etc = read_profile_string(etcfile, section, key, etc_value);
154: }
155: else {
156: exists_in_etc = FALSE;
157: }
158:
159: if (dotexists == TRUE) {
160: exists_in_dotfile = read_profile_string(dotfile, section, key, dot_value);
161: }
162: else {
163: exists_in_dotfile = FALSE;
164: }
165:
166: if (exists_in_dotfile) {
167: strcpy (value, dot_value);
168:
169: free (etc_value);
170: free (dot_value);
171: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
172: free (homedir);
173: free (dotfile);
174: #endif
175:
176: return (TRUE);
177: }
178:
179: if (exists_in_etc) {
180: strcpy(value, etc_value);
181:
182: free (etc_value);
183: free (dot_value);
184: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
185: free (homedir);
186: free (dotfile);
187: #endif
188:
189: return (TRUE);
190: }
191:
192: free (etc_value);
193: free (dot_value);
194: #if !defined(__AMIGA) && !defined(_SCO_DS) && !defined(_AIX)
195: free (homedir);
196: free (dotfile);
197: #endif
198:
199: return (FALSE); /* didn't exist anywhere */
200: }
201:
202: int read_profile_string(char *file, char *section, char *key, char *value)
203: {
204:
205: register int i;
206:
207: FILE *fp;
208:
209: char *curkey;
210: char *curval;
211: char *fullsec;
212: char *cursec;
213: char *line;
214: int lnum = 0;
1.6 snw 215:
216: curkey = (char *) NULL;
1.1 snw 217:
218: fullsec = (char *) malloc(CONF_BUFSIZE);
219: NULLPTRCHK(fullsec,"read_profile_string");
220:
221: cursec = (char *) malloc(CONF_BUFSIZE);
222: NULLPTRCHK(cursec,"read_profile_string");
223:
224: line = (char *) malloc(CONF_BUFSIZE);
225: NULLPTRCHK(line,"read_profile_string");
226:
227:
228:
229:
230: snprintf(fullsec, CONF_BUFSIZE, "[%s]%c", section, '\0');
231:
232: strcpy(cursec, "[]");
233:
234:
235: fp = fopen(file, "r");
236:
237: while(fgets(line, CONF_BUFSIZE, fp) != NULL) {
238: ++lnum;
239:
240: if(line[0] == '[') {
241: strcpy(cursec, line);
242:
243: for(i = 0; i < CONF_BUFSIZE; i++) {
244: if(cursec[i] == ']') {
245: cursec[i + 1] = '\0';
246: break;
247: }
248: }
249: }
250: else {
251: if ((line[0] != '[') && (strchr(line, '=') != NULL)) {
252: curkey = strtok(line, "=");
253: curval = strtok(NULL, "=");
254: curval = strtok(curval, "\n");
255:
256:
257: if((strcmp(curkey, key) == 0) && (strcmp(cursec, fullsec) == 0)) {
258: strcpy(value, curval);
259: (void) fclose(fp);
260:
261: free (fullsec);
262: free (curkey);
263: free (cursec);
264:
265: return(TRUE);
266: }
267: }
268: }
269:
270: }
271:
272: if (fp != NULL) {
273: (void) fclose(fp);
274: }
275:
276: /* if we've gotten here, the section and/or key was not found */
277: sprintf (value, "\0");
278:
279: free (fullsec);
280: free (curkey);
281: free (cursec);
282:
283: return(FALSE);
284:
285: }
286:
287: int file_exists(char *filename)
288: {
289: FILE *fp;
290:
291: if ((fp = fopen(filename, "r")) != NULL) {
292: (void) fclose(fp);
293:
294: return(TRUE);
295: }
296: else {
297: return(FALSE);
298: }
299: }
300:
1.4 snw 301: void parse_section_header(char *input, char *buf, size_t buflen)
302: {
303: strncpy (buf, &(input[1]), buflen);
304: buf[strlen (buf) - 2] = '\0';
305: }
306:
307: int modify_profile_string(char *file, char *section, char *key, char *value)
308: {
309: FILE *input_fp;
310: FILE *output_fp;
311: char output_filename[4096];
1.5 snw 312: char input_line[255];
1.4 snw 313: char current_section[255];
314: char *savptr;
315: char *current_key;
316: char tmpsi[255];
317: char tmps[255];
318: int changed = FALSE;
319:
320: snprintf (output_filename, 4095, "%s.tmp", file);
321:
322: if ((input_fp = fopen (file, "r")) == NULL) {
323: return FALSE;
324: }
325:
326: if ((output_fp = fopen (output_filename, "w+")) == NULL) {
327: fclose (input_fp);
328: return FALSE;
329: }
330:
331: while (fgets (input_line, 255, input_fp)) {
332: if (input_line[0] == '[') {
333: /* this is a section; write it unchanged */
334: fputs (input_line, output_fp);
335:
336: /* update the current section */
337: parse_section_header (input_line, current_section, 255);
338: }
339: else {
340: /* is this a key/value pair? */
341: if (strchr (input_line, '=') != NULL) {
342: /* are we in the requested section? */
343: if (strcmp (section, current_section) == 0) {
344: /* yes; we'll parse it */
345: strcpy (tmpsi, input_line);
346: savptr = tmpsi;
347: current_key = strtok_r (tmpsi, "=", &savptr);
348: /* is this key the one we're changing? */
349: if (strcmp (key, current_key) == 0) {
350: /* yes; modify it and write out*/
351: snprintf (tmps, 255, "%s=%s\n", current_key, value);
352:
353: fputs (tmps, output_fp);
354: changed = TRUE;
355: }
356: else {
357: /* not the requested key; pass it through unmodified */
358: fputs (input_line, output_fp);
359: }
360: }
361: else {
362: /* not the requested section; write it out unchanged */
363: fputs (input_line, output_fp);
364: }
365: }
366: else {
367: /* not a key/value pair; write it out unchanged */
368: fputs (input_line, output_fp);
369: }
370: }
371: }
372:
373: /* close both files */
374: fclose (output_fp);
375: fclose (input_fp);
376:
377: /* delete the original file */
378: unlink (file);
379:
380: /* rename the temporary file */
381: #if !defined(__OS2__)
382: cp (file, output_filename);
383: #else
1.8 ! snw 384: DosCopy (output_filename, file, 1);
1.4 snw 385: #endif
386:
387: return changed;
1.1 snw 388: }
389:
1.4 snw 390:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>