Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Source for dbus plugin
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #ifndef HAVE_KDBCONFIG
11 : #include "kdbconfig.h"
12 : #endif
13 :
14 : #include "dbus.h"
15 :
16 : #include <kdbhelper.h>
17 :
18 20 : int elektraDbusOpen (Plugin * handle, Key * errorKey ELEKTRA_UNUSED)
19 : {
20 20 : ElektraDbusPluginData * data = elektraPluginGetData (handle);
21 :
22 20 : if (!data)
23 : {
24 20 : data = elektraMalloc (sizeof (*data));
25 20 : data->keys = NULL;
26 20 : data->systemBus = NULL;
27 20 : data->sessionBus = NULL;
28 : }
29 20 : elektraPluginSetData (handle, data);
30 :
31 20 : return 1; /* success */
32 : }
33 :
34 20 : int elektraDbusGet (Plugin * handle, KeySet * returned, Key * parentKey)
35 : {
36 20 : if (!strcmp (keyName (parentKey), "system/elektra/modules/dbus"))
37 : {
38 20 : KeySet * contract =
39 20 : ksNew (30, keyNew ("system/elektra/modules/dbus", KEY_VALUE, "dbus plugin waits for your orders", KEY_END),
40 : keyNew ("system/elektra/modules/dbus/exports", KEY_END),
41 : keyNew ("system/elektra/modules/dbus/exports/open", KEY_FUNC, elektraDbusOpen, KEY_END),
42 : keyNew ("system/elektra/modules/dbus/exports/get", KEY_FUNC, elektraDbusGet, KEY_END),
43 : keyNew ("system/elektra/modules/dbus/exports/set", KEY_FUNC, elektraDbusSet, KEY_END),
44 : keyNew ("system/elektra/modules/dbus/exports/close", KEY_FUNC, elektraDbusClose, KEY_END),
45 : #include ELEKTRA_README
46 : keyNew ("system/elektra/modules/dbus/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
47 20 : ksAppend (returned, contract);
48 20 : ksDel (contract);
49 :
50 20 : return 1; /* success */
51 : }
52 :
53 : // remember all keys
54 0 : ElektraDbusPluginData * pluginData = elektraPluginGetData (handle);
55 0 : ELEKTRA_NOT_NULL (pluginData);
56 :
57 0 : KeySet * ks = pluginData->keys;
58 0 : if (ks) ksDel (ks);
59 0 : pluginData->keys = ksDup (returned);
60 :
61 0 : return 1; /* success */
62 : }
63 :
64 : /**
65 : * @internal
66 : * Announce multiple keys with same signal name.
67 : *
68 : * @param ks key set containing modified keys
69 : * @param signalName signal name to use
70 : * @param busType D-Bus bus type
71 : * @param data plugin data containing D-Bus connections, etc.
72 : */
73 0 : static void announceKeys (KeySet * ks, const char * signalName, DBusBusType busType, ElektraDbusPluginData * data)
74 : {
75 0 : ELEKTRA_NOT_NULL (ks);
76 0 : ELEKTRA_NOT_NULL (signalName);
77 0 : ELEKTRA_NOT_NULL (data);
78 :
79 0 : ksRewind (ks);
80 0 : Key * k = 0;
81 0 : while ((k = ksNext (ks)) != 0)
82 : {
83 0 : elektraDbusSendMessage (data, busType, keyName (k), signalName);
84 : }
85 0 : }
86 :
87 0 : int elektraDbusSet (Plugin * handle, KeySet * returned, Key * parentKey)
88 : {
89 0 : ElektraDbusPluginData * pluginData = elektraPluginGetData (handle);
90 0 : ELEKTRA_NOT_NULL (pluginData);
91 :
92 0 : KeySet * oldKeys = pluginData->keys;
93 : // because elektraLogchangeGet will always be executed before elektraLogchangeSet
94 : // we know that oldKeys must exist here!
95 0 : ksRewind (oldKeys);
96 0 : ksRewind (returned);
97 :
98 0 : KeySet * addedKeys = ksDup (returned);
99 0 : KeySet * changedKeys = ksNew (0, KS_END);
100 0 : KeySet * removedKeys = ksNew (0, KS_END);
101 :
102 0 : Key * k = 0;
103 0 : while ((k = ksNext (oldKeys)) != 0)
104 : {
105 0 : Key * p = ksLookup (addedKeys, k, KDB_O_POP);
106 : // Note: keyDel not needed, because at least two references exist
107 0 : if (p)
108 : {
109 0 : if (keyNeedSync (p))
110 : {
111 0 : ksAppendKey (changedKeys, p);
112 : }
113 : }
114 : else
115 : {
116 0 : ksAppendKey (removedKeys, k);
117 : }
118 : }
119 :
120 0 : Key * resolvedParentKey = parentKey;
121 : // Resolve cascaded parent key to get its namespace
122 0 : if (!strncmp (keyName (parentKey), "/", 1))
123 : {
124 0 : resolvedParentKey = ksLookup (returned, parentKey, 0);
125 : }
126 0 : int announceSession = 0;
127 0 : int announceSystem = 0;
128 0 : if (resolvedParentKey != NULL)
129 : {
130 0 : announceSession = !strncmp (keyName (resolvedParentKey), "user", 4);
131 0 : announceSystem = !strncmp (keyName (resolvedParentKey), "system", 6);
132 : }
133 :
134 0 : if (!strncmp (keyString (ksLookupByName (elektraPluginGetConfig (handle), "/announce", 0)), "once", 4))
135 : {
136 0 : if (announceSession) elektraDbusSendMessage (pluginData, DBUS_BUS_SESSION, keyName (resolvedParentKey), "Commit");
137 0 : if (announceSystem) elektraDbusSendMessage (pluginData, DBUS_BUS_SYSTEM, keyName (resolvedParentKey), "Commit");
138 : }
139 : else
140 : {
141 0 : if (announceSession)
142 : {
143 0 : announceKeys (addedKeys, "KeyAdded", DBUS_BUS_SESSION, pluginData);
144 0 : announceKeys (changedKeys, "KeyChanged", DBUS_BUS_SESSION, pluginData);
145 0 : announceKeys (removedKeys, "KeyDeleted", DBUS_BUS_SESSION, pluginData);
146 : }
147 0 : if (announceSystem)
148 : {
149 0 : announceKeys (addedKeys, "KeyAdded", DBUS_BUS_SYSTEM, pluginData);
150 0 : announceKeys (changedKeys, "KeyChanged", DBUS_BUS_SYSTEM, pluginData);
151 0 : announceKeys (removedKeys, "KeyDeleted", DBUS_BUS_SYSTEM, pluginData);
152 : }
153 : }
154 :
155 :
156 0 : ksDel (oldKeys);
157 0 : ksDel (addedKeys);
158 0 : ksDel (changedKeys);
159 0 : ksDel (removedKeys);
160 :
161 : // for next invocation of elektraLogchangeSet, remember our current keyset
162 0 : pluginData->keys = ksDup (returned);
163 :
164 0 : return 1; /* success */
165 : }
166 :
167 20 : int elektraDbusClose (Plugin * handle, Key * parentKey ELEKTRA_UNUSED)
168 : {
169 20 : ElektraDbusPluginData * pluginData = elektraPluginGetData (handle);
170 20 : if (pluginData == NULL)
171 : {
172 : return 1;
173 : }
174 :
175 20 : KeySet * ks = pluginData->keys;
176 20 : if (ks) ksDel (ks);
177 :
178 20 : if (pluginData->systemBus)
179 : {
180 0 : dbus_connection_unref (pluginData->systemBus);
181 0 : pluginData->systemBus = NULL;
182 : }
183 20 : if (pluginData->sessionBus)
184 : {
185 0 : dbus_connection_unref (pluginData->sessionBus);
186 0 : pluginData->sessionBus = NULL;
187 : }
188 :
189 20 : elektraFree (pluginData);
190 20 : elektraPluginSetData (handle, NULL);
191 :
192 20 : return 1; /* success */
193 : }
194 :
195 20 : Plugin * ELEKTRA_PLUGIN_EXPORT
196 : {
197 : // clang-format off
198 20 : return elektraPluginExport("dbus",
199 : ELEKTRA_PLUGIN_OPEN, &elektraDbusOpen,
200 : ELEKTRA_PLUGIN_GET, &elektraDbusGet,
201 : ELEKTRA_PLUGIN_SET, &elektraDbusSet,
202 : ELEKTRA_PLUGIN_CLOSE, &elektraDbusClose,
203 : ELEKTRA_PLUGIN_END);
204 : }
|