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