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