source: trunk/src/libsrc/util/kom.c @ 7513

Revision 7513, 24.4 KB checked in by baker, 6 months ago (diff)

cleanup warning: variable set but not used [-Wunused-but-set-variable]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * kom.c : Simple positional command parser.
3 *
4 *$ 91May07 CEJ Version 1.0
5 *$ 93Oct03 CEJ Added k_put routine.
6 *$ 95Oct18 LDD Created kom.h to house function prototypes.
7 *              Explicitly declared return types for all functions.
8 */
9/*********************C O P Y R I G H T   N O T I C E ***********************/
10/* Copyright 1991 by Carl Johnson.  All rights are reserved. Permission     */
11/* is hereby granted for the use of this product for nonprofit, commercial, */
12/* or noncommercial publications that contain appropriate acknowledgement   */
13/* of the author. Modification of this code is permitted as long as this    */
14/* notice is included in each resulting source module.                      */
15/****************************************************************************/
16
17#include <stdarg.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "kom.h"
23
24#define BOOL_EXPANSION_FROM_ENV(x)  ( (x==KOM_EXPANSION_FROM_ENV)? 1 : 0 )
25#define BOOL_EXPANSION_FROM_FILE(x) ( (x==KOM_EXPANSION_FROM_FILE)? 1 : 0 )
26
27int validate_envvar_name(const char *envvar_name); /* do no use logit */
28int LoadTableEnvVariable(); /* use logit */
29char *GetEnvVarValueFromFile( const char *envvar_name ); /* use logit by LoadTableEnvVariable() */
30char *k_getenv(const char *envvar_name, int flag_expand_from_file); /* use logit */
31int k_envvar_expansion(char *dst, const char *src, size_t max_dst, int flag_expand_from_file); /* use logit by k_getenv */
32
33/* default function for logging messages */
34void kom_log_func_default(char *message) {
35    fprintf(stderr,"%s",message);
36}
37
38/* function pointer to the current function for logging messages */
39static void (*kom_log_func)(char *) = kom_log_func_default;
40
41/* Change function for logging messages, default is fprintf to stderr */
42void set_kom_log(void (*par_kom_log_func)(char *) )
43{
44    kom_log_func = par_kom_log_func;
45}
46
47#define KOM_MAX_LOG_MESSAGE_LENGTH 4096
48/* function to call within kom for logging messages */
49void kom_log(char *format, ... )
50{
51    va_list listptr;
52    char message[KOM_MAX_LOG_MESSAGE_LENGTH];
53
54    if(kom_log_func != NULL) {
55      va_start(listptr, format);
56      vsnprintf(message, (size_t) KOM_MAX_LOG_MESSAGE_LENGTH, format, listptr);
57      kom_log_func(message);
58      va_end(listptr);
59    }
60}
61
62#define MAXCRD 2048
63struct k_buf {
64        FILE *fid;
65        int ncrd;               /* bytes in command             */
66        int istr;               /* index of current string      */
67        int icrd;               /* scan pointer                 */
68        int ierr;               /* error if non-zero            */
69        char crd[MAXCRD];       /* command buffer               */
70        char csav[MAXCRD];      /* last command read            */
71} ;
72
73#define MAXBUF 4
74struct k_buf com = {0L, 0, 0, 0, 0, "Virgin", "Virgin"};
75struct k_buf Kbuf[MAXBUF];
76int Nbuf = 0;
77char iniFormat = 0;
78
79/*
80 **** k_open_base : common code for k_open & k_open_format
81 */
82static int k_open_base( const char *name )
83{
84        if(Nbuf < MAXBUF && com.fid) {
85                Kbuf[Nbuf++] = com;
86                com.fid = 0;
87        }
88        if(com.fid)
89                return(0);
90/*      if(!strcmp(name, "term"))
91                com.fid = stdin;
92        else                                                    */
93                com.fid = fopen(name, "r");
94        if(com.fid)
95                return(Nbuf+1);
96        return(0);
97
98}
99
100/*
101 **** k_open : open new file for k-system input.  For now only one file
102 *              can be open at a time, but it should be straight foward to add
103 *              recursion capabitity using a stack in the com area.
104 */
105int k_open( const char *name )
106{
107        iniFormat = 0;
108        return k_open_base( name );
109}
110
111/*
112 **** k_open_format : k_open, but specify file format
113 *                    ewFormat=0 means file is in .ini format
114 *                               o/w use normal EW format
115 */
116int k_open_format( const char *name, char ewFormat )
117{
118        iniFormat = ewFormat ? 0 : '=';
119        return k_open_base( name );
120}
121
122/*
123 **** k_treat_as_ini : From now on, treat the currently open file as ini format.
124                       If no file is open, do nothing
125 */
126void k_treat_as_ini( void )
127{
128        if(com.fid)
129                iniFormat = '=';
130}
131
132/*
133 **** k_treat_as_ew : From now on, treat the currently open file as ew format.
134                      If no file is open, do nothing
135 */
136void k_treat_as_ew( void )
137{
138        if(com.fid)
139                iniFormat = 0;
140}
141
142/*
143 **** k_close : close current file
144 */
145int k_close( void )
146{
147        if(com.fid){
148                if(com.fid != stdin)
149                        fclose(com.fid);
150                com.fid = 0L;
151        }
152        if(Nbuf > 0) {
153                com = Kbuf[--Nbuf];
154                return Nbuf+1;
155        }
156        return(0);
157
158}
159
160/*
161 **** k_get : Return pointer to current card.
162 */
163char *k_get( void )
164{
165        return com.crd;
166}
167
168/*
169 **** k_dump : Print last card read.
170 */
171void k_dump( void )
172{
173        printf("%s\n", com.crd);
174}
175
176/*
177 **** k_err : return last error code and clear
178 */
179int k_err( void )
180{
181        int jerr;
182
183        jerr = com.ierr;
184        com.ierr = 0;
185        return(jerr);
186}
187
188/*
189 * k_int : Parce next token as integer.
190 */
191int k_int( void )
192{
193        int ival;
194        char *s;
195
196        s = k_str();
197        if(!s) {
198                com.ierr = -1;
199                return(0);
200        }
201        ival = atoi(s);
202        if(ival == 0 && *s != '0') {
203                com.ierr = -2;
204                return(0);
205        }
206        return(ival);
207}
208
209/*
210 * k_its : Compare string from last token to given command.
211 */
212int k_its(char *c)
213{
214        char *s;
215
216        s = &com.crd[com.istr];
217        while(*c == *s) {
218                if(*s == '\0')
219                        return(1);
220                c++;
221                s++;
222        }
223        return(0);
224}
225
226/*
227 * k_long : Return next token as a long integer.
228 */
229long k_long( void )
230{
231        long lval;
232        char *s;
233
234        s = k_str();
235        if(!s) {
236                com.ierr = -1;
237                return(0L);
238        }
239        lval = atol(s);
240        if(lval == 0 && *s != '0') {
241                com.ierr = -2;
242               return(0L);
243        }
244        return(lval);
245}
246
247/*
248 **** k_put : insert command line into buffer
249 */
250int k_put(char *crd)
251 {
252        int i, n;
253
254        strcpy(com.crd, crd);
255        com.ncrd = strlen(crd);
256        /* Lets account for both unix and windows line termination */   
257        /* if(com.ncrd && com.crd[com.ncrd-1] == '\n') */
258        /*         com.crd[--com.ncrd] = 0;            */
259        while (com.ncrd && ( com.crd[com.ncrd-1] == '\r' || com.crd[com.ncrd-1] == '\n')) {
260            com.crd[--com.ncrd] = 0;
261        }
262        if(!com.ncrd) {
263                com.ncrd = 1;
264                com.crd[0] = ' ';
265                com.crd[1] = 0;
266        }
267        com.istr = 0;
268        com.icrd = 0;
269        com.ierr = 0;
270        n = 1;
271        for(i=0; i<com.ncrd; i++) {
272                if(com.crd[i] == '\t')
273                        com.crd[i] = ' ';
274                if(com.crd[i] != ' ')
275                        n = i + 1;
276        }
277        com.ncrd = n;
278        com.crd[n] = 0;
279        strcpy(com.csav, com.crd);
280        return(com.ncrd);
281}
282
283/*
284 **** k_rd_raw : read command line into buffer and try to expand environment variable
285 *                     if flag_expansion_level is true, expansion from environment and file
286 *                     otherwise only from environment
287 */
288int k_rd_raw( int flag_expansion_level ) {
289        int ret;
290        extern struct k_buf com;
291        char newcrd[MAXCRD];
292        char newcrd_envvar_exp[MAXCRD];
293
294        if(com.fid) {
295          if(!fgets(newcrd, MAXCRD-1, com.fid)) {
296            if(feof(com.fid)) {
297              return 0;
298            }
299          }
300        }
301
302        /* POSSIBLE BUG EVEN THOUGH I AM NOT COMPLETELY SURE:
303         * Since the current limit passed to fgets() is equal to MAXCRD then
304         * line longer than MAXCRD could be truncated. As a consequence, some
305         * environment variable names could be truncated and not expanded.
306         * POSSIBLE SOLUTION:
307         * increase the value of MAXCRD for read newcrd by fgets(). */
308
309        /* Environment variable expansion */
310        if(flag_expansion_level == KOM_NO_EXPANSION) {
311            /* backward compatibility, old behavior */
312            ret =  k_put(newcrd);
313        } else {
314            if( k_envvar_expansion(newcrd_envvar_exp, newcrd, (size_t) MAXCRD,
315                        BOOL_EXPANSION_FROM_FILE(flag_expansion_level)) == 0 ) {
316                ret =  k_put(newcrd_envvar_exp);
317            } else {
318                kom_log("warning: skipping variable expansion for the following line (env var match not found):\n%s", newcrd);
319                ret =  k_put(newcrd);
320            }
321        }
322
323        return ret;
324}
325
326
327/*
328 **** k_rd : read command line into buffer
329 */
330int k_rd( void ) {
331    /* Read next line from active file with the variable expansion from environment and file */
332        if ( iniFormat )
333                iniFormat = '=';
334    return k_rd_raw(KOM_EXPANSION_FROM_FILE);
335}
336
337
338/*
339 **** k_com : returns last command line read
340 */
341char *k_com( void )
342{
343        return com.csav;
344}
345
346/*
347 **** k_str() : Return next token as a pointer to string.
348 */
349char *k_str( void )
350{
351        int state;
352        int i;
353
354        state = 1;
355        for(i=com.icrd; i<com.ncrd; i++) {
356                switch(state) {
357                case 1: /* Looking for first non-blank          */
358                        if(com.crd[i] == ' ' || com.crd[i] == '\t')
359                                break;
360                        if(com.crd[i] == '"') {
361                                state = 3;
362                                com.istr = i + 1;
363                                break;
364                        }
365                        if(com.crd[i] == '[') {
366                                state = 4;
367                                com.istr = i;
368                                break;
369                        }
370                        state = 2;
371                        com.istr = i;
372                        break;
373                case 2: /* Looking for end of normal string */
374                                if(iniFormat) {
375                                        if (iniFormat == com.crd[i]) {
376                                                int j = i-1;
377                                                while ( j>0 && (com.crd[j] == ' ' || com.crd[j] =='\t') )
378                                                        j--;
379                                                com.crd[j+1] = 0;
380                                                com.icrd = i + 1;
381                                                iniFormat = ',';
382                                                return(&com.crd[com.istr]);
383                                        }
384                                        continue;
385                                }
386                        if(com.crd[i] == ' ' || com.crd[i] == '\t') {
387                                com.crd[i] = 0;
388                                com.icrd = i + 1;
389                                return(&com.crd[com.istr]);
390                        }
391                        break;
392                case 3: /* Quoted string */
393                        if(com.crd[i] == '"') {
394                                com.crd[i] = 0;
395                                com.icrd = i + 1;
396                                return(&com.crd[com.istr]);
397                        }
398                        break;
399                case 4: /* Bracketed string */
400                        if(com.crd[i] == ']') {
401                                com.crd[i] = 0;
402                                com.icrd = i + 1;
403                                return(&com.crd[com.istr]);
404                        }
405                        break;
406                }
407        }
408        if(state == 2) {
409                com.crd[com.ncrd] = 0;
410                com.icrd = com.ncrd;
411                return(&com.crd[com.istr]);
412        }
413        com.ierr = -17;
414        return( (char *) 0 );
415}
416
417/*
418 **** k_val() Return next token as a double real
419 */
420double k_val( void )
421{
422        double val;
423        char *s;
424
425        s = k_str();
426        if(!s) {
427                com.ierr = -1;
428                return(0.0);
429        }
430        val = atof(s);
431        return(val);
432}
433
434
435
436/*************************************************************************
437 * validate_envvar_name  validate if envvar_name is a valid identifier   *
438 *            Return true or false.                                      *
439 *************************************************************************/
440int validate_envvar_name(const char *envvar_name) {
441    int ret;
442    int j = 0;
443    int l = strlen(envvar_name);
444
445    /* assume it is not ok */
446    ret = 0;
447
448    if(l > 0) {
449
450        /* starts with a character [A-Za-z] */
451        if(
452                (envvar_name[0] >= 'A'  &&  envvar_name[0] <= 'Z')
453                ||
454                (envvar_name[0] >= 'a'  &&  envvar_name[0] <= 'z')
455          ) {
456
457            /* assume it is ok */
458            ret = 1;
459            while(ret  &&  j < l) {
460                if( !(
461                            (envvar_name[j] >= 'A'  &&  envvar_name[j] <= 'Z')
462                            ||
463                            (envvar_name[j] >= 'a'  &&  envvar_name[j] <= 'z')
464                            ||
465                            (envvar_name[j] >= '0'  &&  envvar_name[j] <= '9')
466                            ||
467                            (envvar_name[j] == '_')
468                     )
469                  ) {
470                    ret = 0;
471                }
472                j++;
473            }
474
475        }
476
477    }
478
479    return ret;
480}
481
482
483/* Table of Environment variable names and their values
484 ***********************************************/
485#define MAXENVVAR 256
486#define ENVVARLEN 255
487static struct {
488  char          name[ENVVARLEN+1];
489  char          value[ENVVARLEN+1];
490} EW_EnvVariable[MAXENVVAR];
491static int Max_EnvVariable = 0;  /* # Environment variable currently in table */
492static int flag_LoadTableEnvVariable = 1;
493
494int LoadTableEnvVariable() {
495    int      newMax_EnvVariable = Max_EnvVariable;
496    char     *com;
497    char     *str_value;
498    char     *str;
499    int      skip = 0; /* = "an warning was encountered" */
500    int      nfiles = 0;
501    int      nopen = 0;
502    char     *paramdir;    /* points to environment variable, EW_PARAMS      */
503    int      len;
504    // int      success;
505    int      i;
506    FILE     *f = NULL;
507
508    const char configfile_commonvars[] = "earthworm_commonvars.d";
509#define MAXFILELENCOMVARS 512
510    static char  fullpath_configfile_commonvars[MAXFILELENCOMVARS+1];
511
512    /* Build fullpath_configfile_commonvars */
513    paramdir = getenv( "EW_PARAMS" ); 
514    strcpy( fullpath_configfile_commonvars, paramdir  );
515    len = strlen( fullpath_configfile_commonvars );
516#if defined(_SOLARIS) || defined(_LINUX) || defined(_MACOSX)
517    if( fullpath_configfile_commonvars[len-1] != '/' )   strcat( fullpath_configfile_commonvars, "/" );
518#else  /* OS/2 or NT */
519    if( fullpath_configfile_commonvars[len-1] != '\\' )  strcat( fullpath_configfile_commonvars, "\\" );
520#endif
521    strcat( fullpath_configfile_commonvars, configfile_commonvars );
522
523    f = fopen (fullpath_configfile_commonvars, "rt");
524    if(f) {
525        fclose(f);
526        /* Open the main configuration file */
527        nfiles = k_open_base (fullpath_configfile_commonvars);
528        if (nfiles == 0) {
529            kom_log("LoadTableEnvVariable(): Error opening command file <%s>; exiting!\n", 
530                    configfile_commonvars);
531            return -1;
532        }
533        nopen = nfiles-1;  /* keep track of # open files before ... */
534    }  else {
535        kom_log("LoadTableEnvVariable(): warning %s file not found.\n", fullpath_configfile_commonvars);
536
537    }
538
539    /* Process all command files */
540    while (nfiles > nopen) {   /* While there are command files open */
541
542        kom_log("LoadTableEnvVariable(): nfiles %d\n", nfiles);
543
544        /* Read file without expanding environment variable from file */
545        while (k_rd_raw(KOM_NO_EXPANSION)) {       /* Read next line from active file without expansion from file,
546                                       this prevents infinite recursivity on itself */
547            com = k_str ();         /* Get the first token from line */
548
549            /* Ignore blank lines & comments */
550            if (!com)
551                continue;
552            if (com[0] == '#')
553                continue;
554
555            /* Open a nested configuration file */
556            /*
557            if (com[0] == '@') {
558                success = nfiles + 1;
559                nfiles  = k_open_base (&com[1]);
560                if (nfiles != success) {
561                    kom_log("LoadTableEnvVariable(): Error opening command file <%s>; exiting!\n",
562                            &com[1]);
563                    return -1;
564                }
565                continue;
566            }
567            */
568
569            /* Enter environment variable name/value table
570             *******************************/
571            if( k_its("SetEnvVariable") ) 
572            {
573                skip = 0;
574                /* see if there's more room in the table */
575                if ( newMax_EnvVariable+1 >= MAXENVVAR ) {
576                    kom_log("LoadTableEnvVariable(): Too many <SetEnvVariable> lines in <%s>",
577                            configfile_commonvars );
578                    kom_log("; max=%d; exiting!\n", (int) MAXENVVAR );
579                    return -1;
580                }
581                str = k_str();          /* get variable name from line */
582                str_value = k_str();    /* get variable value from line */
583
584                /* check validity of variable name */
585                if( !validate_envvar_name(str) ) {
586                    kom_log("LoadTableEnvVariable(): Invalid environment variable name <%s> in <%s>",
587                            str, configfile_commonvars );
588                    kom_log(" (names without spaces are valid); skipping!\n" );
589                    skip = 1;
590                }     
591
592
593                /* check NULL of the environment variable name */
594                if ( !str && !skip)
595                {
596                    kom_log("LoadTableEnvVariable(): command EnvVariable NULL for name in <%s>;"
597                            " max=%d chars; exiting!\n", configfile_commonvars, ENVVARLEN );
598                    return -1;
599                }
600
601                /* check NULL of the environment variable value */
602                if ( !str_value  && !skip)
603                {
604                    kom_log("LoadTableEnvVariable(): command EnvVariable NULL for value of %s in <%s>;"
605                            " max=%d chars; exiting!\n", str, configfile_commonvars, ENVVARLEN );
606                    return -1;
607                }
608
609                /* check the length of the environment variable name */
610                if ( strlen(str) > ENVVARLEN  && !skip)
611                {
612                    kom_log("LoadTableEnvVariable(): environment variable name <%s> too long in <%s>;"
613                            " max=%d chars; exiting!\n", str, configfile_commonvars, ENVVARLEN );
614                    return -1;
615                }
616
617                /* check the length of the environment variable value */
618                if ( strlen(str_value) > ENVVARLEN  && !skip)
619                {
620                    kom_log("LoadTableEnvVariable(): environment variable value <%s> too long in <%s>;"
621                            " max=%d chars; exiting!\n", str_value, configfile_commonvars, ENVVARLEN );
622                    return -1;
623                }
624
625
626                /* look thru current table for duplicate type or name */
627                if(!skip) {
628                    i = 0;
629                    while(i<newMax_EnvVariable  &&  !skip) {
630                        if( strcmp( EW_EnvVariable[i].name, str ) == 0 ) {
631                            skip=1;
632                        } else {
633                            i++;
634                        }
635                    }
636
637                    /* complain if there was a duplication with a previous setting */
638                    if( skip ) {
639                        kom_log("LoadTableEnvVariable(): duplication variable in <%s>, new setting ignored\n", 
640                                configfile_commonvars );
641                        kom_log("                   original: <EnvVariable %s='%s'>\n", 
642                                EW_EnvVariable[i].name, EW_EnvVariable[i].value );
643                        kom_log("                        new: <EnvVariable %s='%s'>\n", 
644                                str, str_value );
645                        skip = 1;
646                    }
647
648                }
649
650                /* add new entry to table */
651                if( i==newMax_EnvVariable  &&  !skip) {
652                    strncpy( EW_EnvVariable[newMax_EnvVariable].name, str, (size_t) ENVVARLEN );
653                    strncpy( EW_EnvVariable[newMax_EnvVariable].value, str_value, (size_t) ENVVARLEN );
654                    newMax_EnvVariable++;
655                }
656            }
657
658            /* Unknown command */
659            else {
660                kom_log("LoadTableEnvVariable(): <%s> Unknown command in <%s>.\n",
661                        com, fullpath_configfile_commonvars);
662                continue;
663            }
664
665            /* See if there were any errors processing the command */
666            if (k_err ()) {
667                kom_log("LoadTableEnvVariable(): Bad command in <%s>; exiting!\n\t%s\n",
668                        fullpath_configfile_commonvars, k_com());
669                return -1;
670            }
671
672        } /** while k_rd_raw() **/
673
674        nfiles = k_close ();
675
676    } /** while nfiles **/
677
678    Max_EnvVariable = newMax_EnvVariable;
679
680    /* TODO Expand further value ?*/
681
682#ifdef DEBUG_ENVTABLE
683    kom_log("LoadTableEnvVariable(): EW_EnvVariable current table: %d items\n", Max_EnvVariable);
684    for(i=0; i < Max_EnvVariable; i++) {
685        kom_log("LoadTableEnvVariable(): %d %s=\"%s\"\n",
686                i+1, EW_EnvVariable[i].name, EW_EnvVariable[i].value);
687    }
688#endif
689
690    return 0;
691}
692
693/********************************************************
694*               GetEnvVarValueFromFile                 *
695*                                                      *
696* Given an environment variable name, return a pointer *
697* to its character string value.  Returns NULL pointer *
698* if the environment variable is not defined in        *
699* earthworm_commonvars.d                               *
700********************************************************/
701char *GetEnvVarValueFromFile( const char *envvar_name ) {
702    int i;
703    char *ret = NULL;
704
705    if(envvar_name) {
706
707        /* Load environment variable into table when it is needed */
708        if( flag_LoadTableEnvVariable ) {
709            LoadTableEnvVariable();
710            flag_LoadTableEnvVariable = 0;
711        }
712
713
714        /* Find environment variable value in earthworm.d table
715         **************************************/
716        i = 0;
717        while( i <  Max_EnvVariable  &&  !ret ) {
718            if ( strcmp(EW_EnvVariable[i].name, envvar_name) == 0 ) {
719                ret  =  EW_EnvVariable[i].value;
720            }
721            i++;
722        }
723
724    }
725
726    return ret;
727}
728
729
730/*
731 **** k_getenv :
732 *    Obtains the current value of the environment Earthworm variable, envvar_name
733 *               if flag_expand_from_file is true, expansion from environment and file
734 *               otherwise only from environment
735 */
736char *k_getenv(const char *envvar_name, int flag_expand_from_file) {
737    char *ret;
738    /* 0 environment getenv(), 1 earthworm file GetEnvVarValueFromFile() */
739/*  int source = 0; */
740    char *value_from_file = NULL;
741    char *value_from_environment = NULL;
742
743    /* TODO explain order used for getting variable values */
744    value_from_environment = getenv( envvar_name );
745    if(flag_expand_from_file) {
746        value_from_file = GetEnvVarValueFromFile( envvar_name );
747        if(value_from_file) {
748/*          source = 1; */
749            ret = value_from_file;
750        } else {
751            ret = value_from_environment;
752        }
753    } else {
754        ret = value_from_environment;
755    }
756
757/* commented out this logging of where env came from to stderr, as it was getting cumbersome, on 2013-07-13 */
758
759/* perhaps re-enable this with an environment debug flag somehow?
760    if(ret) {
761        kom_log("Environment variable %s=\"%s\" read from %s\n",
762                envvar_name, ret, (source==0)? "Environment" : "File");
763    } else {
764        kom_log("Environment variable %s not found (from file %s).\n",
765                envvar_name, (flag_expand_from_file)? "enabled" : "disabled");
766    }
767*/
768
769    return ret;
770}
771
772/*
773 **** k_envvar_expansion :
774 *    Copies at most max_dst-1 characters from src into dst replacing
775 *    environment variable name declared by the syntax ${.....} with respective value.
776 *        src is the input buffer as NULL terminated-string
777 *        dst is the output buffer as NULL terminated-string
778 *        flag_expand_from_file is the flag passed to k_getenv()
779 *    Return -1 in case of failure (do not use dst),
780 *            0 otherwise (you can use dst)
781 *
782 */
783int k_envvar_expansion(char *dst, const char *src, size_t max_dst, int flag_expand_from_file) {
784    int ret = 0;
785    int flag_copy = 0;
786    char envvar_name[MAXCRD];
787    char envvar_value[MAXCRD];
788    char *temp_variable_value;
789    int count_global_var   = 0;
790    int count_expanded_var = 0;
791    int comment_started = 0;
792    /* (unsigned) size_t variables for string indexing to match size_t max_dat */
793    size_t j, k;
794    size_t i_src = 0;
795    size_t i_dst = 0;
796    size_t l_src = strlen(src);
797
798    while(i_src < l_src  &&  ret == 0) {
799        flag_copy = 1;
800
801        /* Check if more space available for string dst */
802        if(i_dst+1 < max_dst) {
803
804            /* Take precaution against possible multi-lines within the src buffer */
805            if(src[i_src] == '\n'  ||  src[i_src] == '\r') {
806                comment_started = 0;
807            /* Start a comment. TODO: pound symbol could belong to a previous value */
808            } else if(src[i_src] == '#') {
809                comment_started = 1;
810            }
811
812            /* Check for Copying or Expanding */
813            if(src[i_src] == '$'  &&  !comment_started) {
814                if(i_src+1<l_src  &&  src[i_src+1] == '{') {
815
816                    /* Look for '}' */
817                    j = i_src + 2;
818                    while(j < l_src  &&  src[j] != '}') {
819                        j++;
820                    }
821
822                    /* TODO variable name can not contain '}' */
823                    if(j < l_src  &&  src[j] == '}') {
824                        /* Expand environment variable */
825                        flag_copy = 0;
826                        count_global_var++;
827
828                        /* Set envvar_name */
829                        k=i_src+2;
830                        while(k<j) {
831                            envvar_name[k - (i_src+2)] = src[k];
832                            k++;
833                        }
834                        envvar_name[k - (i_src+2)] = 0;
835
836                        /* Set envvar_value from  envvar_name */
837                        temp_variable_value = k_getenv( envvar_name, flag_expand_from_file );
838                        if(temp_variable_value) {
839                            count_expanded_var++;
840                            strncpy(envvar_value, temp_variable_value, (size_t) MAXCRD);
841                        } else {
842                            /* Not expand value and set again flag_copy to 1 */
843                            flag_copy = 1;
844                            envvar_value[0] = 0;
845                        }
846
847                    }
848
849                    /* Expand environment variable value into dst */
850                    if(!flag_copy) {
851                        i_src = j;
852                        k=0;
853                        while(k<strlen(envvar_value)  &&  ret == 0 ) {
854                            if(i_dst+1 < max_dst) {
855                                dst[i_dst] = envvar_value[k];
856                                i_dst++;
857                            } else {
858                                ret = -1;
859                            }
860                            k++;
861                        }
862                    }
863
864                }
865            }
866
867            /* Copy current character */
868            if(flag_copy) {
869                dst[i_dst] = src[i_src];
870                i_dst++;
871            }
872
873        } else {
874            /* error: over bound destination string */
875            ret = -1;
876        }
877
878        i_src++;
879    }
880
881    /* Terminate destination string */
882    dst[i_dst] = 0;
883    i_dst++;
884
885    /* At least one of the found variables has to have been expanded */
886    if(count_global_var>0 && count_expanded_var==0) {
887        ret = -1;
888    }
889
890    return ret;
891}
Note: See TracBrowser for help on using the repository browser.