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