Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Source for profile plugin
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #include "profile.h"
11 :
12 : #include <kdbhelper.h>
13 :
14 : #include <kdb.h> //actual namespaces
15 : #include <kdbease.h> //elektraKeyGetRelativeName
16 : #include <kdbos.h> //elektraNamespace
17 : #include <stdio.h>
18 : #include <string.h>
19 :
20 : #include <fnmatch.h>
21 :
22 : #define PROFILEPATH "*/sw/*/*/#*/profile"
23 : #define CURRENTPATH "*/sw/*/*/#*/current"
24 :
25 20 : int elektraProfileOpen (Plugin * handle ELEKTRA_UNUSED, Key * errorKey ELEKTRA_UNUSED)
26 : {
27 : // plugin initialization logic
28 20 : KeySet * appendedKeys = NULL;
29 20 : elektraPluginSetData (handle, appendedKeys);
30 20 : return 1; // success
31 : }
32 :
33 20 : int elektraProfileClose (Plugin * handle ELEKTRA_UNUSED, Key * errorKey ELEKTRA_UNUSED)
34 : {
35 : // free all plugin resources and shut it down
36 20 : KeySet * appendedKeys = elektraPluginGetData (handle);
37 20 : if (appendedKeys) ksDel (appendedKeys);
38 20 : return 1; // success
39 : }
40 :
41 0 : static Key * keyDupWithNS (const Key * origKey, elektraNamespace ns)
42 : {
43 0 : Key * newKey = NULL;
44 0 : switch (ns)
45 : {
46 : case KEY_NS_SPEC:
47 0 : newKey = keyNew ("spec", KEY_END);
48 0 : break;
49 : case KEY_NS_DIR:
50 0 : newKey = keyNew ("dir", KEY_END);
51 0 : break;
52 : case KEY_NS_USER:
53 0 : newKey = keyNew ("user", KEY_END);
54 0 : break;
55 : case KEY_NS_SYSTEM:
56 0 : newKey = keyNew ("system", KEY_END);
57 0 : break;
58 : case KEY_NS_PROC:
59 0 : newKey = keyNew ("proc", KEY_END);
60 0 : break;
61 : case KEY_NS_CASCADING:
62 : default:
63 0 : newKey = keyNew ("/", KEY_CASCADING_NAME, KEY_END);
64 0 : break;
65 : }
66 0 : const char * relativeName = keyName (origKey);
67 0 : char * nextPtr = NULL;
68 0 : if (keyName (origKey)[0] == '/')
69 0 : ++relativeName;
70 0 : else if ((nextPtr = strchr (keyName (origKey), '/')))
71 0 : relativeName = (++nextPtr);
72 0 : keyAddName (newKey, relativeName);
73 0 : return newKey;
74 : }
75 :
76 0 : static void linkProfileKeys (KeySet * swKS, KeySet * profileKeys, KeySet * appendedKeys)
77 : {
78 0 : Key * profileCutKey = NULL;
79 0 : Key * profileKey = NULL;
80 0 : const char * profileString = NULL;
81 0 : ksRewind (profileKeys);
82 0 : while ((profileKey = ksNext (profileKeys)) != NULL)
83 : {
84 0 : profileString = keyString (profileKey);
85 0 : if (profileString)
86 : {
87 0 : profileCutKey = keyDup (profileKey);
88 0 : keyAddName (profileCutKey, "..");
89 0 : Key * currentProfileKey = keyDup (profileCutKey);
90 0 : keyAddBaseName (currentProfileKey, "current");
91 0 : keyAddBaseName (profileCutKey, profileString);
92 0 : KeySet * profileKS = ksCut (swKS, profileCutKey);
93 0 : ksRewind (profileKS);
94 : Key * cur;
95 0 : while ((cur = ksNext (profileKS)) != NULL)
96 : {
97 0 : if (!strcmp (keyName (cur), keyName (profileCutKey))) continue;
98 0 : Key * overrideKey = keyDupWithNS (currentProfileKey, KEY_NS_SPEC);
99 0 : const char * relativeName = elektraKeyGetRelativeName (cur, profileCutKey);
100 0 : keyAddName (overrideKey, relativeName);
101 0 : Key * lookupKey = keyDupWithNS (overrideKey, keyGetNamespace (currentProfileKey));
102 0 : if (ksLookup (swKS, lookupKey, KDB_O_NONE))
103 : {
104 0 : keyDel (lookupKey);
105 0 : keyDel (overrideKey);
106 0 : continue;
107 : }
108 0 : keyDel (lookupKey);
109 0 : keySetMeta (overrideKey, "override/#0", keyName (cur));
110 0 : ksAppendKey (swKS, keyDup (overrideKey));
111 0 : ksAppendKey (appendedKeys, keyDup (overrideKey));
112 0 : keyDel (overrideKey);
113 : }
114 0 : keyDel (currentProfileKey);
115 0 : keyDel (profileCutKey);
116 0 : ksAppend (swKS, profileKS);
117 0 : ksDel (profileKS);
118 : }
119 : }
120 0 : }
121 :
122 0 : static void linkDefaultKeys (KeySet * swKS, KeySet * profileParents, KeySet * appendedKeys)
123 : {
124 0 : ksRewind (profileParents);
125 0 : Key * profileParent = NULL;
126 0 : while ((profileParent = ksNext (profileParents)) != NULL)
127 : {
128 0 : Key * defaultCutKey = keyDup (profileParent);
129 0 : keyAddName (defaultCutKey, "%");
130 0 : KeySet * defaultKS = ksCut (swKS, defaultCutKey);
131 0 : ksRewind (defaultKS);
132 : Key * cur;
133 0 : Key * currentProfileKey = keyDup (profileParent);
134 0 : keyAddName (currentProfileKey, "current");
135 0 : while ((cur = ksNext (defaultKS)) != NULL)
136 : {
137 0 : if (!strcmp (keyName (cur), keyName (defaultCutKey))) continue;
138 0 : const char * relativeName = elektraKeyGetRelativeName (cur, defaultCutKey);
139 0 : Key * overrideKey = keyDupWithNS (currentProfileKey, KEY_NS_SPEC);
140 0 : keyAddName (overrideKey, relativeName);
141 0 : Key * existingKey = keyDupWithNS (overrideKey, keyGetNamespace (profileParent));
142 0 : if (ksLookup (swKS, overrideKey, KDB_O_NONE) || ksLookup (swKS, existingKey, KDB_O_NONE))
143 : {
144 0 : keyDel (overrideKey);
145 0 : keyDel (existingKey);
146 0 : continue;
147 : }
148 0 : keyDel (existingKey);
149 0 : keySetMeta (overrideKey, "override/#0", keyName (cur));
150 0 : ksAppendKey (swKS, keyDup (overrideKey));
151 0 : ksAppendKey (appendedKeys, keyDup (overrideKey));
152 0 : keyDel (overrideKey);
153 : }
154 0 : keyDel (currentProfileKey);
155 0 : keyDel (defaultCutKey);
156 0 : ksAppend (swKS, defaultKS);
157 0 : ksDel (defaultKS);
158 : }
159 0 : }
160 :
161 20 : int elektraProfileGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
162 : {
163 20 : if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/profile"))
164 : {
165 20 : KeySet * contract =
166 20 : ksNew (30, keyNew ("system/elektra/modules/profile", KEY_VALUE, "profile plugin waits for your orders", KEY_END),
167 : keyNew ("system/elektra/modules/profile/exports", KEY_END),
168 : keyNew ("system/elektra/modules/profile/exports/open", KEY_FUNC, elektraProfileOpen, KEY_END),
169 : keyNew ("system/elektra/modules/profile/exports/close", KEY_FUNC, elektraProfileClose, KEY_END),
170 : keyNew ("system/elektra/modules/profile/exports/get", KEY_FUNC, elektraProfileGet, KEY_END),
171 : keyNew ("system/elektra/modules/profile/exports/set", KEY_FUNC, elektraProfileSet, KEY_END),
172 : keyNew ("system/elektra/modules/profile/exports/error", KEY_FUNC, elektraProfileError, KEY_END),
173 : #include ELEKTRA_README
174 : keyNew ("system/elektra/modules/profile/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
175 20 : ksAppend (returned, contract);
176 20 : ksDel (contract);
177 :
178 20 : return 1; // success
179 : }
180 : // get all keys
181 0 : Key * swKey = keyNew ("/sw", KEY_CASCADING_NAME, KEY_END);
182 0 : KeySet * swKS = ksCut (returned, swKey);
183 0 : keyDel (swKey);
184 0 : ksRewind (swKS);
185 : Key * cur;
186 :
187 0 : KeySet * appendedKeys = elektraPluginGetData (handle);
188 0 : if (!appendedKeys) appendedKeys = ksNew (0, KS_END);
189 0 : KeySet * profileKeys = ksNew (0, KS_END);
190 0 : while ((cur = ksNext (swKS)) != NULL)
191 : {
192 0 : if (!fnmatch (PROFILEPATH, keyName (cur), FNM_PATHNAME))
193 : {
194 0 : ksAppendKey (profileKeys, cur);
195 : }
196 : }
197 0 : linkProfileKeys (swKS, profileKeys, appendedKeys);
198 0 : ksDel (profileKeys);
199 0 : ksDel (appendedKeys);
200 0 : ksRewind (swKS);
201 0 : KeySet * profileParents = ksNew (0, KS_END);
202 0 : while ((cur = ksNext (swKS)) != NULL)
203 : {
204 0 : if (!fnmatch (CURRENTPATH, keyName (cur), FNM_PATHNAME))
205 : {
206 0 : Key * profileParent = keyDup (cur);
207 0 : keyAddName (profileParent, "..");
208 0 : ksAppendKey (profileParents, keyDup (profileParent));
209 0 : keyDel (profileParent);
210 : }
211 : }
212 0 : linkDefaultKeys (swKS, profileParents, appendedKeys);
213 0 : ksDel (profileParents);
214 0 : ksAppend (returned, swKS);
215 0 : ksDel (swKS);
216 :
217 0 : return 1; // success
218 : }
219 :
220 0 : int elektraProfileSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
221 : {
222 : // get all keys
223 0 : KeySet * appendedKeys = elektraPluginGetData (handle);
224 0 : if (!appendedKeys) return 1;
225 0 : ksRewind (appendedKeys);
226 : Key * cur;
227 0 : while ((cur = ksNext (appendedKeys)) != NULL)
228 : {
229 0 : keyDel (ksLookup (returned, cur, KDB_O_POP));
230 : }
231 0 : ksDel (appendedKeys);
232 0 : elektraPluginSetData (handle, NULL);
233 0 : return 1; // success
234 : }
235 :
236 0 : int elektraProfileError (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
237 : {
238 : // set all keys
239 :
240 0 : return 1; // success
241 : }
242 :
243 20 : Plugin * ELEKTRA_PLUGIN_EXPORT
244 : {
245 : // clang-format off
246 20 : return elektraPluginExport ("profile",
247 : ELEKTRA_PLUGIN_OPEN, &elektraProfileOpen,
248 : ELEKTRA_PLUGIN_CLOSE, &elektraProfileClose,
249 : ELEKTRA_PLUGIN_GET, &elektraProfileGet,
250 : ELEKTRA_PLUGIN_SET, &elektraProfileSet,
251 : ELEKTRA_PLUGIN_ERROR, &elektraProfileError,
252 : ELEKTRA_PLUGIN_END);
253 : }
254 :
|