LCOV - code coverage report
Current view: top level - src/plugins/c - c.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 75 96 78.1 %
Date: 2019-09-12 12:28:41 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for c plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include "c.h"
      11             : 
      12             : #include <kdberrors.h>
      13             : #include <kdbhelper.h>
      14             : 
      15             : #include <ctype.h>
      16             : #include <stdio.h>
      17             : 
      18             : static const char * toEscape = "\"'\\?\n\r\t";
      19             : static const char * escapes = "\"'\\?nrt";
      20             : 
      21             : static const char * hex = "0123456789abcdef";
      22             : 
      23        1106 : static char * escapeString (char ** str)
      24             : {
      25        1106 :         size_t size = 0;
      26        9304 :         for (char * cur = *str; *cur != '\0'; ++cur)
      27             :         {
      28        8198 :                 unsigned char c = *cur;
      29             : 
      30        8198 :                 if (strchr (toEscape, c) != NULL)
      31             :                 {
      32           0 :                         size += 2;
      33             :                 }
      34        8198 :                 else if (isprint (c))
      35             :                 {
      36        8198 :                         ++size;
      37             :                 }
      38             :                 else
      39             :                 {
      40           0 :                         size += 4;
      41             :                 }
      42             :         }
      43             : 
      44        1106 :         if (size == 0)
      45             :         {
      46          48 :                 return *str;
      47             :         }
      48             : 
      49        1058 :         char * newStr = elektraMalloc (size + 1);
      50        1058 :         char * newCur = newStr;
      51        9256 :         for (char * cur = *str; *cur != '\0'; ++cur)
      52             :         {
      53        8198 :                 unsigned char c = *cur;
      54        8198 :                 char * e = strchr (toEscape, c);
      55             : 
      56        8198 :                 if (e != NULL)
      57             :                 {
      58           0 :                         char escaped = escapes[e - toEscape];
      59           0 :                         *newCur = '\\';
      60           0 :                         ++newCur;
      61           0 :                         *newCur = escaped;
      62           0 :                         ++newCur;
      63             :                 }
      64        8198 :                 else if (isprint (c))
      65             :                 {
      66        8198 :                         *newCur = c;
      67        8198 :                         ++newCur;
      68             :                 }
      69             :                 else
      70             :                 {
      71           0 :                         *newCur = '\\';
      72           0 :                         ++newCur;
      73           0 :                         *newCur = 'x';
      74           0 :                         ++newCur;
      75           0 :                         *newCur = hex[c >> 4u];
      76           0 :                         ++newCur;
      77           0 :                         *newCur = hex[c & 0xFu];
      78           0 :                         ++newCur;
      79             :                 }
      80             :         }
      81        1058 :         *newCur = '\0';
      82        1058 :         elektraFree (*str);
      83        1058 :         *str = newStr;
      84        1058 :         return newStr;
      85             : }
      86             : 
      87             : /**
      88             :  * Generate a C-Style key and stream it.
      89             :  *
      90             :  * This keyset can be used to include as c-code for
      91             :  * applikations using elektra.
      92             :  *
      93             :  * @param key the key object to work with
      94             :  * @param stream the file pointer where to send the stream
      95             :  * @param options KDB_O_SHOWINDICES, KDB_O_IGNORE_COMMENT, KDB_O_SHOWINFO
      96             :  * @retval 1 on success
      97             :  * @ingroup stream
      98             :  */
      99         210 : int keyGenerate (const Key * key, FILE * stream, option_t options)
     100             : {
     101         210 :         size_t n = keyGetNameSize (key);
     102         210 :         if (n > 1)
     103             :         {
     104         192 :                 char * nam = (char *) elektraMalloc (n);
     105         192 :                 if (nam == NULL) return -1;
     106         192 :                 keyGetName (key, nam, n);
     107         192 :                 fprintf (stream, "\tkeyNew (\"%s\"", escapeString (&nam));
     108         192 :                 elektraFree (nam);
     109             :         }
     110          18 :         else if (n == 1)
     111             :         {
     112          18 :                 fprintf (stream, "\tkeyNew(\"\"");
     113             :         }
     114             : 
     115         210 :         size_t s = keyGetValueSize (key);
     116         210 :         if (s > 1)
     117             :         {
     118          18 :                 char * str = (char *) elektraMalloc (s);
     119          18 :                 if (str == NULL) return -1;
     120          18 :                 if (keyIsBinary (key))
     121             :                 {
     122           0 :                         keyGetBinary (key, str, s);
     123           0 :                         fprintf (stream, ", KEY_SIZE, \"%zd\"", keyGetValueSize (key));
     124             :                 }
     125             :                 else
     126             :                 {
     127          18 :                         keyGetString (key, str, s);
     128             :                 }
     129          18 :                 fprintf (stream, ", KEY_VALUE, \"%s\"", escapeString (&str));
     130          18 :                 elektraFree (str);
     131             :         }
     132             : 
     133             :         const Key * meta;
     134         210 :         Key * dup = keyDup (key);
     135         210 :         keyRewindMeta (dup);
     136         868 :         while ((meta = keyNextMeta (dup)))
     137             :         {
     138         448 :                 char * metaNam = elektraStrDup (keyName (meta));
     139         448 :                 char * metaStr = elektraStrDup (keyString (meta));
     140         448 :                 fprintf (stream, ", KEY_META, \"%s\", \"%s\"", escapeString (&metaNam), escapeString (&metaStr));
     141         448 :                 elektraFree (metaNam);
     142         448 :                 elektraFree (metaStr);
     143             :         }
     144         210 :         keyDel (dup);
     145             : 
     146         210 :         fprintf (stream, ", KEY_END)");
     147             : 
     148             :         if (options == 0) return 1; /* dummy to make icc happy */
     149             :         return 1;
     150             : }
     151             : 
     152             : 
     153             : /**
     154             :  * Generate a C-Style keyset and stream it.
     155             :  *
     156             :  * This keyset can be used to include as c-code for
     157             :  * applikations using elektra.
     158             :  *
     159             :  * The options takes the same options as kdbGet()
     160             :  * and kdbSet().
     161             :  *
     162             :  * @param ks the keyset to work with
     163             :  * @param stream the file pointer where to send the stream
     164             :  * @param options which keys not to output
     165             :  * @retval 1 on success
     166             :  * @ingroup stream
     167             :  */
     168          54 : int ksGenerate (const KeySet * ks, FILE * stream, option_t options)
     169             : {
     170             :         Key * key;
     171          54 :         KeySet * cks = ksDup (ks);
     172             : 
     173          54 :         ksRewind (cks);
     174             : 
     175          54 :         fprintf (stream, "ksNew (%d,\n", (int) ksGetSize (cks));
     176         318 :         while ((key = ksNext (cks)) != 0)
     177             :         {
     178         210 :                 if (options & KDB_O_INACTIVE)
     179           0 :                         if (key && keyIsInactive (key)) continue;
     180             : 
     181         210 :                 keyGenerate (key, stream, options);
     182         210 :                 fprintf (stream, ",\n");
     183             :         }
     184          54 :         fprintf (stream, "\tKS_END);\n");
     185             : 
     186          54 :         ksDel (cks);
     187          54 :         return 1;
     188             : }
     189             : 
     190          74 : int elektraCGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     191             : {
     192          74 :         if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/c"))
     193             :         {
     194          74 :                 KeySet * contract = ksNew (30, keyNew ("system/elektra/modules/c", KEY_VALUE, "c plugin waits for your orders", KEY_END),
     195             :                                            keyNew ("system/elektra/modules/c/exports", KEY_END),
     196             :                                            keyNew ("system/elektra/modules/c/exports/get", KEY_FUNC, elektraCGet, KEY_END),
     197             :                                            keyNew ("system/elektra/modules/c/exports/set", KEY_FUNC, elektraCSet, KEY_END),
     198             :                                            keyNew ("system/elektra/modules/c/exports/checkconf", KEY_FUNC, elektraCCheckConfig, KEY_END),
     199             : #include ELEKTRA_README
     200             :                                            keyNew ("system/elektra/modules/c/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
     201          74 :                 ksAppend (returned, contract);
     202          74 :                 ksDel (contract);
     203             : 
     204          74 :                 return 1; // success
     205             :         }
     206             :         // get all keys
     207             : 
     208             :         return 1; // success
     209             : }
     210             : 
     211          54 : int elektraCSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     212             : {
     213          54 :         FILE * fp = fopen (keyString (parentKey), "w");
     214             : 
     215          54 :         if (!fp)
     216             :         {
     217           0 :                 ELEKTRA_SET_ERROR_SET (parentKey);
     218             :                 return -1;
     219             :         }
     220             : 
     221          54 :         ksGenerate (returned, fp, 0);
     222             : 
     223          54 :         fclose (fp);
     224          54 :         return 1; // success
     225             : }
     226             : 
     227           0 : int elektraCCheckConfig (Key * errorKey ELEKTRA_UNUSED, KeySet * conf ELEKTRA_UNUSED)
     228             : {
     229             :         // validate plugin configuration
     230             :         // this function is optional
     231             : 
     232             :         // the return codes have the following meaning:
     233             :         // 0: The configuration was OK and has not been changed
     234             :         // 1: The configuration has been changed and now it is OK
     235             :         // -1: The configuration was not OK and could not be fixed. An error has to be set to errorKey.
     236           0 :         return 0;
     237             : }
     238             : 
     239          74 : Plugin * ELEKTRA_PLUGIN_EXPORT
     240             : {
     241             :         // clang-format off
     242          74 :         return elektraPluginExport ("c",
     243             :                 ELEKTRA_PLUGIN_GET,     &elektraCGet,
     244             :                 ELEKTRA_PLUGIN_SET,     &elektraCSet,
     245             :                 ELEKTRA_PLUGIN_END);
     246             : }
     247             : 

Generated by: LCOV version 1.13