Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief A plugin that reads configuration files and saves keys on a line by line basis *
5 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
6 : *
7 : */
8 :
9 : #ifndef HAVE_KDBCONFIG
10 : #include "kdbconfig.h"
11 : #endif
12 :
13 : #include "line.h"
14 :
15 : #include <kdbease.h>
16 : #include <kdberrors.h>
17 : #include <kdbproposal.h>
18 :
19 : #include <errno.h>
20 : #include <stddef.h>
21 : // The definition `_WITH_GETLINE` is required for FreeBSD
22 : #define _WITH_GETLINE
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 :
27 91 : static inline KeySet * elektraLineContract (void)
28 : {
29 91 : return ksNew (30, keyNew ("system/elektra/modules/line", KEY_VALUE, "line plugin waits for your orders", KEY_END),
30 : keyNew ("system/elektra/modules/line/exports", KEY_END),
31 : keyNew ("system/elektra/modules/line/exports/get", KEY_FUNC, elektraLineGet, KEY_END),
32 : keyNew ("system/elektra/modules/line/exports/set", KEY_FUNC, elektraLineSet, KEY_END),
33 : #include "readme_line.c"
34 : keyNew ("system/elektra/modules/line/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
35 : }
36 :
37 20 : int elektraLineRead (FILE * fp, KeySet * returned)
38 : {
39 20 : char * value = NULL;
40 20 : size_t len = 0;
41 20 : ssize_t n = 0;
42 20 : Key * read = NULL;
43 :
44 : // Read in each line
45 150 : while ((n = getline (&value, &len, fp)) != -1)
46 : {
47 : // Remove trailing newline
48 110 : if (value[n - 1] == '\n')
49 : {
50 110 : value[n - 1] = '\0';
51 : }
52 110 : read = keyDup (ksTail (returned));
53 110 : if (elektraArrayIncName (read) == -1)
54 : {
55 0 : elektraFree (value);
56 0 : keyDel (read);
57 0 : return -1;
58 : }
59 110 : keySetString (read, value);
60 :
61 110 : ksAppendKey (returned, read);
62 : }
63 20 : elektraFree (value);
64 :
65 20 : return 1;
66 : }
67 :
68 :
69 111 : int elektraLineGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
70 : {
71 : /* get all keys */
72 :
73 111 : if (!strcmp (keyName (parentKey), "system/elektra/modules/line"))
74 : {
75 91 : KeySet * moduleConfig = elektraLineContract ();
76 91 : ksAppend (returned, moduleConfig);
77 91 : ksDel (moduleConfig);
78 91 : return 1;
79 : }
80 :
81 20 : int errnosave = errno;
82 20 : FILE * fp = fopen (keyString (parentKey), "r");
83 :
84 20 : if (!fp)
85 : {
86 0 : ELEKTRA_SET_ERROR_GET (parentKey);
87 0 : errno = errnosave;
88 0 : return -1;
89 : }
90 :
91 20 : Key * b = keyNew (keyName (parentKey), KEY_END);
92 20 : ksAppendKey (returned, keyDup (b)); // start with parentKey
93 20 : keyAddName (b, "#"); // start point for our array
94 20 : ksAppendKey (returned, b);
95 :
96 20 : int ret = elektraLineRead (fp, returned);
97 :
98 : // get rid of startpoint, if it was an empty file
99 20 : keyDel (ksLookup (returned, b, KDB_O_POP));
100 :
101 20 : if (ret == -1)
102 : {
103 0 : ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey, "Could not increment array from %s", keyName (ksTail (returned)));
104 0 : ret = -1;
105 : }
106 20 : else if (feof (fp) == 0)
107 : {
108 0 : ELEKTRA_SET_VALIDATION_SYNTACTIC_ERROR (parentKey, "Invalid line encountered: not at the end of file");
109 0 : ret = -1;
110 : }
111 :
112 20 : fclose (fp);
113 :
114 20 : return ret; /* success */
115 : }
116 :
117 6 : int elektraLineSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
118 : {
119 : /* set all keys */
120 :
121 6 : int errnosave = errno;
122 6 : FILE * fp = fopen (keyString (parentKey), "w");
123 :
124 6 : if (!fp)
125 : {
126 0 : ELEKTRA_SET_ERROR_SET (parentKey);
127 0 : errno = errnosave;
128 0 : return -1;
129 : }
130 :
131 : Key * cur;
132 6 : if (!ksLookup (returned, parentKey, 0))
133 : {
134 : // ignore parentKey if found
135 1 : ksRewind (returned);
136 : }
137 :
138 20 : while ((cur = ksNext (returned)) != 0)
139 : {
140 14 : fprintf (fp, "%s\n", keyString (cur));
141 : }
142 :
143 6 : fclose (fp);
144 :
145 6 : return 1; /* success */
146 : }
147 :
148 177 : Plugin * ELEKTRA_PLUGIN_EXPORT
149 : {
150 : // clang-format off
151 177 : return elektraPluginExport("line",
152 : ELEKTRA_PLUGIN_GET, &elektraLineGet,
153 : ELEKTRA_PLUGIN_SET, &elektraLineSet,
154 : ELEKTRA_PLUGIN_END);
155 : }
|