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