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