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>