Libconfig Reading and Editing/Writing C Tutorial

One of the best libraries I've stumbled across for libraries (minus glib) is Libconfig. It provides a nice way to read in, manage and edit configuration files in a simple unified way - my favorite feature of all is that my config files will look consistent! Its fairly well documented, but actual step through tutorials and explanations need a bit of work. Here are two example functions that should help you out:

The configuration file - example.cfg

Okay looking at the config, there are a couple points to note: the configuration file has containers, the first childContainer is a group, and the second is an array (this is the PITA). I have also only used the String type

  1. rootContainer :
  2. {
  3.   childContainer :
  4.   {
  5.     value = "value1";
  6.     value2 = "value2";
  7.   };
  8.  anotherChildContainer = (
  9.  {
  10.    childval = "1"
  11.  },
  12.  {
  13.   childval = "2"
  14.  },
  15.  {
  16.   childval = "3"
  17.  } );
  18. };

Example program

Here is an example program that will perform different functions if you use soft links for arg0. Note that you will need libconfig installed for this to compile and to create the aliases the command:

  1. ln -s exampleProg setChildVar
  2. ln -s exampleProg getChildVar
  3. ln -s exampleProg setArrVar
  4. ln -s exampleProg getArrVar

To compile run the following command:

gcc -Wall -lconfig -o exampleProg libconfigEx.c

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <libconfig.h>
  7.  
  8. #define SUCCESS 0
  9. #define ERROR -1
  10.  
  11. #define SET_STRING_CONFIG_TYPE 0
  12. #define GET_STRING_CONFIG_TYPE 1
  13. #define CONFIGFILE "example.cfg"
  14.  
  15. /**
  16.  * int childVarUtil(int varType, char *variableName, char *value)
  17.  *
  18.  * @brief utility function that will get/set any variable in the CHILD section
  19.  * of the configuration file.
  20.  *
  21.  * @param int varType
  22.  * @param char *variableName
  23.  * @param char *value
  24.  * @return int 0 for success, or -1 for error
  25.  */
  26. int childVarUtil(int varType, char *variableName, char *value)
  27. {
  28.         config_t cfg;
  29.         config_setting_t *setting;
  30.         const char *str;
  31.  
  32.         config_init(&cfg);
  33.  
  34.         /* Read the file. If there is an error, report it and exit. */
  35.         if (!config_read_file(&cfg, CONFIGFILE)) {
  36.                 fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
  37.                         config_error_line(&cfg), config_error_text(&cfg));
  38.                 config_destroy(&cfg);
  39.         }
  40.  
  41.         switch (varType) {
  42.         case (GET_STRING_CONFIG_TYPE):
  43.  
  44.                 setting = config_lookup(&cfg, variableName);
  45.                 if (setting == NULL) {
  46.                         config_destroy(&cfg);
  47.                         return (ERROR);
  48.                 }
  49.                 config_lookup_string(&cfg, variableName, &str);
  50.                 printf("%s\n", str);
  51.                 config_destroy(&cfg);
  52.                 return (SUCCESS);
  53.  
  54.                 break;
  55.         case (SET_STRING_CONFIG_TYPE):
  56.  
  57.                 setting = config_lookup(&cfg, variableName);
  58.                 if (setting == NULL) {
  59.                         config_destroy(&cfg);
  60.                         return (ERROR);
  61.                 }
  62.                 config_setting_set_string(setting, value);
  63.                 /* Write out the updated configuration. */
  64.                 if (!config_write_file(&cfg, CONFIGFILE)) {
  65.                         fprintf(stderr, "Error while writing file.\n");
  66.                         config_destroy(&cfg);
  67.                         return (ERROR);
  68.                 }
  69.                 config_destroy(&cfg);
  70.                 return (SUCCESS);
  71.  
  72.                 break;
  73.         default:
  74.                 break;
  75.         }
  76.  
  77.         config_destroy(&cfg);
  78.  
  79.         return (SUCCESS);
  80. }
  81.  
  82. /**
  83.  * int arrVarUtil(int varType, char *identifier, char *variableName, char *value)
  84.  *
  85.  * @brief utility function that will get/set any variable in the ANOTHERCHILD section
  86.  * of the configuration file.  Notice that it is tricky when dealing with a
  87.  * sub-element that has a string.
  88.  *
  89.  * @param int varType GET or SET
  90.  * @param char *variableName
  91.  * @param char * value
  92.  * @return int 0 for success, or -1 for error
  93.  */
  94. int arrVarUtil(int varType, char *variableName, char *value)
  95. {
  96.         config_t cfg;
  97.         config_setting_t *root, *setting;
  98.         const char *varName;
  99.  
  100.         config_init(&cfg);
  101.  
  102.         /* Read the file. If there is an error, report it and exit. */
  103.         if (!config_read_file(&cfg, CONFIGFILE)) {
  104.                 fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
  105.                         config_error_line(&cfg), config_error_text(&cfg));
  106.                 config_destroy(&cfg);
  107.         }
  108.  
  109.         /* DO the parent containers exist? */
  110.         root = config_root_setting(&cfg);
  111.  
  112.         setting = config_setting_get_member(root, "rootContainer");
  113.         if (!setting)
  114.                 setting = config_setting_add(root, "rootContainer", CONFIG_TYPE_GROUP);
  115.  
  116.         setting = config_setting_get_member(setting, "anotherChildContainer");
  117.         if (!setting)
  118.                 setting = config_setting_add(setting, "anotherChildContainer", CONFIG_TYPE_LIST);
  119.  
  120.         /* If there is a licenses section */
  121.         if (setting != NULL) {
  122.                 int count = config_setting_length(setting);
  123.                 int i = 0;
  124.  
  125.                 for (i = 0; i < count; ++i) {
  126.                         config_setting_t *element = config_setting_get_elem(setting, i);
  127.  
  128.                         if (!( config_setting_lookup_string(element, variableName, &varName))) {
  129.                                 continue;
  130.                         }
  131.                        
  132.                         switch (varType) {
  133.                         case (GET_STRING_CONFIG_TYPE):
  134.  
  135.                                 /* Just print out the lsm info */
  136.                                 printf("%s\n", varName);
  137.                                 config_destroy(&cfg);
  138.                                 return (SUCCESS);
  139.  
  140.                                 break;
  141.  
  142.                         case (SET_STRING_CONFIG_TYPE):
  143.  
  144.                                 /* Notice that there is no simple update and replace */
  145.                                 config_setting_remove(element, variableName);
  146.                                 setting = config_setting_add(element, variableName, CONFIG_TYPE_STRING);
  147.                                 config_setting_set_string(setting, value);
  148.  
  149.                                 /* Write out the updated configuration. */
  150.                                 if (!config_write_file(&cfg, CONFIGFILE)) {
  151.                                         fprintf(stderr, "Error while writing file.\n");
  152.                                         config_destroy(&cfg);
  153.                                         return (ERROR);
  154.                                 }
  155.                                 config_destroy(&cfg);
  156.                                 return (SUCCESS);
  157.  
  158.                                 break;
  159.  
  160.                         default:
  161.                                 break;
  162.                         }
  163.  
  164.                 }
  165.                 putchar('\n');
  166.         }
  167.  
  168.         config_destroy(&cfg);
  169.  
  170.         return (SUCCESS);
  171. }
  172.  
  173. /**
  174.  * int main(int argc, char **argv)
  175.  */
  176. int main(int argc, char **argv)
  177. {
  178.  
  179.         if (strstr(argv[0], "setChildVar") != NULL) {
  180.  
  181.                 char appendStr[56] = "rootContainer.childContainer.";
  182.                 strcat(appendStr, argv[1]);
  183.                 if (childVarUtil(SET_STRING_CONFIG_TYPE, appendStr, argv[2]) != 0) {
  184.                         return (ERROR);
  185.                 }
  186.                 return SUCCESS;
  187.  
  188.         } else if (strstr(argv[0], "setArrVar") != NULL) {
  189.  
  190.                 if (arrVarUtil(SET_STRING_CONFIG_TYPE, argv[1], argv[2]) != 0) {
  191.                         return (ERROR);
  192.                 }
  193.                 return SUCCESS;
  194.  
  195.         } else if (strstr(argv[0], "getChildVar") != NULL) {
  196.  
  197.                 char appendStr[56] = "rootContainer.childContainer.";
  198.                 strcat(appendStr, argv[1]);
  199.                 if (childVarUtil(GET_STRING_CONFIG_TYPE, appendStr, NULL) != 0) {
  200.                         return (ERROR);
  201.                 }
  202.                 return SUCCESS;
  203.  
  204.         } else if (strstr(argv[0], "getArrVar") != NULL) {
  205.  
  206.                 if (arrVarUtil(GET_STRING_CONFIG_TYPE, argv[1], argv[2]) != 0) {
  207.                         return (ERROR);
  208.                 }
  209.                 return SUCCESS;
  210.  
  211.         } else {
  212.                 fprintf(stderr, "Error");
  213.                 return (ERROR);
  214.         }
  215. }

I didn't really go too into depth, but this should get you reading and give you a better understanding of what to do when wanting to read/write configs using libconfig

Example Usage

Here are some examples for program usage:

  1. ./getChildVar value
  2. ./setChildVar value TEST
  3. ./getArrVar childval 1
  4. ./setArrVar childval 10

Blog tags: 

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.