1 kumpf 1.2 /*
|
2 martin 1.5 //%LICENSE////////////////////////////////////////////////////////////////
|
3 martin 1.6 //
|
4 martin 1.5 // Licensed to The Open Group (TOG) under one or more contributor license
5 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
6 // this work for additional information regarding copyright ownership.
7 // Each contributor licenses this file to you under the OpenPegasus Open
8 // Source License; you may not use this file except in compliance with the
9 // License.
|
10 martin 1.6 //
|
11 martin 1.5 // Permission is hereby granted, free of charge, to any person obtaining a
12 // copy of this software and associated documentation files (the "Software"),
13 // to deal in the Software without restriction, including without limitation
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 // and/or sell copies of the Software, and to permit persons to whom the
16 // Software is furnished to do so, subject to the following conditions:
|
17 martin 1.6 //
|
18 martin 1.5 // The above copyright notice and this permission notice shall be included
19 // in all copies or substantial portions of the Software.
|
20 martin 1.6 //
|
21 martin 1.5 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
22 martin 1.6 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
23 martin 1.5 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
28 martin 1.6 //
|
29 martin 1.5 //////////////////////////////////////////////////////////////////////////
|
30 kumpf 1.2 */
31
32 #include <string.h>
33 #include "Defines.h"
34 #include "Macro.h"
35 #include "Strlcpy.h"
36 #include "Strlcat.h"
37 #include "Log.h"
38 #include "Config.h"
39 #include "Globals.h"
40 #include "Path.h"
41 #include <assert.h>
42
43 /*
44 **==============================================================================
45 **
46 ** Macro
47 **
48 ** This structure defines a macro (a name-value pair).
49 **
50 **==============================================================================
51 kumpf 1.2 */
52
53 struct Macro
54 {
55 char* name;
56 char* value;
57 struct Macro* next;
58 };
59
60 /*
61 **==============================================================================
62 **
63 ** _macros
64 **
65 ** The list of process macros.
66 **
67 **==============================================================================
68 */
69
70 static struct Macro* _macros = 0;
71
72 kumpf 1.2 /*
73 **==============================================================================
74 **
75 ** FindMacro()
76 **
77 ** Find the value of the named macro. Return pointer to value or NULL if
78 ** not found.
79 **
80 **==============================================================================
81 */
82
83 const char* FindMacro(const char* name)
84 {
85 const struct Macro* p;
86
87 for (p = _macros; p; p = p->next)
88 {
89 if (strcmp(p->name, name) == 0)
|
90 dmitry.mikulin 1.4 {
|
91 kumpf 1.2 return p->value;
|
92 dmitry.mikulin 1.4 }
|
93 kumpf 1.2 }
94
95 /* Not found. */
96 return NULL;
97 }
98
99 /*
100 **==============================================================================
101 **
102 ** DefineMacro()
103 **
104 ** Add a new macro to the macro list.
105 **
106 **==============================================================================
107 */
108
109 int DefineMacro(const char* name, const char* value)
110 {
111 struct Macro* macro;
112
113 /* Reject if the macro is already defined. */
114 kumpf 1.2
115 if (FindMacro(name) != NULL)
|
116 dmitry.mikulin 1.4 {
|
117 kumpf 1.2 return -1;
|
118 dmitry.mikulin 1.4 }
|
119 kumpf 1.2
120 /* Create new macro. */
121
|
122 dmitry.mikulin 1.4 if ((macro = (struct Macro*)malloc(sizeof(struct Macro))) == NULL)
123 {
124 return -1;
125 }
|
126 kumpf 1.2 macro->name = strdup(name);
127 macro->value = strdup(value);
128
129 /* Add to end of list. */
130
131 {
132 struct Macro* p;
133 struct Macro* prev = NULL;
134
135 for (p = _macros; p; p = p->next)
|
136 dmitry.mikulin 1.4 {
|
137 kumpf 1.2 prev = p;
|
138 dmitry.mikulin 1.4 }
|
139 kumpf 1.2
140 if (prev)
|
141 dmitry.mikulin 1.4 {
|
142 kumpf 1.2 prev->next = macro;
|
143 dmitry.mikulin 1.4 }
|
144 kumpf 1.2 else
|
145 dmitry.mikulin 1.4 {
|
146 kumpf 1.2 _macros = macro;
|
147 dmitry.mikulin 1.4 }
|
148 kumpf 1.2
149 macro->next = NULL;
150 }
151
152 return 0;
153 }
154
155 /*
156 **==============================================================================
157 **
158 ** UndefineMacro()
159 **
160 ** Remove the given macro from the macro table.
161 **
162 **==============================================================================
163 */
164
165 int UndefineMacro(const char* name)
166 {
167 struct Macro* p;
168 struct Macro* prev;
169 kumpf 1.2
170 for (p = _macros, prev = 0; p; p = p->next)
171 {
172 if (strcmp(p->name, name) == 0)
173 {
174 if (prev)
|
175 dmitry.mikulin 1.4 {
|
176 kumpf 1.2 prev->next = p->next;
|
177 dmitry.mikulin 1.4 }
|
178 kumpf 1.2 else
|
179 dmitry.mikulin 1.4 {
|
180 kumpf 1.2 _macros = p->next;
|
181 dmitry.mikulin 1.4 }
|
182 kumpf 1.2
183 free(p->name);
184 free(p->value);
185 free(p);
186 return 0;
187 }
188
189 prev = p;
190 }
191
192 /* Not found. */
193 return -1;
194 }
195
196 /*
197 **==============================================================================
198 **
199 ** ExpandMacros()
200 **
201 ** Expand all macros in *input*. Leave result in *output*.
202 **
203 kumpf 1.2 **==============================================================================
204 */
205
206 int ExpandMacros(const char* input, char output[EXECUTOR_BUFFER_SIZE])
207 {
208 char buffer[EXECUTOR_BUFFER_SIZE];
209 char* p;
210
211 /* Make copy of input since we'll need to destroy it. */
212
213 Strlcpy(buffer, input, sizeof(buffer));
214 output[0] = '\0';
215
216 /* Traverse buffer, copying characters and expanding macros as we go. */
217
218 for (p = buffer; *p; )
219 {
220 /* Look for start of macro. */
221
222 if (p[0] == '$' && p[1] == '{')
223 {
224 kumpf 1.2 char* q;
225
226 /* Set p and q as follows.
227 *
228 * p q
229 * | |
230 * v v
231 * "...${MY_MACRO}..."
232 */
233
234 p += 2;
235
236 /* Find end of macro. */
237
238 for (q = p; *q && *q != '}'; q++)
239 ;
240
241 if (*q != '}')
242 {
243 Log(LL_SEVERE, "ExpandMacros(): corrupt input: %s", input);
244 return -1;
245 kumpf 1.2 }
246
247 /* Replace '}' with null-terminator. */
248
249 *q = '\0';
250
251 /* Lookup macro and append value. */
252
253 {
254 const char* value;
255 value = FindMacro(p);
256
257 if (!value)
258 {
259 Log(LL_SEVERE, "ExpandMacros(): Undefined macro: %s", p);
260 return -1;
261 }
262
263 Strlcat(output, value, EXECUTOR_BUFFER_SIZE);
264 }
265
266 kumpf 1.2 p = q + 1;
267 }
268 else
269 {
270 /* Append current character to output. */
271
272 char two[2];
273 two[0] = *p++;
274 two[1] = '\0';
275
276 Strlcat(output, two, EXECUTOR_BUFFER_SIZE);
277 }
278 }
279
280 return 0;
281 }
282
283 /*
284 **==============================================================================
285 **
286 ** DefineConfigPathMacro()
287 kumpf 1.2 **
288 ** Define a new path macro whose value is taken from the given
289 ** configuration parameter. If no such configuration parameter is defined,
290 ** use the defaultPath.
291 **
292 **==============================================================================
293 */
294
295 int DefineConfigPathMacro(const char* configParam, const char* defaultPath)
296 {
297 char path[EXECUTOR_BUFFER_SIZE];
298 int status;
299
300 status = 0;
301
302 do
303 {
304 char buffer[EXECUTOR_BUFFER_SIZE];
305
306 /* First try to get value from configuration. */
307
308 kumpf 1.2 if (GetConfigParam(configParam, buffer) == 0)
309 {
310 if (buffer[0] == '/')
311 {
312 Strlcpy(path, buffer, sizeof(path));
313 break;
314 }
315 else if (GetHomedPath(buffer, buffer) == 0)
316 {
317 Strlcpy(path, buffer, sizeof(path));
318 break;
319 }
320 }
321
322 /* Just use the default value. */
323
324 if (GetHomedPath(defaultPath, buffer) == 0)
325 {
326 Strlcpy(path, buffer, sizeof(path));
327 break;
328 }
329 kumpf 1.2
330 /* Failed. */
331
332 status = -1;
333 }
334 while (0);
335
336 if (status == 0)
|
337 dmitry.mikulin 1.4 {
|
338 kumpf 1.2 DefineMacro(configParam, path);
|
339 dmitry.mikulin 1.4 }
|
340 kumpf 1.2
341 return status;
342 }
343
344 /*
345 **==============================================================================
346 **
347 ** DumpMacros()
348 **
349 ** Dump all macros to standard output.
350 **
351 **==============================================================================
352 */
353
|
354 kumpf 1.3 void DumpMacros(FILE* outputStream)
|
355 kumpf 1.2 {
356 const struct Macro* p;
357
|
358 kumpf 1.3 fprintf(outputStream, "===== Macros:\n");
|
359 kumpf 1.2
360 for (p = _macros; p; p = p->next)
|
361 dmitry.mikulin 1.4 {
|
362 kumpf 1.3 fprintf(outputStream, "%s=%s\n", p->name, p->value);
|
363 dmitry.mikulin 1.4 }
|
364 kumpf 1.2
|
365 kumpf 1.3 putc('\n', outputStream);
|
366 kumpf 1.2 }
|