How to read a config file in C 
Author Message
 How to read a config file in C

Hi!
Is there some library in C (not C++) which helps to parse
simple config files.
Config file looks like follow:

# Comment

name1 = val1
name2 = val2
...

Thanks for any help.

Bob.



Fri, 11 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:

> Hi!
> Is there some library in C (not C++) which helps to parse
> simple config files.
> Config file looks like follow:

> # Comment

> name1 = val1
> name2 = val2

Why not write one yourself?

I suggest you use fgets() in a loop to gather the data, perhaps placing
each value you discover into a linked list or other dynamic data
structure. Think carefully about how you will store the values. Will you
treat them all as strings, or attempt to convert to an integer or
floating-point type where appropriate? Will the data validation routine
be tolerant of extra/missing whitespace, e.g. name1=val1 or name1  =  
val1 ? These questions, and more, need to be carefully considered in
your design stage.

When you have a design, cut some source code. When you have some source
code, get it working. When it works, the answer to your question will be
- yes!

If you get stuck, show us what you have and we'll try to help. Right
now, we can't help much because you don't have much.

--

Richard Heathfield

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.

C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
34 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (63
to go)



Fri, 11 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:
>Hi!
>Is there some library in C (not C++) which helps to parse
>simple config files.
>Config file looks like follow:

># Comment

>name1 = val1
>name2 = val2
>...

Just by writing a correct code to do it. You need:

fopen() fgets() fclose() from <stdio.h> to open, read and close the file.
strchr() or strstr() from <string.h> to parse clean and the read line.
eventually, strtod() or strtol() from <stdlib.h> to perform the requested
conversions

Of course, you could find some ready to play implementation on the Web...
Maybe here

www.snippet.org

But if you are a beginner, achieving such a program is a good challenge
(tricky, but not too difficult)

--
-hs- "Stove"
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
"Really?  When run on my machine, a printed copy of the C FAQ leaps
from the monitor and whacks me over the head.." -- Chris Mears CLC



Fri, 11 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:


> > Hi!
> > Is there some library in C (not C++) which helps to parse
> > simple config files.
> > Config file looks like follow:

> > # Comment

> > name1 = val1
> > name2 = val2

> Why not write one yourself?

I just wanted to save time of mine :)

Quote:

> I suggest you use fgets() in a loop to gather the data, perhaps placing
> each value you discover into a linked list or other dynamic data
> structure. Think carefully about how you will store the values. Will you
> treat them all as strings, or attempt to convert to an integer or
> floating-point type where appropriate? Will the data validation routine
> be tolerant of extra/missing whitespace, e.g. name1=val1 or name1  =
> val1 ? These questions, and more, need to be carefully considered in
> your design stage.

> When you have a design, cut some source code. When you have some source
> code, get it working. When it works, the answer to your question will be
> - yes!

> If you get stuck, show us what you have and we'll try to help. Right
> now, we can't help much because you don't have much.

Ok. My draft is here:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main ()
{
  FILE *CONF;

  int buff_size = 1024;
  char *buff, *token;
  char delimiters[] = "= \t";

  char **lineptr;
  int *n;

  lineptr = &buff;
  n = &buff_size;
  buff = (char*)malloc(*n);

  if(getcwd(buff, buff_size) == 0){
      printf("Can't get work directory.\nExit.\n");
      exit(1);
  }
  strcat(buff, "/saturn.conf");
  if((CONF = fopen(buff, "r")) == NULL){
      printf("Can't open config file: %s\nExit.\n", buff);
      exit(1);
  }
  printf("Parse config file: %s\n", buff);
//  free(buff);

  while(getline(lineptr, n, CONF) != -1 ){

      token = strtok(buff, delimiters);
      if(token[0] == '#' || token[0] == '\n') //Ignore comments and
empty lines
          continue;

      printf("%s ", token);

      token = strtok(NULL, delimiters);
      token[strlen(token) - 1] = '\0'; // Remove newline
      printf("%s\n", token);
      // and so on...

  }

fclose(CONF);
free(buff);

exit(0);

Quote:
}

Example of config file:

#
# Configuration file to Saturn program.
#
# Uncomment one of the follow lines:
#
mode = Asia
#mode = Europe
#mode = Africa
########################
#
section=Asia
#
SQLSERVER=localhost
#
SQLBASE=fond
#
SQLUSER=eugeneb
#
SQLPASSWORD=
#
LOGFILE=./asia.log
#
ENDSECTION=ASIA
#######################
section=etc

endsection=etc
#######################

The questions are:

1. Why gcc complains:
parse.c:33: warning: implicit declaration of function `getline'

despite getline() declarated in stdio.h ?

2. If we uncomment the firs line "free(buff);"
we catch SIGSEGV at the end of program (at the second "free(buff)").
Why?
I gess getline() must automatically use realloc to make the buffer
bigger.

3. How to force OS (Linux in my case) to do core dump file on error?

Thank you for answers.

Bob.



Sat, 12 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:

> Ok. My draft is here:
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
> int main ()
> {
>   FILE *CONF;
>   int buff_size = 1024;
>   char *buff, *token;
>   char delimiters[] = "= \t";
>   char **lineptr;
>   int *n;
>   lineptr = &buff;
>   n = &buff_size;
>   buff = (char*)malloc(*n);

cast not needed :)

Quote:
>   if(getcwd(buff, buff_size) == 0){
>       printf("Can't get work directory.\nExit.\n");
>       exit(1);
>   }
>   strcat(buff, "/saturn.conf");

this seems like a pretty complicated way to write:
        buff = "saturn.conf";
:P

Quote:
>   if((CONF = fopen(buff, "r")) == NULL){
>       printf("Can't open config file: %s\nExit.\n", buff);
>       exit(1);

EXIT_FAILURE is preferred by top breeders (and, incidentally, non-breeders
and bottom breeders as well).

Quote:
>   }
>   printf("Parse config file: %s\n", buff);
> //  free(buff);
>   while(getline(lineptr, n, CONF) != -1 ){

getline?  i'm not familiar with getline.  is that similar to readline()?

Quote:
>       token = strtok(buff, delimiters);
>       if(token[0] == '#' || token[0] == '\n') //Ignore comments and
> empty lines
>           continue;
>       printf("%s ", token);
>       token = strtok(NULL, delimiters);
>       token[strlen(token) - 1] = '\0'; // Remove newline
>       printf("%s\n", token);
>       // and so on...
>   }
> fclose(CONF);
> free(buff);
> exit(0);
> }

btw i might rewrite this last part just using fgets and sscanf():

        while (fgets(buff, n, CONF)) {
                buff[strlen(buff) - 1] = '\0';  /* remove possible '\n' */

                if (buff[0] == '#' || buff[0] == '\n')  continue;

                if (sscanf(buff, "%s = %s", &var_name, &var_value)) {
                        /* error */
                }
        }

and then just decide how you want to store all the things (e.g. what're
var_name and var_value going to be?).

- Show quoted text -

Quote:
> Example of config file:
> #
> # Configuration file to Saturn program.
> #
> # Uncomment one of the follow lines:
> #
> mode = Asia
> #mode = Europe
> #mode = Africa
> ########################
> #
> section=Asia
> #
> SQLSERVER=localhost
> #
> SQLBASE=fond
> #
> SQLUSER=eugeneb
> #
> SQLPASSWORD=
> #
> LOGFILE=./asia.log
> #
> ENDSECTION=ASIA
> #######################
> section=etc
> endsection=etc
> #######################
> The questions are:
> 1. Why gcc complains:
> parse.c:33: warning: implicit declaration of function `getline'
> despite getline() declarated in stdio.h ?

#ifdef  __USE_GNU

hint: use fgets().

Quote:
> 2. If we uncomment the firs line "free(buff);"
> we catch SIGSEGV at the end of program (at the second "free(buff)").
> Why?
> I gess getline() must automatically use realloc to make the buffer
> bigger.

you guess?  i think your guess is wrong.  why would it require a size
argument then?

Quote:
> 3. How to force OS (Linux in my case) to do core dump file on error?

i can't remember.  it would be non-ANSI anyway.  if worse comes to worse,
you could just do:
        raise(SIGSEGV);
(after including signal.h)

--
              /"\                              m i k e    b u r r e l l

               X        AGAINST HTML MAIL
              / \



Sat, 12 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:


> > Ok. My draft is here:

> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <unistd.h>
> > #include <string.h>

> > int main ()
> > {
> >   FILE *CONF;

> >   int buff_size = 1024;
> >   char *buff, *token;
> >   char delimiters[] = "= \t";

> >   char **lineptr;
> >   int *n;

> >   lineptr = &buff;
> >   n = &buff_size;
> >   buff = (char*)malloc(*n);

> cast not needed :)
:))

> >   if(getcwd(buff, buff_size) == 0){
> >       printf("Can't get work directory.\nExit.\n");
> >       exit(1);
> >   }
> >   strcat(buff, "/saturn.conf");

> this seems like a pretty complicated way to write:
>         buff = "saturn.conf";
> :P

That's it! Thanks.

Quote:

> >   if((CONF = fopen(buff, "r")) == NULL){
> >       printf("Can't open config file: %s\nExit.\n", buff);
> >       exit(1);

> EXIT_FAILURE is preferred by top breeders (and, incidentally, non-breeders
> and bottom breeders as well).

OK

Quote:

> >   }
> >   printf("Parse config file: %s\n", buff);
> > //  free(buff);

> >   while(getline(lineptr, n, CONF) != -1 ){

> getline?  i'm not familiar with getline.  is that similar to readline()?

It is a GNU extension but it is the recommended way to read lines from a
stream instead of standatd functions which are unreliable.

I've got this sentence from the reference manual of the GNU C Library :)

- Show quoted text -

Quote:

> >       token = strtok(buff, delimiters);
> >       if(token[0] == '#' || token[0] == '\n') //Ignore comments and
> > empty lines
> >           continue;

> >       printf("%s ", token);

> >       token = strtok(NULL, delimiters);
> >       token[strlen(token) - 1] = '\0'; // Remove newline

> >       printf("%s\n", token);
> >       // and so on...

> >   }

> > fclose(CONF);
> > free(buff);

> > exit(0);
> > }

> btw i might rewrite this last part just using fgets and sscanf():

>         while (fgets(buff, n, CONF)) {
>                 buff[strlen(buff) - 1] = '\0';  /* remove possible '\n' */

>                 if (buff[0] == '#' || buff[0] == '\n')  continue;

>                 if (sscanf(buff, "%s = %s", &var_name, &var_value)) {
>                         /* error */
>                 }
>         }

sscanf() doesnot work, sorry. onf file doesnot strong formatted.
It's possible no spaces around token '='.

Quote:

> and then just decide how you want to store all the things (e.g. what're
> var_name and var_value going to be?).

I going to use strcmp() for var_name and sscanf() for var_value.

[SKIP]

Quote:

> > The questions are:

> > 1. Why gcc complains:
> > parse.c:33: warning: implicit declaration of function `getline'

> > despite getline() declarated in stdio.h ?

> #ifdef  __USE_GNU

I put the command:

$ gcc -D__USE_GNU -Wall  parse.c -o parse

and again get:

parse.c:38: warning: implicit declaration of function `getline'

What's wrong??
When I insert explicit declaration straight into the text of my program
this warning disappear.

Quote:

> hint: use fgets().

May be I will.

Quote:

> > 2. If we uncomment the firs line "free(buff);"
> > we catch SIGSEGV at the end of program (at the second "free(buff)").
> > Why?
> > I gess getline() must automatically use realloc to make the buffer
> > bigger.

> you guess?  i think your guess is wrong.  why would it require a size
> argument then?

Why? Cut from reference is here:

"getline(char **lineptr, size_t *n, FILE *stream)

Before calling getline(), you should place in *lineptr the address
of a buffer *n bytes long. If this buffer is long enough to hold
the line, getline() stores the line in this buffer. Otherwise,
getline() makes the buffer bigger using realloc(), storing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the new buffer address back in *lineptr and the increased
size back in *n."

Quote:

> > 3. How to force OS (Linux in my case) to do core dump file on error?

> i can't remember.  it would be non-ANSI anyway.  if worse comes to worse,
> you could just do:
>         raise(SIGSEGV);

Oh, no. It is a little bit different thing. I don't need
to send a signal to myself. I would like to get core-dump file
after my program gets SIGSEGV from OS and dies.
I don't know should I insert something commands into
the text of my program for that. Or, may be I should
tune my OS? Any ideas?

Quote:
> (after including signal.h)

> --
>               /"\                              m i k e    b u r r e l l

>                X        AGAINST HTML MAIL
>               / \

To mike: Thank you for the lesson. I'm novice in C.
With regards,
Eugene Bobkov



Sun, 13 Oct 2002 03:00:00 GMT  
 How to read a config file in C

Quote:

>> getline?  i'm not familiar with getline.  is that similar to readline()?
> It is a GNU extension but it is the recommended way to read lines from a
> stream instead of standatd functions which are unreliable.
> I've got this sentence from the reference manual of the GNU C Library :)

OK :).

Quote:
>>                 if (sscanf(buff, "%s = %s", &var_name, &var_value)) {
> sscanf() doesnot work, sorry. onf file doesnot strong formatted.
> It's possible no spaces around token '='.

oh it works.  from my *scanf() manpage:

       White space (such as blanks, tabs,
       or newlines) in the format  string  match  any  amount  of
       white  space,  including  none,  in the input.
                      ^^^^^^^^^^^^^^^

i just realised that the %s would eat the = sign if there were no first
space, though, so you'd have to change it to something like:
        sscanf(buff, "%[^= ] = %s", &var_name, &var_value);
i still believe that sscanf() would be a good choice for this.

Quote:
> I going to use strcmp() for var_name and sscanf() for var_value.
> [SKIP]

>> > The questions are:

>> > 1. Why gcc complains:
>> > parse.c:33: warning: implicit declaration of function `getline'

>> > despite getline() declarated in stdio.h ?

>> #ifdef  __USE_GNU
> I put the command:
> $ gcc -D__USE_GNU -Wall  parse.c -o parse
> and again get:
> parse.c:38: warning: implicit declaration of function `getline'
> What's wrong??
> When I insert explicit declaration straight into the text of my program
> this warning disappear.

hmm.  okay after a lot of hunting around (the only thing worse than GNU
source code is GNU header files), i see that it'll work if you define
_GNU_SOURCE instead of __USE_GNU.  the reason is that stdio.h includes
features.h.  features.h #undef's __USE_GNU, then #define's it to be 1 if
_GNU_SOURCE is set.  it's very very strange.

Quote:
> "getline(char **lineptr, size_t *n, FILE *stream)
> Before calling getline(), you should place in *lineptr the address
> of a buffer *n bytes long. If this buffer is long enough to hold
> the line, getline() stores the line in this buffer. Otherwise,
> getline() makes the buffer bigger using realloc(), storing
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> the new buffer address back in *lineptr and the increased
> size back in *n."

ahh i see.  you could just set *n to 0 and pass it a NULL pointer for
*lineptr initially then, couldn't you?

Quote:
>> > 3. How to force OS (Linux in my case) to do core dump file on error?

>> i can't remember.  it would be non-ANSI anyway.  if worse comes to worse,
>> you could just do:
>>         raise(SIGSEGV);
> Oh, no. It is a little bit different thing. I don't need
> to send a signal to myself. I would like to get core-dump file
> after my program gets SIGSEGV from OS and dies.
> I don't know should I insert something commands into
> the text of my program for that. Or, may be I should
> tune my OS? Any ideas?

oh i see.  if you're using bash, then 'ulimit -c unlimited' will work.  if
you're using csh and tcsh, then i don't know.

--
              /"\                              m i k e    b u r r e l l

               X        AGAINST HTML MAIL
              / \



Sun, 13 Oct 2002 03:00:00 GMT  
 How to read a config file in C
GetPrivateProfileString may be useful under windoze

Bob Rock

* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!



Sun, 13 Oct 2002 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Newbie: separate big .cs file into small .cs files

2. Config files: best to use struct when reading in data

3. read Config-file module for C?

4. reading config files

5. basic config file read

6. are there better ways to read config file?

7. looking for function to read config file

8. Library for reading config files?

9. read config file

10. Updating the security.config file in the CONFIG directory

11. how to compile a .cs file with config file using csc?

12. resx files needed for cs - files ??

 

 
Powered by phpBB® Forum Software