|
|
2ff057 |
#include "system.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <sys/types.h>
|
|
|
2ff057 |
#include <sys/wait.h>
|
|
|
2ff057 |
#include <errno.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmfileutil.h>
|
|
|
2ff057 |
#include <rpm/rpmmacro.h>
|
|
|
2ff057 |
#include <rpm/rpmio.h>
|
|
|
2ff057 |
#include <rpm/rpmlog.h>
|
|
|
2ff057 |
#include <rpm/header.h>
|
|
|
2ff057 |
#include <rpm/rpmds.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "rpmio/rpmlua.h"
|
|
|
2ff057 |
#include "lib/rpmscript.h"
|
|
|
2ff057 |
#include "rpmio/rpmio_internal.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "lib/rpmplugins.h" /* rpm plugins hooks */
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "debug.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
struct scriptNextFileFunc_s {
|
|
|
2ff057 |
char *(*func)(void *); /* function producing input for script */
|
|
|
2ff057 |
void *param; /* parameter for func */
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
typedef struct scriptNextFileFunc_s *scriptNextFileFunc;
|
|
|
2ff057 |
|
|
|
2ff057 |
struct rpmScript_s {
|
|
|
2ff057 |
rpmscriptTypes type; /* script type */
|
|
|
2ff057 |
rpmTagVal tag; /* script tag */
|
|
|
2ff057 |
char **args; /* scriptlet call arguments */
|
|
|
2ff057 |
char *body; /* script body */
|
|
|
2ff057 |
char *descr; /* description for logging */
|
|
|
2ff057 |
rpmscriptFlags flags; /* flags to control operation */
|
|
|
2ff057 |
struct scriptNextFileFunc_s nextFileFunc; /* input function */
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
struct scriptInfo_s {
|
|
|
2ff057 |
rpmscriptTypes type;
|
|
|
2ff057 |
const char *desc;
|
|
|
2ff057 |
rpmsenseFlags sense;
|
|
|
2ff057 |
rpmTagVal tag;
|
|
|
2ff057 |
rpmTagVal progtag;
|
|
|
2ff057 |
rpmTagVal flagtag;
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static const struct scriptInfo_s scriptInfo[] = {
|
|
|
2ff057 |
{ RPMSCRIPT_PREIN, "%prein", 0,
|
|
|
2ff057 |
RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_PREUN, "%preun", 0,
|
|
|
2ff057 |
RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_POSTIN, "%post", 0,
|
|
|
2ff057 |
RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_POSTUN, "%postun", 0,
|
|
|
2ff057 |
RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_PRETRANS, "%pretrans", 0,
|
|
|
2ff057 |
RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_POSTTRANS, "%posttrans", 0,
|
|
|
2ff057 |
RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS },
|
|
|
2ff057 |
{ RPMSCRIPT_TRIGGERPREIN, "%triggerprein", RPMSENSE_TRIGGERPREIN,
|
|
|
2ff057 |
RPMTAG_TRIGGERPREIN, 0, 0 },
|
|
|
2ff057 |
{ RPMSCRIPT_TRIGGERUN, "%triggerun", RPMSENSE_TRIGGERUN,
|
|
|
2ff057 |
RPMTAG_TRIGGERUN, 0, 0 },
|
|
|
2ff057 |
{ RPMSCRIPT_TRIGGERIN, "%triggerin", RPMSENSE_TRIGGERIN,
|
|
|
2ff057 |
RPMTAG_TRIGGERIN, 0, 0 },
|
|
|
2ff057 |
{ RPMSCRIPT_TRIGGERPOSTUN, "%triggerpostun", RPMSENSE_TRIGGERPOSTUN,
|
|
|
2ff057 |
RPMTAG_TRIGGERPOSTUN, 0, 0 },
|
|
|
2ff057 |
{ RPMSCRIPT_VERIFY, "%verify", 0,
|
|
|
2ff057 |
RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
|
|
|
2ff057 |
{ 0, "unknown", 0,
|
|
|
2ff057 |
RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND }
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static const struct scriptInfo_s * findTag(rpmTagVal tag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const struct scriptInfo_s * si = scriptInfo;
|
|
|
2ff057 |
while (si->type && si->tag != tag)
|
|
|
2ff057 |
si++;
|
|
|
2ff057 |
return si;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* Run internal Lua script.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
|
|
|
2ff057 |
const char *sname, rpmlogLvl lvl, FD_t scriptFd,
|
|
|
2ff057 |
ARGV_t * argvp, const char *script, int arg1, int arg2,
|
|
|
2ff057 |
scriptNextFileFunc nextFileFunc)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmRC rc = RPMRC_FAIL;
|
|
|
2ff057 |
#ifdef WITH_LUA
|
|
|
2ff057 |
ARGV_t argv = argvp ? *argvp : NULL;
|
|
|
2ff057 |
rpmlua lua = NULL; /* Global state. */
|
|
|
2ff057 |
rpmluav var = rpmluavNew();
|
|
|
2ff057 |
int cwd = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "%s: running <lua> scriptlet.\n", sname);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Create arg variable */
|
|
|
2ff057 |
rpmluaPushTable(lua, "arg");
|
|
|
2ff057 |
rpmluavSetListMode(var, 1);
|
|
|
2ff057 |
rpmluaSetNextFileFunc(nextFileFunc->func, nextFileFunc->param);
|
|
|
2ff057 |
if (argv) {
|
|
|
2ff057 |
char **p;
|
|
|
2ff057 |
for (p = argv; *p; p++) {
|
|
|
2ff057 |
rpmluavSetValue(var, RPMLUAV_STRING, *p);
|
|
|
2ff057 |
rpmluaSetVar(lua, var);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (arg1 >= 0) {
|
|
|
2ff057 |
rpmluavSetValueNum(var, arg1);
|
|
|
2ff057 |
rpmluaSetVar(lua, var);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (arg2 >= 0) {
|
|
|
2ff057 |
rpmluavSetValueNum(var, arg2);
|
|
|
2ff057 |
rpmluaSetVar(lua, var);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmluaPop(lua);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Lua scripts can change our cwd and umask, save and restore */
|
|
|
2ff057 |
/* XXX TODO: use cwd from chroot state to save unnecessary open here */
|
|
|
2ff057 |
cwd = open(".", O_RDONLY);
|
|
|
2ff057 |
if (cwd != -1) {
|
|
|
2ff057 |
mode_t oldmask = umask(0);
|
|
|
2ff057 |
umask(oldmask);
|
|
|
2ff057 |
pid_t pid = getpid();
|
|
|
2ff057 |
|
|
|
2ff057 |
if (chdir("/") == 0 && rpmluaRunScript(lua, script, sname) == 0) {
|
|
|
2ff057 |
rc = RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (pid != getpid()) {
|
|
|
2ff057 |
/* Terminate child process forked in lua scriptlet */
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("No exec() called after fork() in lua scriptlet\n"));
|
|
|
2ff057 |
_exit(EXIT_FAILURE);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* This failing would be fatal, return something different for it... */
|
|
|
2ff057 |
if (fchdir(cwd)) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("Unable to restore current directory: %m"));
|
|
|
2ff057 |
rc = RPMRC_NOTFOUND;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
close(cwd);
|
|
|
2ff057 |
umask(oldmask);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmluaDelVar(lua, "arg");
|
|
|
2ff057 |
rpmluavFree(var);
|
|
|
2ff057 |
|
|
|
2ff057 |
#else
|
|
|
2ff057 |
rpmlog(lvl, _("<lua> scriptlet support not built in\n"));
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
|
|
|
2ff057 |
|
|
|
2ff057 |
static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
|
|
|
2ff057 |
FD_t scriptFd, FD_t out)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int xx;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
|
|
|
2ff057 |
(void) signal(SIGPIPE, SIG_DFL);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmSetCloseOnExec();
|
|
|
2ff057 |
|
|
|
2ff057 |
if (scriptFd != NULL) {
|
|
|
2ff057 |
int sfdno = Fileno(scriptFd);
|
|
|
2ff057 |
int ofdno = Fileno(out);
|
|
|
2ff057 |
if (sfdno != STDERR_FILENO)
|
|
|
2ff057 |
xx = dup2(sfdno, STDERR_FILENO);
|
|
|
2ff057 |
if (ofdno != STDOUT_FILENO)
|
|
|
2ff057 |
xx = dup2(ofdno, STDOUT_FILENO);
|
|
|
2ff057 |
/* make sure we don't close stdin/stderr/stdout by mistake! */
|
|
|
2ff057 |
if (ofdno > STDERR_FILENO && ofdno != sfdno)
|
|
|
2ff057 |
xx = Fclose (out);
|
|
|
2ff057 |
if (sfdno > STDERR_FILENO && ofdno != sfdno)
|
|
|
2ff057 |
xx = Fclose (scriptFd);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
{ char *ipath = rpmExpand("%{_install_script_path}", NULL);
|
|
|
2ff057 |
const char *path = SCRIPT_PATH;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ipath && ipath[5] != '%')
|
|
|
2ff057 |
path = ipath;
|
|
|
2ff057 |
|
|
|
2ff057 |
xx = setenv("PATH", path, 1);
|
|
|
2ff057 |
free(ipath);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
for (ARGV_const_t pf = prefixes; pf && *pf; pf++) {
|
|
|
2ff057 |
char *name = NULL;
|
|
|
2ff057 |
int num = (pf - prefixes);
|
|
|
2ff057 |
|
|
|
2ff057 |
rasprintf(&name, "RPM_INSTALL_PREFIX%d", num);
|
|
|
2ff057 |
setenv(name, *pf, 1);
|
|
|
2ff057 |
free(name);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* scripts might still be using the old style prefix */
|
|
|
2ff057 |
if (num == 0) {
|
|
|
2ff057 |
setenv("RPM_INSTALL_PREFIX", *pf, 1);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (chdir("/") == 0) {
|
|
|
2ff057 |
/* XXX Don't mtrace into children. */
|
|
|
2ff057 |
unsetenv("MALLOC_CHECK_");
|
|
|
2ff057 |
|
|
|
2ff057 |
xx = execv(argv[0], argv);
|
|
|
2ff057 |
if (xx) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR,
|
|
|
2ff057 |
_("failed to exec scriptlet interpreter %s: %s\n"),
|
|
|
2ff057 |
argv[0], strerror(errno));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
_exit(127); /* exit 127 for compatibility with bash(1) */
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static char * writeScript(const char *cmd, const char *script)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
char *fn = NULL;
|
|
|
2ff057 |
size_t slen = strlen(script);
|
|
|
2ff057 |
int ok = 0;
|
|
|
2ff057 |
FD_t fd = rpmMkTempFile("/", &fn);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (Ferror(fd))
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmIsDebug() && (rstreq(cmd, "/bin/sh") || rstreq(cmd, "/bin/bash"))) {
|
|
|
2ff057 |
static const char set_x[] = "set -x\n";
|
|
|
2ff057 |
/* Assume failures will be caught by the write below */
|
|
|
2ff057 |
Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ok = (Fwrite(script, sizeof(script[0]), slen, fd) == slen);
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
if (!ok) fn = _free(fn);
|
|
|
2ff057 |
Fclose(fd);
|
|
|
2ff057 |
return fn;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* Run an external script.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
|
|
|
2ff057 |
const char *sname, rpmlogLvl lvl, FD_t scriptFd,
|
|
|
2ff057 |
ARGV_t * argvp, const char *script, int arg1, int arg2,
|
|
|
2ff057 |
scriptNextFileFunc nextFileFunc)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
FD_t out = NULL;
|
|
|
2ff057 |
char * fn = NULL;
|
|
|
2ff057 |
pid_t pid, reaped;
|
|
|
2ff057 |
int status;
|
|
|
2ff057 |
int inpipe[2];
|
|
|
2ff057 |
FILE *in = NULL;
|
|
|
2ff057 |
const char *line;
|
|
|
2ff057 |
char *mline = NULL;
|
|
|
2ff057 |
rpmRC rc = RPMRC_FAIL;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (script) {
|
|
|
2ff057 |
fn = writeScript(*argvp[0], script);
|
|
|
2ff057 |
if (fn == NULL) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR,
|
|
|
2ff057 |
_("Couldn't create temporary file for %s: %s\n"),
|
|
|
2ff057 |
sname, strerror(errno));
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
argvAdd(argvp, fn);
|
|
|
2ff057 |
if (arg1 >= 0) {
|
|
|
2ff057 |
argvAddNum(argvp, arg1);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (arg2 >= 0) {
|
|
|
2ff057 |
argvAddNum(argvp, arg2);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (pipe(inpipe) < 0) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR,
|
|
|
2ff057 |
("Couldn't create pipe: %s\n"), strerror(errno));
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
in = fdopen(inpipe[1], "w");
|
|
|
2ff057 |
inpipe[1] = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (scriptFd != NULL) {
|
|
|
2ff057 |
if (rpmIsVerbose()) {
|
|
|
2ff057 |
out = fdDup(Fileno(scriptFd));
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
out = Fopen("/dev/null", "w.fdio");
|
|
|
2ff057 |
if (Ferror(out)) {
|
|
|
2ff057 |
out = fdDup(Fileno(scriptFd));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
out = fdDup(STDOUT_FILENO);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (out == NULL) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n"),
|
|
|
2ff057 |
sname, strerror(errno));
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
pid = fork();
|
|
|
2ff057 |
if (pid == (pid_t) -1) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"),
|
|
|
2ff057 |
sname, strerror(errno));
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
} else if (pid == 0) {/* Child */
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n",
|
|
|
2ff057 |
sname, *argvp[0], (unsigned)getpid());
|
|
|
2ff057 |
|
|
|
2ff057 |
fclose(in);
|
|
|
2ff057 |
dup2(inpipe[0], STDIN_FILENO);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Run scriptlet post fork hook for all plugins */
|
|
|
2ff057 |
if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) {
|
|
|
2ff057 |
doScriptExec(*argvp, prefixes, scriptFd, out);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
_exit(126); /* exit 126 for compatibility with bash(1) */
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
close(inpipe[0]);
|
|
|
2ff057 |
inpipe[0] = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (nextFileFunc->func) {
|
|
|
2ff057 |
while ((line = nextFileFunc->func(nextFileFunc->param)) != NULL) {
|
|
|
2ff057 |
size_t size = strlen(line);
|
|
|
2ff057 |
size_t ret_size;
|
|
|
2ff057 |
mline = xstrdup(line);
|
|
|
2ff057 |
mline[size] = '\n';
|
|
|
2ff057 |
|
|
|
2ff057 |
ret_size = fwrite(mline, size + 1, 1, in);
|
|
|
2ff057 |
mline = _free(mline);
|
|
|
2ff057 |
if (ret_size != 1) {
|
|
|
2ff057 |
if (errno == EPIPE) {
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("Fwrite failed: %s"), strerror(errno));
|
|
|
2ff057 |
rc = RPMRC_FAIL;
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
fclose(in);
|
|
|
2ff057 |
in = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
do {
|
|
|
2ff057 |
reaped = waitpid(pid, &status, 0);
|
|
|
2ff057 |
} while (reaped == -1 && errno == EINTR);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "%s: waitpid(%d) rc %d status %x\n",
|
|
|
2ff057 |
sname, (unsigned)pid, (unsigned)reaped, status);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (reaped < 0) {
|
|
|
2ff057 |
rpmlog(lvl, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n"),
|
|
|
2ff057 |
sname, pid, reaped, strerror(errno));
|
|
|
2ff057 |
} else if (!WIFEXITED(status) || WEXITSTATUS(status)) {
|
|
|
2ff057 |
if (WIFSIGNALED(status)) {
|
|
|
2ff057 |
rpmlog(lvl, _("%s scriptlet failed, signal %d\n"),
|
|
|
2ff057 |
sname, WTERMSIG(status));
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
rpmlog(lvl, _("%s scriptlet failed, exit status %d\n"),
|
|
|
2ff057 |
sname, WEXITSTATUS(status));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
/* if we get this far we're clear */
|
|
|
2ff057 |
rc = RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
if (in)
|
|
|
2ff057 |
fclose(in);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (inpipe[0])
|
|
|
2ff057 |
close(inpipe[0]);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (out)
|
|
|
2ff057 |
Fclose(out); /* XXX dup'd STDOUT_FILENO */
|
|
|
2ff057 |
|
|
|
2ff057 |
if (fn) {
|
|
|
2ff057 |
if (!rpmIsDebug())
|
|
|
2ff057 |
unlink(fn);
|
|
|
2ff057 |
free(fn);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(mline);
|
|
|
2ff057 |
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
|
|
|
2ff057 |
ARGV_const_t prefixes, int warn_only, rpmPlugins plugins)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
ARGV_t args = NULL;
|
|
|
2ff057 |
rpmlogLvl lvl = warn_only ? RPMLOG_WARNING : RPMLOG_ERR;
|
|
|
2ff057 |
rpmRC rc;
|
|
|
2ff057 |
int script_type = RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (script == NULL) return RPMRC_OK;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* construct a new argv as we can't modify the one from header */
|
|
|
2ff057 |
if (script->args) {
|
|
|
2ff057 |
argvAppend(&args, script->args);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
argvAdd(&args, "/bin/sh");
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rstreq(args[0], "<lua>"))
|
|
|
2ff057 |
script_type = RPMSCRIPTLET_NONE;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Run scriptlet pre hook for all plugins */
|
|
|
2ff057 |
rc = rpmpluginsCallScriptletPre(plugins, script->descr, script_type);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rc != RPMRC_FAIL) {
|
|
|
2ff057 |
if (script_type & RPMSCRIPTLET_EXEC) {
|
|
|
2ff057 |
rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Run scriptlet post hook for all plugins */
|
|
|
2ff057 |
rpmpluginsCallScriptletPost(plugins, script->descr, script_type, rc);
|
|
|
2ff057 |
|
|
|
2ff057 |
argvFree(args);
|
|
|
2ff057 |
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmscriptTypes getScriptType(rpmTagVal scriptTag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return findTag(scriptTag)->type;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmTagVal getProgTag(rpmTagVal scriptTag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return findTag(scriptTag)->progtag;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmTagVal getFlagTag(rpmTagVal scriptTag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return findTag(scriptTag)->flagtag;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static const char * tag2sln(rpmTagVal tag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return findTag(tag)->desc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body,
|
|
|
2ff057 |
rpmscriptFlags flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
|
|
|
2ff057 |
rpmScript script = xcalloc(1, sizeof(*script));
|
|
|
2ff057 |
script->tag = tag;
|
|
|
2ff057 |
script->type = getScriptType(tag);
|
|
|
2ff057 |
script->flags = flags;
|
|
|
2ff057 |
script->body = (body != NULL) ? xstrdup(body) : NULL;
|
|
|
2ff057 |
rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* macros need to be expanded before possible queryformat */
|
|
|
2ff057 |
if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) {
|
|
|
2ff057 |
char *body = rpmExpand(script->body, NULL);
|
|
|
2ff057 |
free(script->body);
|
|
|
2ff057 |
script->body = body;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (script->body && (script->flags & RPMSCRIPT_FLAG_QFORMAT)) {
|
|
|
2ff057 |
/* XXX TODO: handle queryformat errors */
|
|
|
2ff057 |
char *body = headerFormat(h, script->body, NULL);
|
|
|
2ff057 |
free(script->body);
|
|
|
2ff057 |
script->body = body;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
script->nextFileFunc.func = NULL;
|
|
|
2ff057 |
script->nextFileFunc.param = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
free(nevra);
|
|
|
2ff057 |
return script;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *),
|
|
|
2ff057 |
void *param)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
script->nextFileFunc.func = func;
|
|
|
2ff057 |
script->nextFileFunc.param = param;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal triggerDsTag(rpmscriptTriggerModes tm)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tag = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
switch (tm) {
|
|
|
2ff057 |
case RPMSCRIPT_NORMALTRIGGER:
|
|
|
2ff057 |
tag = RPMTAG_TRIGGERNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSCRIPT_FILETRIGGER:
|
|
|
2ff057 |
tag = RPMTAG_FILETRIGGERNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSCRIPT_TRANSFILETRIGGER:
|
|
|
2ff057 |
tag = RPMTAG_TRANSFILETRIGGERNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tag;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmscriptTriggerModes triggerMode(rpmTagVal tag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmscriptTriggerModes tm = 0;
|
|
|
2ff057 |
switch (tag) {
|
|
|
2ff057 |
case RPMTAG_TRIGGERNAME:
|
|
|
2ff057 |
tm = RPMSCRIPT_NORMALTRIGGER;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_FILETRIGGERNAME:
|
|
|
2ff057 |
tm = RPMSCRIPT_FILETRIGGER;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_TRANSFILETRIGGERNAME:
|
|
|
2ff057 |
tm = RPMSCRIPT_TRANSFILETRIGGER;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tm;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal triggertag(rpmsenseFlags sense)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tag = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
switch (sense) {
|
|
|
2ff057 |
case RPMSENSE_TRIGGERIN:
|
|
|
2ff057 |
tag = RPMTAG_TRIGGERIN;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSENSE_TRIGGERUN:
|
|
|
2ff057 |
tag = RPMTAG_TRIGGERUN;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSENSE_TRIGGERPOSTUN:
|
|
|
2ff057 |
tag = RPMTAG_TRIGGERPOSTUN;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSENSE_TRIGGERPREIN:
|
|
|
2ff057 |
tag = RPMTAG_TRIGGERPREIN;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tag;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmScript rpmScriptFromTriggerTag(Header h, rpmTagVal triggerTag,
|
|
|
2ff057 |
rpmscriptTriggerModes tm, uint32_t ix)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmScript script = NULL;
|
|
|
2ff057 |
struct rpmtd_s tscripts, tprogs, tflags;
|
|
|
2ff057 |
headerGetFlags hgflags = HEADERGET_MINMEM;
|
|
|
2ff057 |
|
|
|
2ff057 |
switch (tm) {
|
|
|
2ff057 |
case RPMSCRIPT_NORMALTRIGGER:
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRIGGERSCRIPTS, &tscripts, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRIGGERSCRIPTPROG, &tprogs, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRIGGERSCRIPTFLAGS, &tflags, hgflags);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSCRIPT_FILETRIGGER:
|
|
|
2ff057 |
headerGet(h, RPMTAG_FILETRIGGERSCRIPTS, &tscripts, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_FILETRIGGERSCRIPTPROG, &tprogs, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_FILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMSCRIPT_TRANSFILETRIGGER:
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTS, &tscripts, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTPROG, &tprogs, hgflags);
|
|
|
2ff057 |
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmtdSetIndex(&tscripts, ix) >= 0 && rpmtdSetIndex(&tprogs, ix) >= 0) {
|
|
|
2ff057 |
rpmscriptFlags sflags = 0;
|
|
|
2ff057 |
const char *prog = rpmtdGetString(&tprogs);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmtdSetIndex(&tflags, ix) >= 0)
|
|
|
2ff057 |
sflags = rpmtdGetNumber(&tflags);
|
|
|
2ff057 |
|
|
|
2ff057 |
script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* hack up a hge-style NULL-terminated array */
|
|
|
2ff057 |
script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1);
|
|
|
2ff057 |
script->args[0] = (char *)(script->args + 2);
|
|
|
2ff057 |
script->args[1] = NULL;
|
|
|
2ff057 |
strcpy(script->args[0], prog);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtdFreeData(&tscripts);
|
|
|
2ff057 |
rpmtdFreeData(&tprogs);
|
|
|
2ff057 |
rpmtdFreeData(&tflags);
|
|
|
2ff057 |
|
|
|
2ff057 |
return script;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmScript rpmScriptFromTag(Header h, rpmTagVal scriptTag)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmScript script = NULL;
|
|
|
2ff057 |
rpmTagVal progTag = getProgTag(scriptTag);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (headerIsEntry(h, scriptTag) || headerIsEntry(h, progTag)) {
|
|
|
2ff057 |
struct rpmtd_s prog;
|
|
|
2ff057 |
|
|
|
2ff057 |
script = rpmScriptNew(h, scriptTag,
|
|
|
2ff057 |
headerGetString(h, scriptTag),
|
|
|
2ff057 |
headerGetNumber(h, getFlagTag(scriptTag)));
|
|
|
2ff057 |
|
|
|
2ff057 |
if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) {
|
|
|
2ff057 |
script->args = prog.data;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return script;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmScript rpmScriptFree(rpmScript script)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (script) {
|
|
|
2ff057 |
free(script->args);
|
|
|
2ff057 |
free(script->body);
|
|
|
2ff057 |
free(script->descr);
|
|
|
2ff057 |
free(script);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmScriptTag(rpmScript script)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (script != NULL) ? script->tag : RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmscriptTypes rpmScriptType(rpmScript script)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (script != NULL) ? script->type : 0;
|
|
|
2ff057 |
}
|