forked from ElektraInitiative/libelektra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontracts.c
149 lines (135 loc) · 5.85 KB
/
contracts.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* @file
*
* @brief Contract constructors for kdbOpen()
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/
#include "kdb.h"
#include "kdbprivate.h"
#include <stddef.h>
/**
* Sets up a contract for use with kdbOpen() that configures
* the gopts plugin.
*
* You can pass 0 for @p argc **and** `NULL` for @p argv to let gopts lookup
* command line options internally.
* You can also pass `NULL` for @p envp to do the same for environment variables.
*
* @param contract The KeySet into which the contract will be written.
* @param argc The argc value that should be used by gopts.
* @param argv The argv value that should be used by gopts.
* IMPORTANT: The pointer and data behind must be valid
* until after kdbClose() is called.
* @param envp The envp value that should be used by gopts.
* IMPORTANT: The pointer and data behind must be valid
* until after kdbClose() is called.
* @param parentKey The parent key that should be used by gopts.
* Only the key name is copied. The key can be deleted
* immediately after calling this function.
* @param goptsConfig The config that used to mount the gopts plugin.
* This value can be NULL. Only keys in the user:/
* namespace will be used.
*
* @retval -1 if @p contract or @p parentKey is NULL
* @retval -1 if @p argc is 0 and @p argv is not NULL or if @p argc is not 0 and @p argv is NULL
* @retval 0 on success
*/
int elektraGOptsContract (KeySet * contract, int argc, const char * const * argv, const char * const * envp, const Key * parentKey,
KeySet * goptsConfig)
{
if (contract == NULL || (argc == 0) != (argv == NULL) || parentKey == NULL) return -1;
ksAppendKey (contract, keyNew ("system:/elektra/contract/mountglobal/gopts", KEY_END));
if (goptsConfig != NULL)
{
Key * configRoot = keyNew ("user:/", KEY_END);
Key * contractRoot = keyNew ("system:/elektra/contract/mountglobal/gopts", KEY_END);
elektraCursor end;
for (elektraCursor it = ksFindHierarchy (goptsConfig, configRoot, &end); it < end; it++)
{
Key * renamed = keyDup (ksAtCursor (goptsConfig, it), KEY_CP_ALL);
keyReplacePrefix (renamed, configRoot, contractRoot);
ksAppendKey (contract, renamed);
}
keyDel (configRoot);
keyDel (contractRoot);
}
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/parent", KEY_VALUE, keyName (parentKey), KEY_END));
if (argc != 0)
{
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/argc", KEY_BINARY, KEY_SIZE, sizeof (int),
KEY_VALUE, &argc, KEY_END));
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/argv", KEY_BINARY, KEY_SIZE,
sizeof (const char * const *), KEY_VALUE, &argv, KEY_END));
}
if (envp != NULL)
{
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/envp", KEY_BINARY, KEY_SIZE,
sizeof (const char * const *), KEY_VALUE, &envp, KEY_END));
}
return 0;
}
/**
* Sets up a contract for use with kdbOpen() that configures
* the gopts plugin.
*
* NOTE: prefer to use elektraGOptsContract() if possible
*
* You can pass `NULL` for @p args to let gopts lookup command line
* options internally.
* You can also pass `NULL` for @p env to do the same for environment
* variables.
*
* @param contract The KeySet into which the contract will be written.
* @param argsSize The size of the @p args data
* @param args Continuous buffer containing all argv arguments
* separated (and terminated) by zero bytes.
* The whole buffer is copied, so the pointer only has to
* be valid for this function call.
* @param envSize The size of the @p env data
* @param env Continuous buffer containing all environment variables
* separated (and terminated) by zero bytes
* The whole buffer is copied, so the pointer only has to
* be valid for this function call.
* @param parentKey The parent key that should be used by gopts.
* Only the key name is copied. The key can be deleted
* immediately after calling this function.
* @param goptsConfig The config that used to mount the gopts plugin.
* This value can be NULL. Only keys in the user:/
* namespace will be used.
*
* @retval -1 if any of @p contract or @p parentKey is NULL
* @retval 0 on success
*/
int elektraGOptsContractFromStrings (KeySet * contract, size_t argsSize, const char * args, size_t envSize, const char * env,
const Key * parentKey, KeySet * goptsConfig)
{
if (contract == NULL || parentKey == NULL) return -1;
ksAppendKey (contract, keyNew ("system:/elektra/contract/mountglobal/gopts", KEY_END));
if (goptsConfig != NULL)
{
Key * configRoot = keyNew ("user:/", KEY_END);
Key * contractRoot = keyNew ("system:/elektra/contract/mountglobal/gopts", KEY_END);
elektraCursor end;
for (elektraCursor it = ksFindHierarchy (goptsConfig, configRoot, &end); it < end; it++)
{
Key * renamed = keyDup (ksAtCursor (goptsConfig, it), KEY_CP_ALL);
keyReplacePrefix (renamed, configRoot, contractRoot);
ksAppendKey (contract, renamed);
}
keyDel (configRoot);
keyDel (contractRoot);
}
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/parent", KEY_VALUE, keyName (parentKey), KEY_END));
if (args != NULL)
{
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/args", KEY_BINARY, KEY_SIZE, argsSize,
KEY_VALUE, args, KEY_END));
}
if (env != NULL)
{
ksAppendKey (contract, keyNew ("system:/elektra/contract/globalkeyset/gopts/env", KEY_BINARY, KEY_SIZE, envSize, KEY_VALUE,
env, KEY_END));
}
return 0;
}