Add rpmScriptNextFiletFunc()

This enables assigning some function to script. Purpose of this
function is to provide input data for scripts. Forkable script can read
these data from its stdin and lua script can read these data with
function rpm.next_file()
This commit is contained in:
Lubos Kardos 2015-01-22 12:23:22 +01:00
parent 846d0e0203
commit 278c552666
4 changed files with 89 additions and 11 deletions

View File

@ -19,6 +19,13 @@
#include "debug.h"
struct scriptNextFileFunc_s {
char *(*func)(void *); /* function producing input for script */
void *param; /* parameter for func */
};
typedef struct scriptNextFileFunc_s *scriptNextFileFunc;
struct rpmScript_s {
rpmscriptTypes type; /* script type */
rpmTagVal tag; /* script tag */
@ -26,6 +33,7 @@ struct rpmScript_s {
char *body; /* script body */
char *descr; /* description for logging */
rpmscriptFlags flags; /* flags to control operation */
struct scriptNextFileFunc_s nextFileFunc; /* input function */
};
struct scriptInfo_s {
@ -76,7 +84,8 @@ static const struct scriptInfo_s * findTag(rpmTagVal tag)
*/
static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
const char *sname, rpmlogLvl lvl, FD_t scriptFd,
ARGV_t * argvp, const char *script, int arg1, int arg2)
ARGV_t * argvp, const char *script, int arg1, int arg2,
scriptNextFileFunc nextFileFunc)
{
rpmRC rc = RPMRC_FAIL;
#ifdef WITH_LUA
@ -90,6 +99,7 @@ static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
/* Create arg variable */
rpmluaPushTable(lua, "arg");
rpmluavSetListMode(var, 1);
rpmluaSetNextFileFunc(nextFileFunc->func, nextFileFunc->param);
if (argv) {
char **p;
for (p = argv; *p; p++) {
@ -141,19 +151,12 @@ static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr
static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
FD_t scriptFd, FD_t out)
{
int pipes[2];
int flag;
int fdno;
int xx;
int open_max;
(void) signal(SIGPIPE, SIG_DFL);
pipes[0] = pipes[1] = 0;
/* make stdin inaccessible */
xx = pipe(pipes);
xx = close(pipes[1]);
xx = dup2(pipes[0], STDIN_FILENO);
xx = close(pipes[0]);
/* XXX Force FD_CLOEXEC on all inherited fdno's. */
open_max = sysconf(_SC_OPEN_MAX);
@ -246,12 +249,17 @@ exit:
*/
static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
const char *sname, rpmlogLvl lvl, FD_t scriptFd,
ARGV_t * argvp, const char *script, int arg1, int arg2)
ARGV_t * argvp, const char *script, int arg1, int arg2,
scriptNextFileFunc nextFileFunc)
{
FD_t out = NULL;
char * fn = NULL;
pid_t pid, reaped;
int status;
int inpipe[2];
FILE *in;
const char *line;
char *mline = NULL;
rpmRC rc = RPMRC_FAIL;
rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname);
@ -274,6 +282,14 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
}
}
if (pipe(inpipe) < 0) {
rpmlog(RPMLOG_ERR,
("Couldn't create pipe: %s\n"), strerror(errno));
goto exit;
}
in = fdopen(inpipe[1], "w");
inpipe[1] = 0;
if (scriptFd != NULL) {
if (rpmIsVerbose()) {
out = fdDup(Fileno(scriptFd));
@ -301,6 +317,9 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n",
sname, *argvp[0], (unsigned)getpid());
fclose(in);
dup2(inpipe[0], STDIN_FILENO);
/* Run scriptlet post fork hook for all plugins */
if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) {
doScriptExec(*argvp, prefixes, scriptFd, out);
@ -309,6 +328,25 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
}
}
if (nextFileFunc->func) {
while ((line = nextFileFunc->func(nextFileFunc->param)) != NULL) {
size_t size = strlen(line);
mline = xstrdup(line);
mline[size] = '\n';
if (fwrite(mline, size + 1, 1, in) != 1) {
if (errno != EPIPE) {
rpmlog(RPMLOG_ERR, _("Fwrite failed: %s"), strerror(errno));
rc = RPMRC_FAIL;
goto exit;
}
}
mline = _free(mline);
}
}
fclose(in);
in = NULL;
do {
reaped = waitpid(pid, &status, 0);
} while (reaped == -1 && errno == EINTR);
@ -333,6 +371,9 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
}
exit:
if (in)
fclose(in);
if (out)
Fclose(out); /* XXX dup'd STDOUT_FILENO */
@ -341,6 +382,7 @@ exit:
unlink(fn);
free(fn);
}
free(mline);
return rc;
}
@ -369,9 +411,9 @@ rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
if (rc != RPMRC_FAIL) {
if (script_type & RPMSCRIPTLET_EXEC) {
rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2);
rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
} else {
rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2);
rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc);
}
}
@ -427,10 +469,20 @@ static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body,
script->body = body;
}
script->nextFileFunc.func = NULL;
script->nextFileFunc.param = NULL;
free(nevra);
return script;
}
void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *),
void *param)
{
script->nextFileFunc.func = func;
script->nextFileFunc.param = param;
}
rpmScript rpmScriptFromTriggerTag(Header h, rpmTagVal triggerTag, uint32_t ix)
{
rpmScript script = NULL;

View File

@ -54,6 +54,10 @@ rpmTagVal rpmScriptTag(rpmScript script);
RPM_GNUC_INTERNAL
rpmscriptTypes rpmScriptType(rpmScript script);
RPM_GNUC_INTERNAL
void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *),
void *param);
#ifdef __cplusplus
}
#endif

View File

@ -60,6 +60,9 @@ struct rpmluapb_s {
static rpmlua globalLuaState = NULL;
static char *(*nextFileFunc)(void *) = NULL;
static void *nextFileFuncParam = NULL;
static int luaopen_rpm(lua_State *L);
static int rpm_print(lua_State *L);
@ -212,6 +215,12 @@ static int pushvar(lua_State *L, rpmluavType type, void *value)
return ret;
}
void rpmluaSetNextFileFunc(char *(*func)(void *), void *funcParam)
{
nextFileFunc = func;
nextFileFuncParam = funcParam;
}
void rpmluaSetVar(rpmlua _lua, rpmluav var)
{
INITSTATE(_lua, lua);
@ -685,6 +694,16 @@ static int rpm_interactive(lua_State *L)
return 0;
}
static int rpm_next_file(lua_State *L)
{
if (nextFileFunc)
lua_pushstring(L, nextFileFunc(nextFileFuncParam));
else
lua_pushstring(L, NULL);
return 1;
}
typedef struct rpmluaHookData_s {
lua_State *L;
int funcRef;
@ -876,6 +895,7 @@ static const luaL_Reg rpmlib[] = {
{"unregister", rpm_unregister},
{"call", rpm_call},
{"interactive", rpm_interactive},
{"next_file", rpm_next_file},
{NULL, NULL}
};

View File

@ -62,6 +62,8 @@ void rpmluaSetData(rpmlua lua, const char *key, const void *data);
char *rpmluaPopPrintBuffer(rpmlua lua);
void rpmluaPushPrintBuffer(rpmlua lua);
void rpmluaSetNextFileFunc(char *(*func)(void *), void *funcParam);
void rpmluaGetVar(rpmlua lua, rpmluav var);
void rpmluaSetVar(rpmlua lua, rpmluav var);
void rpmluaDelVar(rpmlua lua, const char *key, ...);