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