| File: | lib/rpmscript.c |
| Warning: | line 192, column 6 Value stored to 'xx' is never read |
| 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 | |
| 22 | struct scriptNextFileFunc_s { |
| 23 | char *(*func)(void *); /* function producing input for script */ |
| 24 | void *param; /* parameter for func */ |
| 25 | }; |
| 26 | |
| 27 | typedef struct scriptNextFileFunc_s *scriptNextFileFunc; |
| 28 | |
| 29 | struct 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 | |
| 39 | struct scriptInfo_s { |
| 40 | rpmscriptTypes type; |
| 41 | const char *desc; |
| 42 | rpmsenseFlags sense; |
| 43 | rpmTagVal tag; |
| 44 | rpmTagVal progtag; |
| 45 | rpmTagVal flagtag; |
| 46 | }; |
| 47 | |
| 48 | static 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 | |
| 75 | static 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 | */ |
| 85 | static 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 | |
| 155 | static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin"; |
| 156 | |
| 157 | static 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 | |
| 230 | static 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 | |
| 248 | exit: |
| 249 | if (!ok) fn = _free(fn)rfree((fn)); |
| 250 | Fclose(fd); |
| 251 | return fn; |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Run an external script. |
| 256 | */ |
| 257 | static 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 | |
| 386 | exit: |
| 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 | |
| 406 | rpmRC 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 | |
| 445 | static rpmscriptTypes getScriptType(rpmTagVal scriptTag) |
| 446 | { |
| 447 | return findTag(scriptTag)->type; |
| 448 | } |
| 449 | |
| 450 | static rpmTagVal getProgTag(rpmTagVal scriptTag) |
| 451 | { |
| 452 | return findTag(scriptTag)->progtag; |
| 453 | } |
| 454 | |
| 455 | static rpmTagVal getFlagTag(rpmTagVal scriptTag) |
| 456 | { |
| 457 | return findTag(scriptTag)->flagtag; |
| 458 | } |
| 459 | |
| 460 | static const char * tag2sln(rpmTagVal tag) |
| 461 | { |
| 462 | return findTag(tag)->desc; |
| 463 | } |
| 464 | |
| 465 | static 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 | |
| 496 | void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *), |
| 497 | void *param) |
| 498 | { |
| 499 | script->nextFileFunc.func = func; |
| 500 | script->nextFileFunc.param = param; |
| 501 | } |
| 502 | |
| 503 | rpmTagVal 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 | |
| 520 | rpmscriptTriggerModes 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 | |
| 537 | rpmTagVal 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 | |
| 559 | rpmScript 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 | |
| 607 | rpmScript 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 | |
| 626 | rpmScript 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 | |
| 637 | rpmTagVal rpmScriptTag(rpmScript script) |
| 638 | { |
| 639 | return (script != NULL((void*)0)) ? script->tag : RPMTAG_NOT_FOUND; |
| 640 | } |
| 641 | |
| 642 | rpmscriptTypes rpmScriptType(rpmScript script) |
| 643 | { |
| 644 | return (script != NULL((void*)0)) ? script->type : 0; |
| 645 | } |