rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

parseScript.c
Go to the documentation of this file.
1
6 #include "system.h"
7
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #include <rpmlog.h>
11 #define _RPMEVR_INTERNAL
12 #include "rpmbuild.h"
13 #include "debug.h"
14
15 #include <rpmlua.h>
16
17 /*@access poptContext @*/ /* compared with NULL */
18
21 static rpmuint32_t addTriggerIndex(Package pkg, const char *file,
22 const char *script, const char *prog)
23 /*@modifies pkg->triggerFiles @*/
24 {
25 struct TriggerFileEntry *tfe;
26 struct TriggerFileEntry *list = pkg->triggerFiles;
27 struct TriggerFileEntry *last = NULL;
28 rpmuint32_t index = 0;
29
30 while (list) {
31 last = list;
32 list = list->next;
33 }
34
35 if (last)
36 index = last->index + 1;
37
38 tfe = xcalloc(1, sizeof(*tfe));
39
40 tfe->fileName = (file) ? xstrdup(file) : NULL;
41 tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
42 tfe->prog = xstrdup(prog);
43 tfe->index = index;
44 tfe->next = NULL;
45
46 if (last)
47 last->next = tfe;
48 else
49 pkg->triggerFiles = tfe;
50
51 return index;
52 }
53
54 /* these have to be global because of stupid compilers */
55 /*@unchecked@*/
56 /*@observer@*/ /*@null@*/ static const char *name = NULL;
57 /*@unchecked@*/
58 /*@observer@*/ /*@null@*/ static const char *prog = NULL;
59 /*@unchecked@*/
60 /*@observer@*/ /*@null@*/ static const char *file = NULL;
61 /*@unchecked@*/
62 static struct poptOption optionsTable[] = {
63 { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL},
64 { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
65 { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL},
66 { 0, 0, 0, 0, 0, NULL, NULL}
67 };
68
69 /* %trigger is a strange combination of %pre and Requires: behavior */
70 /* We can handle it by parsing the args before "--" in parseScript. */
71 /* We then pass the remaining arguments to parseRCPOT, along with */
72 /* an index we just determined. */
73
74 int parseScript(Spec spec, int parsePart)
75 {
76 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
77 int xx;
78
79 /* There are a few options to scripts: */
80 /* <pkg> */
81 /* -n <pkg> */
82 /* -p <sh> */
83 /* -p "<sh> <args>..." */
84 /* -f <file> */
85
86 char *p;
87 const char **progArgv = NULL;
88 int progArgc;
89 char *partname = NULL;
90 rpmTag reqtag = 0;
91 rpmTag tag = 0;
92 rpmsenseFlags tagflags = 0;
93 rpmTag progtag = 0;
94 int flag = PART_SUBNAME;
95 Package pkg;
96 rpmiob iob = NULL;
97 rpmParseState nextPart;
98 char reqargs[BUFSIZ];
99
100 int argc;
101 int arg;
102 const char **argv = NULL;
103 poptContext optCon = NULL;
104 rpmRC rc;
105
106 reqargs[0] = '\0';
107 /*@-mods@*/
108 name = NULL;
109 prog = "/bin/sh";
110 file = NULL;
111 /*@=mods@*/
112
113 switch (parsePart) {
114 case PART_PRE:
115 tag = RPMTAG_PREIN;
116 tagflags = RPMSENSE_SCRIPT_PRE;
117 progtag = RPMTAG_PREINPROG;
118 partname = "%pre";
119 break;
120 case PART_POST:
121 tag = RPMTAG_POSTIN;
122 tagflags = RPMSENSE_SCRIPT_POST;
123 progtag = RPMTAG_POSTINPROG;
124 partname = "%post";
125 break;
126 case PART_PREUN:
127 tag = RPMTAG_PREUN;
128 tagflags = RPMSENSE_SCRIPT_PREUN;
129 progtag = RPMTAG_PREUNPROG;
130 partname = "%preun";
131 break;
132 case PART_POSTUN:
133 tag = RPMTAG_POSTUN;
134 tagflags = RPMSENSE_SCRIPT_POSTUN;
135 progtag = RPMTAG_POSTUNPROG;
136 partname = "%postun";
137 break;
138 case PART_PRETRANS:
139 tag = RPMTAG_PRETRANS;
140 tagflags = 0;
141 progtag = RPMTAG_PRETRANSPROG;
142 partname = "%pretrans";
143 break;
144 case PART_POSTTRANS:
145 tag = RPMTAG_POSTTRANS;
146 tagflags = 0;
147 progtag = RPMTAG_POSTTRANSPROG;
148 partname = "%posttrans";
149 break;
150 case PART_VERIFYSCRIPT:
151 tag = RPMTAG_VERIFYSCRIPT;
152 tagflags = RPMSENSE_SCRIPT_VERIFY;
153 progtag = RPMTAG_VERIFYSCRIPTPROG;
154 partname = "%verifyscript";
155 break;
156 case PART_TRIGGERPREIN:
157 tag = RPMTAG_TRIGGERSCRIPTS;
158 tagflags = 0;
159 reqtag = RPMTAG_TRIGGERPREIN;
160 progtag = RPMTAG_TRIGGERSCRIPTPROG;
161 partname = "%triggerprein";
162 break;
163 case PART_TRIGGERIN:
164 tag = RPMTAG_TRIGGERSCRIPTS;
165 tagflags = 0;
166 reqtag = RPMTAG_TRIGGERIN;
167 progtag = RPMTAG_TRIGGERSCRIPTPROG;
168 partname = "%triggerin";
169 break;
170 case PART_TRIGGERUN:
171 tag = RPMTAG_TRIGGERSCRIPTS;
172 tagflags = 0;
173 reqtag = RPMTAG_TRIGGERUN;
174 progtag = RPMTAG_TRIGGERSCRIPTPROG;
175 partname = "%triggerun";
176 break;
177 case PART_TRIGGERPOSTUN:
178 tag = RPMTAG_TRIGGERSCRIPTS;
179 tagflags = 0;
180 reqtag = RPMTAG_TRIGGERPOSTUN;
181 progtag = RPMTAG_TRIGGERSCRIPTPROG;
182 partname = "%triggerpostun";
183 break;
184 /* support "%sanitycheck" script/section */
185 case PART_SANITYCHECK:
186 tag = RPMTAG_SANITYCHECK;
187 tagflags = RPMSENSE_SCRIPT_SANITYCHECK;
188 progtag = RPMTAG_SANITYCHECKPROG;
189 partname = "%sanitycheck";
190 break;
191 }
192
193 if (tag == RPMTAG_TRIGGERSCRIPTS) {
194 /* break line into two */
195 p = strstr(spec->line, "--");
196 if (!p) {
197 rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
198 spec->lineNum, spec->line);
199 return RPMRC_FAIL;
200 }
201
202 *p = '\0';
203 strcpy(reqargs, p + 2);
204 }
205
206 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
207 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
208 spec->lineNum, partname, poptStrerror(rc));
209 return RPMRC_FAIL;
210 }
211
212 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
213 while ((arg = poptGetNextOpt(optCon)) > 0) {
214 switch (arg) {
215 case 'p':
216 if (prog[0] == '<') {
217 if (prog[strlen(prog)-1] != '>') {
218 rpmlog(RPMLOG_ERR,
219 _("line %d: internal script must end "
220 "with \'>\': %s\n"), spec->lineNum, prog);
221 rc = RPMRC_FAIL;
222 goto exit;
223 }
224 } else if (prog[0] == '%') {
225 /* XXX check well-formed macro? */
226 } else if (prog[0] != '/') {
227 rpmlog(RPMLOG_ERR,
228 _("line %d: script program must begin "
229 "with \'/\': %s\n"), spec->lineNum, prog);
230 rc = RPMRC_FAIL;
231 goto exit;
232 }
233 /*@switchbreak@*/ break;
234 case 'n':
235 flag = PART_NAME;
236 /*@switchbreak@*/ break;
237 }
238 }
239
240 if (arg < -1) {
241 rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
242 spec->lineNum,
243 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
244 spec->line);
245 rc = RPMRC_FAIL;
246 goto exit;
247 }
248
249 if (poptPeekArg(optCon)) {
250 /*@-mods@*/
251 if (name == NULL)
252 name = poptGetArg(optCon);
253 /*@=mods@*/
254 if (poptPeekArg(optCon)) {
255 rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
256 spec->lineNum,
257 spec->line);
258 rc = RPMRC_FAIL;
259 goto exit;
260 }
261 }
262
263 if (lookupPackage(spec, name, flag, &pkg) != RPMRC_OK) {
264 rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
265 spec->lineNum, spec->line);
266 rc = RPMRC_FAIL;
267 goto exit;
268 }
269
270 if (tag != RPMTAG_TRIGGERSCRIPTS) {
271 if (headerIsEntry(pkg->header, progtag)) {
272 rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
273 spec->lineNum, partname);
274 rc = RPMRC_FAIL;
275 goto exit;
276 }
277 }
278
279 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
280 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
281 spec->lineNum, partname, poptStrerror(rc));
282 rc = RPMRC_FAIL;
283 goto exit;
284 }
285
286 iob = rpmiobNew(0);
287 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
288 nextPart = PART_NONE;
289 } else {
290 if (rc)
291 goto exit;
292 while ((nextPart = isPart(spec)) == PART_NONE) {
293 iob = rpmiobAppend(iob, spec->line, 0);
294 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
295 nextPart = PART_NONE;
296 break;
297 }
298 if (rc)
299 goto exit;
300 }
301 }
302 iob = rpmiobRTrim(iob);
303 p = rpmiobStr(iob);
304
305 #ifdef WITH_LUA
306 if (!strcmp(progArgv[0], "<lua>")) {
307 rpmlua lua = NULL; /* Global state. */
308 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
309 rc = RPMRC_FAIL;
310 goto exit;
311 }
312 (void) rpmlibNeedsFeature(pkg->header,
313 "BuiltinLuaScripts", "4.2.2-1");
314 } else
315 #endif
316 #ifdef WITH_FICL
317 if (!strcmp(progArgv[0], "<ficl>")) {
318 (void) rpmlibNeedsFeature(pkg->header,
319 "BuiltinFiclScripts", "5.2-1");
320 } else
321 #endif
322 #ifdef WITH_JS
323 if (!strcmp(progArgv[0], "<js>")) {
324 (void) rpmlibNeedsFeature(pkg->header,
325 "BuiltinJavaScript", "5.2-1");
326 } else
327 #endif
328 #ifdef WITH_PERLEMBED
329 if (!strcmp(progArgv[0], "<perl>")) {
330 (void) rpmlibNeedsFeature(pkg->header,
331 "BuiltinPerlScripts", "5.2-1");
332 } else
333 #endif
334 #ifdef WITH_PYTHONEMBED
335 if (!strcmp(progArgv[0], "<python>")) {
336 (void) rpmlibNeedsFeature(pkg->header,
337 "BuiltinPythonScripts", "5.2-1");
338 } else
339 #endif
340 #ifdef WITH_RUBYEMBED
341 if (!strcmp(progArgv[0], "<ruby>")) {
342 (void) rpmlibNeedsFeature(pkg->header,
343 "BuiltinRubyScripts", "5.2-1");
344 } else
345 #endif
346 #ifdef WITH_TCL
347 if (!strcmp(progArgv[0], "<tcl>")) {
348 (void) rpmlibNeedsFeature(pkg->header,
349 "BuiltinTclScripts", "5.2-1");
350 } else
351 #endif
352 if (progArgv[0][0] == '<') {
353 rpmlog(RPMLOG_ERR,
354 _("line %d: unsupported internal script: %s\n"),
355 spec->lineNum, progArgv[0]);
356 rc = RPMRC_FAIL;
357 goto exit;
358 } else
359 if (!(rpmExpandNumeric("%{?_disable_shell_interpreter_deps}")
360 && !strcmp(progArgv[0], "/bin/sh")))
361 {
362
363 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME,
364 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
365 }
366
367 /* Trigger script insertion is always delayed in order to */
368 /* get the index right. */
369 if (tag == RPMTAG_TRIGGERSCRIPTS) {
370 /* Add file/index/prog triple to the trigger file list */
371 rpmuint32_t index = addTriggerIndex(pkg, file, p, progArgv[0]);
372
373 /* Generate the trigger tags */
374 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
375 goto exit;
376 } else {
377 if (progArgc == 1) {
378 he->tag = progtag;
379 he->t = RPM_STRING_TYPE;
380 he->p.str = *progArgv;
381 he->c = progArgc;
382 xx = headerPut(pkg->header, he, 0);
383 } else {
384 (void) rpmlibNeedsFeature(pkg->header,
385 "ScriptletInterpreterArgs", "4.0.3-1");
386 he->tag = progtag;
387 he->t = RPM_STRING_ARRAY_TYPE;
388 he->p.argv = progArgv;
389 he->c = progArgc;
390 xx = headerPut(pkg->header, he, 0);
391 }
392
393 if (*p != '\0') {
394 he->tag = tag;
395 he->t = RPM_STRING_TYPE;
396 he->p.str = p;
397 he->c = 1;
398 xx = headerPut(pkg->header, he, 0);
399 }
400
401 if (file) {
402 switch (parsePart) {
403 case PART_PRE:
404 pkg->preInFile = xstrdup(file);
405 break;
406 case PART_POST:
407 pkg->postInFile = xstrdup(file);
408 break;
409 case PART_PREUN:
410 pkg->preUnFile = xstrdup(file);
411 break;
412 case PART_POSTUN:
413 pkg->postUnFile = xstrdup(file);
414 break;
415 case PART_PRETRANS:
416 pkg->preTransFile = xstrdup(file);
417 break;
418 case PART_POSTTRANS:
419 pkg->postTransFile = xstrdup(file);
420 break;
421 case PART_VERIFYSCRIPT:
422 pkg->verifyFile = xstrdup(file);
423 break;
424 case PART_SANITYCHECK:
425 pkg->sanityCheckFile = xstrdup(file);
426 break;
427 }
428 }
429 }
430 rc = (rpmRC) nextPart;
431
432 exit:
433 iob = rpmiobFree(iob);
434 progArgv = _free(progArgv);
435 argv = _free(argv);
436 optCon = poptFreeContext(optCon);
437
438 return rc;
439 }