Bug Summary

File:lib/rpmscript.c
Warning:line 192, column 6
Value stored to 'xx' is never read

Annotated Source Code

1#include "system.h"
2
3#include <sys/types.h>
4#include <sys/wait.h>
5#include <errno(*__errno_location ()).h>
6#include <unistd.h>
7
8#include <rpm/rpmfileutil.h>
9#include <rpm/rpmmacro.h>
10#include <rpm/rpmio.h>
11#include <rpm/rpmlog.h>
12#include <rpm/header.h>
13#include <rpm/rpmds.h>
14
15#include "rpmio/rpmlua.h"
16#include "lib/rpmscript.h"
17
18#include "lib/rpmplugins.h" /* rpm plugins hooks */
19
20#include "debug.h"
21
22struct scriptNextFileFunc_s {
23 char *(*func)(void *); /* function producing input for script */
24 void *param; /* parameter for func */
25};
26
27typedef struct scriptNextFileFunc_s *scriptNextFileFunc;
28
29struct rpmScript_s {
30 rpmscriptTypes type; /* script type */
31 rpmTagVal tag; /* script tag */
32 char **args; /* scriptlet call arguments */
33 char *body; /* script body */
34 char *descr; /* description for logging */
35 rpmscriptFlags flags; /* flags to control operation */
36 struct scriptNextFileFunc_s nextFileFunc; /* input function */
37};
38
39struct scriptInfo_s {
40 rpmscriptTypes type;
41 const char *desc;
42 rpmsenseFlags sense;
43 rpmTagVal tag;
44 rpmTagVal progtag;
45 rpmTagVal flagtag;
46};
47
48static const struct scriptInfo_s scriptInfo[] = {
49 { RPMSCRIPT_PREIN, "%prein", 0,
50 RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS },
51 { RPMSCRIPT_PREUN, "%preun", 0,
52 RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS },
53 { RPMSCRIPT_POSTIN, "%post", 0,
54 RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS },
55 { RPMSCRIPT_POSTUN, "%postun", 0,
56 RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS },
57 { RPMSCRIPT_PRETRANS, "%pretrans", 0,
58 RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS },
59 { RPMSCRIPT_POSTTRANS, "%posttrans", 0,
60 RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS },
61 { RPMSCRIPT_TRIGGERPREIN, "%triggerprein", RPMSENSE_TRIGGERPREIN,
62 RPMTAG_TRIGGERPREIN, 0, 0 },
63 { RPMSCRIPT_TRIGGERUN, "%triggerun", RPMSENSE_TRIGGERUN,
64 RPMTAG_TRIGGERUN, 0, 0 },
65 { RPMSCRIPT_TRIGGERIN, "%triggerin", RPMSENSE_TRIGGERIN,
66 RPMTAG_TRIGGERIN, 0, 0 },
67 { RPMSCRIPT_TRIGGERPOSTUN, "%triggerpostun", RPMSENSE_TRIGGERPOSTUN,
68 RPMTAG_TRIGGERPOSTUN, 0, 0 },
69 { RPMSCRIPT_VERIFY, "%verify", 0,
70 RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
71 { 0, "unknown", 0,
72 RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND }
73};
74
75static const struct scriptInfo_s * findTag(rpmTagVal tag)
76{
77 const struct scriptInfo_s * si = scriptInfo;
78 while (si->type && si->tag != tag)
79 si++;
80 return si;
81}
82/**
83 * Run internal Lua script.
84 */
85static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
86 const char *sname, rpmlogLvl lvl, FD_t scriptFd,
87 ARGV_t * argvp, const char *script, int arg1, int arg2,
88 scriptNextFileFunc nextFileFunc)
89{
90 rpmRC rc = RPMRC_FAIL;
91#ifdef WITH_LUA1
92 ARGV_t argv = argvp ? *argvp : NULL((void*)0);
93 rpmlua lua = NULL((void*)0); /* Global state. */
94 rpmluav var = rpmluavNew();
95 int cwd = -1;
96
97 rpmlog(RPMLOG_DEBUG, "%s: running <lua> scriptlet.\n", sname);
98
99 /* Create arg variable */
100 rpmluaPushTable(lua, "arg");
101 rpmluavSetListMode(var, 1);
102 rpmluaSetNextFileFunc(nextFileFunc->func, nextFileFunc->param);
103 if (argv) {
104 char **p;
105 for (p = argv; *p; p++) {
106 rpmluavSetValue(var, RPMLUAV_STRING, *p);
107 rpmluaSetVar(lua, var);
108 }
109 }
110 if (arg1 >= 0) {
111 rpmluavSetValueNum(var, arg1);
112 rpmluaSetVar(lua, var);
113 }
114 if (arg2 >= 0) {
115 rpmluavSetValueNum(var, arg2);
116 rpmluaSetVar(lua, var);
117 }
118 rpmluaPop(lua);
119
120 /* Lua scripts can change our cwd and umask, save and restore */
121 /* XXX TODO: use cwd from chroot state to save unnecessary open here */
122 cwd = open(".", O_RDONLY00);
123 if (cwd != -1) {
124 mode_t oldmask = umask(0);
125 umask(oldmask);
126 pid_t pid = getpid();
127
128 if (chdir("/") == 0 && rpmluaRunScript(lua, script, sname) == 0) {
129 rc = RPMRC_OK;
130 }
131 if (pid != getpid()) {
132 /* Terminate child process forked in lua scriptlet */
133 rpmlog(RPMLOG_ERR, _("No exec() called after fork() in lua scriptlet\n")dcgettext ("rpm", "No exec() called after fork() in lua scriptlet\n"
, 5)
);
134 _exit(EXIT_FAILURE1);
135 }
136 /* This failing would be fatal, return something different for it... */
137 if (fchdir(cwd)) {
138 rpmlog(RPMLOG_ERR, _("Unable to restore current directory: %m")dcgettext ("rpm", "Unable to restore current directory: %m", 5
)
);
139 rc = RPMRC_NOTFOUND;
140 }
141 close(cwd);
142 umask(oldmask);
143 }
144
145 rpmluaDelVar(lua, "arg");
146 rpmluavFree(var);
147
148#else
149 rpmlog(lvl, _("<lua> scriptlet support not built in\n")dcgettext ("rpm", "<lua> scriptlet support not built in\n"
, 5)
);
150#endif
151
152 return rc;
153}
154
155static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
156
157static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
158 FD_t scriptFd, FD_t out)
159{
160 int flag;
161 int fdno;
162 int xx;
163 int open_max;
164
165 /* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
166 (void) signal(SIGPIPE13, SIG_DFL((__sighandler_t) 0));
167
168 /* XXX Force FD_CLOEXEC on all inherited fdno's. */
169 open_max = sysconf(_SC_OPEN_MAX_SC_OPEN_MAX);
170 if (open_max == -1) {
171 open_max = 1024;
172 }
173 for (fdno = 3; fdno < open_max; fdno++) {
174 flag = fcntl(fdno, F_GETFD1);
175 if (flag == -1 || (flag & FD_CLOEXEC1))
176 continue;
177 xx = fcntl(fdno, F_SETFD2, FD_CLOEXEC1);
178 /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
179 }
180
181 if (scriptFd != NULL((void*)0)) {
182 int sfdno = Fileno(scriptFd);
183 int ofdno = Fileno(out);
184 if (sfdno != STDERR_FILENO2)
185 xx = dup2(sfdno, STDERR_FILENO2);
186 if (ofdno != STDOUT_FILENO1)
187 xx = dup2(ofdno, STDOUT_FILENO1);
188 /* make sure we don't close stdin/stderr/stdout by mistake! */
189 if (ofdno > STDERR_FILENO2 && ofdno != sfdno)
190 xx = Fclose (out);
191 if (sfdno > STDERR_FILENO2 && ofdno != sfdno)
192 xx = Fclose (scriptFd);
Value stored to 'xx' is never read
193 }
194
195 { char *ipath = rpmExpand("%{_install_script_path}", NULL((void*)0));
196 const char *path = SCRIPT_PATH;
197
198 if (ipath && ipath[5] != '%')
199 path = ipath;
200
201 xx = setenv("PATH", path, 1);
202 free(ipath);
203 }
204
205 for (ARGV_const_t pf = prefixes; pf && *pf; pf++) {
206 char *name = NULL((void*)0);
207 int num = (pf - prefixes);
208
209 rasprintf(&name, "RPM_INSTALL_PREFIX%d", num);
210 setenv(name, *pf, 1);
211 free(name);
212
213 /* scripts might still be using the old style prefix */
214 if (num == 0) {
215 setenv("RPM_INSTALL_PREFIX", *pf, 1);
216 }
217 }
218
219 if (chdir("/") == 0) {
220 /* XXX Don't mtrace into children. */
221 unsetenv("MALLOC_CHECK_");
222
223 if (xx == 0) {
224 xx = execv(argv[0], argv);
225 }
226 }
227 _exit(127); /* exit 127 for compatibility with bash(1) */
228}
229
230static char * writeScript(const char *cmd, const char *script)
231{
232 char *fn = NULL((void*)0);
233 size_t slen = strlen(script);
234 int ok = 0;
235 FD_t fd = rpmMkTempFile("/", &fn);
236
237 if (Ferror(fd))
238 goto exit;
239
240 if (rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG)
)))
&& (rstreq(cmd, "/bin/sh") || rstreq(cmd, "/bin/bash"))) {
241 static const char set_x[] = "set -x\n";
242 /* Assume failures will be caught by the write below */
243 Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
244 }
245
246 ok = (Fwrite(script, sizeof(script[0]), slen, fd) == slen);
247
248exit:
249 if (!ok) fn = _free(fn)rfree((fn));
250 Fclose(fd);
251 return fn;
252}
253
254/**
255 * Run an external script.
256 */
257static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
258 const char *sname, rpmlogLvl lvl, FD_t scriptFd,
259 ARGV_t * argvp, const char *script, int arg1, int arg2,
260 scriptNextFileFunc nextFileFunc)
261{
262 FD_t out = NULL((void*)0);
263 char * fn = NULL((void*)0);
264 pid_t pid, reaped;
265 int status;
266 int inpipe[2];
267 FILE *in = NULL((void*)0);
268 const char *line;
269 char *mline = NULL((void*)0);
270 rpmRC rc = RPMRC_FAIL;
271
272 rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname);
273
274 if (script) {
275 fn = writeScript(*argvp[0], script);
276 if (fn == NULL((void*)0)) {
277 rpmlog(RPMLOG_ERR,
278 _("Couldn't create temporary file for %s: %s\n")dcgettext ("rpm", "Couldn't create temporary file for %s: %s\n"
, 5)
,
279 sname, strerror(errno(*__errno_location ())));
280 goto exit;
281 }
282
283 argvAdd(argvp, fn);
284 if (arg1 >= 0) {
285 argvAddNum(argvp, arg1);
286 }
287 if (arg2 >= 0) {
288 argvAddNum(argvp, arg2);
289 }
290 }
291
292 if (pipe(inpipe) < 0) {
293 rpmlog(RPMLOG_ERR,
294 ("Couldn't create pipe: %s\n"), strerror(errno(*__errno_location ())));
295 goto exit;
296 }
297 in = fdopen(inpipe[1], "w");
298 inpipe[1] = 0;
299
300 if (scriptFd != NULL((void*)0)) {
301 if (rpmIsVerbose()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_INFO))
))
) {
302 out = fdDup(Fileno(scriptFd));
303 } else {
304 out = Fopen("/dev/null", "w.fdio");
305 if (Ferror(out)) {
306 out = fdDup(Fileno(scriptFd));
307 }
308 }
309 } else {
310 out = fdDup(STDOUT_FILENO1);
311 }
312 if (out == NULL((void*)0)) {
313 rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n")dcgettext ("rpm", "Couldn't duplicate file descriptor: %s: %s\n"
, 5)
,
314 sname, strerror(errno(*__errno_location ())));
315 goto exit;
316 }
317
318 pid = fork();
319 if (pid == (pid_t) -1) {
320 rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n")dcgettext ("rpm", "Couldn't fork %s: %s\n", 5),
321 sname, strerror(errno(*__errno_location ())));
322 goto exit;
323 } else if (pid == 0) {/* Child */
324 rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n",
325 sname, *argvp[0], (unsigned)getpid());
326
327 fclose(in);
328 dup2(inpipe[0], STDIN_FILENO0);
329
330 /* Run scriptlet post fork hook for all plugins */
331 if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) {
332 doScriptExec(*argvp, prefixes, scriptFd, out);
333 } else {
334 _exit(126); /* exit 126 for compatibility with bash(1) */
335 }
336 }
337 close(inpipe[0]);
338 inpipe[0] = 0;
339
340 if (nextFileFunc->func) {
341 while ((line = nextFileFunc->func(nextFileFunc->param)) != NULL((void*)0)) {
342 size_t size = strlen(line);
343 size_t ret_size;
344 mline = xstrdup(line)rstrdup((line));
345 mline[size] = '\n';
346
347 ret_size = fwrite(mline, size + 1, 1, in);
348 mline = _free(mline)rfree((mline));
349 if (ret_size != 1) {
350 if (errno(*__errno_location ()) == EPIPE32) {
351 break;
352 } else {
353 rpmlog(RPMLOG_ERR, _("Fwrite failed: %s")dcgettext ("rpm", "Fwrite failed: %s", 5), strerror(errno(*__errno_location ())));
354 rc = RPMRC_FAIL;
355 goto exit;
356 }
357 }
358 }
359 }
360 fclose(in);
361 in = NULL((void*)0);
362
363 do {
364 reaped = waitpid(pid, &status, 0);
365 } while (reaped == -1 && errno(*__errno_location ()) == EINTR4);
366
367 rpmlog(RPMLOG_DEBUG, "%s: waitpid(%d) rc %d status %x\n",
368 sname, (unsigned)pid, (unsigned)reaped, status);
369
370 if (reaped < 0) {
371 rpmlog(lvl, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n")dcgettext ("rpm", "%s scriptlet failed, waitpid(%d) rc %d: %s\n"
, 5)
,
372 sname, pid, reaped, strerror(errno(*__errno_location ())));
373 } else if (!WIFEXITED(status)(((status) & 0x7f) == 0) || WEXITSTATUS(status)(((status) & 0xff00) >> 8)) {
374 if (WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
) {
375 rpmlog(lvl, _("%s scriptlet failed, signal %d\n")dcgettext ("rpm", "%s scriptlet failed, signal %d\n", 5),
376 sname, WTERMSIG(status)((status) & 0x7f));
377 } else {
378 rpmlog(lvl, _("%s scriptlet failed, exit status %d\n")dcgettext ("rpm", "%s scriptlet failed, exit status %d\n", 5),
379 sname, WEXITSTATUS(status)(((status) & 0xff00) >> 8));
380 }
381 } else {
382 /* if we get this far we're clear */
383 rc = RPMRC_OK;
384 }
385
386exit:
387 if (in)
388 fclose(in);
389
390 if (inpipe[0])
391 close(inpipe[0]);
392
393 if (out)
394 Fclose(out); /* XXX dup'd STDOUT_FILENO */
395
396 if (fn) {
397 if (!rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG)
)))
)
398 unlink(fn);
399 free(fn);
400 }
401 free(mline);
402
403 return rc;
404}
405
406rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
407 ARGV_const_t prefixes, int warn_only, rpmPlugins plugins)
408{
409 ARGV_t args = NULL((void*)0);
410 rpmlogLvl lvl = warn_only ? RPMLOG_WARNING : RPMLOG_ERR;
411 rpmRC rc;
412 int script_type = RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC;
413
414 if (script == NULL((void*)0)) return RPMRC_OK;
415
416 /* construct a new argv as we can't modify the one from header */
417 if (script->args) {
418 argvAppend(&args, script->args);
419 } else {
420 argvAdd(&args, "/bin/sh");
421 }
422
423 if (rstreq(args[0], "<lua>"))
424 script_type = RPMSCRIPTLET_NONE;
425
426 /* Run scriptlet pre hook for all plugins */
427 rc = rpmpluginsCallScriptletPre(plugins, script->descr, script_type);
428
429 if (rc != RPMRC_FAIL) {
430 if (script_type & RPMSCRIPTLET_EXEC) {
431 rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
432 } else {
433 rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
434 }
435 }
436
437 /* Run scriptlet post hook for all plugins */
438 rpmpluginsCallScriptletPost(plugins, script->descr, script_type, rc);
439
440 argvFree(args);
441
442 return rc;
443}
444
445static rpmscriptTypes getScriptType(rpmTagVal scriptTag)
446{
447 return findTag(scriptTag)->type;
448}
449
450static rpmTagVal getProgTag(rpmTagVal scriptTag)
451{
452 return findTag(scriptTag)->progtag;
453}
454
455static rpmTagVal getFlagTag(rpmTagVal scriptTag)
456{
457 return findTag(scriptTag)->flagtag;
458}
459
460static const char * tag2sln(rpmTagVal tag)
461{
462 return findTag(tag)->desc;
463}
464
465static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body,
466 rpmscriptFlags flags)
467{
468 char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
469 rpmScript script = xcalloc(1, sizeof(*script))rcalloc((1), (sizeof(*script)));
470 script->tag = tag;
471 script->type = getScriptType(tag);
472 script->flags = flags;
473 script->body = (body != NULL((void*)0)) ? xstrdup(body)rstrdup((body)) : NULL((void*)0);
474 rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra);
475
476 /* macros need to be expanded before possible queryformat */
477 if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) {
478 char *body = rpmExpand(script->body, NULL((void*)0));
479 free(script->body);
480 script->body = body;
481 }
482 if (script->body && (script->flags & RPMSCRIPT_FLAG_QFORMAT)) {
483 /* XXX TODO: handle queryformat errors */
484 char *body = headerFormat(h, script->body, NULL((void*)0));
485 free(script->body);
486 script->body = body;
487 }
488
489 script->nextFileFunc.func = NULL((void*)0);
490 script->nextFileFunc.param = NULL((void*)0);
491
492 free(nevra);
493 return script;
494}
495
496void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *),
497 void *param)
498{
499 script->nextFileFunc.func = func;
500 script->nextFileFunc.param = param;
501}
502
503rpmTagVal triggerDsTag(rpmscriptTriggerModes tm)
504{
505 rpmTagVal tag = RPMTAG_NOT_FOUND;
506 switch (tm) {
507 case RPMSCRIPT_NORMALTRIGGER:
508 tag = RPMTAG_TRIGGERNAME;
509 break;
510 case RPMSCRIPT_FILETRIGGER:
511 tag = RPMTAG_FILETRIGGERNAME;
512 break;
513 case RPMSCRIPT_TRANSFILETRIGGER:
514 tag = RPMTAG_TRANSFILETRIGGERNAME;
515 break;
516 }
517 return tag;
518}
519
520rpmscriptTriggerModes triggerMode(rpmTagVal tag)
521{
522 rpmscriptTriggerModes tm = 0;
523 switch (tag) {
524 case RPMTAG_TRIGGERNAME:
525 tm = RPMSCRIPT_NORMALTRIGGER;
526 break;
527 case RPMTAG_FILETRIGGERNAME:
528 tm = RPMSCRIPT_FILETRIGGER;
529 break;
530 case RPMTAG_TRANSFILETRIGGERNAME:
531 tm = RPMSCRIPT_TRANSFILETRIGGER;
532 break;
533 }
534 return tm;
535}
536
537rpmTagVal triggertag(rpmsenseFlags sense)
538{
539 rpmTagVal tag = RPMTAG_NOT_FOUND;
540 switch (sense) {
541 case RPMSENSE_TRIGGERIN:
542 tag = RPMTAG_TRIGGERIN;
543 break;
544 case RPMSENSE_TRIGGERUN:
545 tag = RPMTAG_TRIGGERUN;
546 break;
547 case RPMSENSE_TRIGGERPOSTUN:
548 tag = RPMTAG_TRIGGERPOSTUN;
549 break;
550 case RPMSENSE_TRIGGERPREIN:
551 tag = RPMTAG_TRIGGERPREIN;
552 break;
553 default:
554 break;
555 }
556 return tag;
557}
558
559rpmScript rpmScriptFromTriggerTag(Header h, rpmTagVal triggerTag,
560 rpmscriptTriggerModes tm, uint32_t ix)
561{
562 rpmScript script = NULL((void*)0);
563 struct rpmtd_s tscripts, tprogs, tflags;
564 headerGetFlags hgflags = HEADERGET_MINMEM;
565
566 switch (tm) {
567 case RPMSCRIPT_NORMALTRIGGER:
568 headerGet(h, RPMTAG_TRIGGERSCRIPTS, &tscripts, hgflags);
569 headerGet(h, RPMTAG_TRIGGERSCRIPTPROG, &tprogs, hgflags);
570 headerGet(h, RPMTAG_TRIGGERSCRIPTFLAGS, &tflags, hgflags);
571 break;
572 case RPMSCRIPT_FILETRIGGER:
573 headerGet(h, RPMTAG_FILETRIGGERSCRIPTS, &tscripts, hgflags);
574 headerGet(h, RPMTAG_FILETRIGGERSCRIPTPROG, &tprogs, hgflags);
575 headerGet(h, RPMTAG_FILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
576 break;
577 case RPMSCRIPT_TRANSFILETRIGGER:
578 headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTS, &tscripts, hgflags);
579 headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTPROG, &tprogs, hgflags);
580 headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
581 break;
582 }
583
584 if (rpmtdSetIndex(&tscripts, ix) >= 0 && rpmtdSetIndex(&tprogs, ix) >= 0) {
585 rpmscriptFlags sflags = 0;
586 const char *prog = rpmtdGetString(&tprogs);
587
588 if (rpmtdSetIndex(&tflags, ix) >= 0)
589 sflags = rpmtdGetNumber(&tflags);
590
591 script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags);
592
593 /* hack up a hge-style NULL-terminated array */
594 script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1)rmalloc((2 * sizeof(*script->args) + strlen(prog) + 1));
595 script->args[0] = (char *)(script->args + 2);
596 script->args[1] = NULL((void*)0);
597 strcpy(script->args[0], prog);
598 }
599
600 rpmtdFreeData(&tscripts);
601 rpmtdFreeData(&tprogs);
602 rpmtdFreeData(&tflags);
603
604 return script;
605}
606
607rpmScript rpmScriptFromTag(Header h, rpmTagVal scriptTag)
608{
609 rpmScript script = NULL((void*)0);
610 rpmTagVal progTag = getProgTag(scriptTag);
611
612 if (headerIsEntry(h, scriptTag) || headerIsEntry(h, progTag)) {
613 struct rpmtd_s prog;
614
615 script = rpmScriptNew(h, scriptTag,
616 headerGetString(h, scriptTag),
617 headerGetNumber(h, getFlagTag(scriptTag)));
618
619 if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) {
620 script->args = prog.data;
621 }
622 }
623 return script;
624}
625
626rpmScript rpmScriptFree(rpmScript script)
627{
628 if (script) {
629 free(script->args);
630 free(script->body);
631 free(script->descr);
632 free(script);
633 }
634 return NULL((void*)0);
635}
636
637rpmTagVal rpmScriptTag(rpmScript script)
638{
639 return (script != NULL((void*)0)) ? script->tag : RPMTAG_NOT_FOUND;
640}
641
642rpmscriptTypes rpmScriptType(rpmScript script)
643{
644 return (script != NULL((void*)0)) ? script->type : 0;
645}