| File: | lib/rpmscript.c |
| Warning: | line 390, column 9 Branch condition evaluates to a garbage value |
| 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); | |||
| 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 | } |