###############################################################################
import os
+import sys
import chroot
import packages
# Load the scriplet.
self.scriptlet = self.pkg.get_scriptlet(self.script_action)
+ def get_lang(self):
+ if not self.scriptlet:
+ return
+
+ interp = None
+
+ for line in self.scriptlet.splitlines():
+ if line.startswith("#!/"):
+ interp = "exec"
+ break
+
+ elif line.startswith("#<lang: "):
+ interp = line[8:].replace(">", "")
+ break
+
+ return interp
+
@property
def interpreter(self):
"""
# Actually run the scriplet.
log.debug("Running scriptlet %s" % self)
+ # Check of what kind the scriptlet is and run the
+ # corresponding handler.
+ lang = self.get_lang()
+
+ if lang == "exec":
+ self.run_exec()
+
+ elif lang == "python":
+ self.run_python()
+
+ else:
+ raise ActionError, _("Could not handle scriptlet of unknown type. Skipping.")
+
+ def run_exec(self):
+ log.debug(_("Executing python scriptlet..."))
+
# Check if the interpreter does exist and is executable.
if self.interpreter:
interpreter = "%s/%s" % (self.pakfire.path, self.interpreter)
except OSError:
log.debug("Could not remove scriptlet file: %s" % script_file)
+ def run_python(self):
+ # This functions creates a fork with then chroots into the
+ # pakfire root if necessary and then compiles the given scriptlet
+ # code and runs it.
+
+ log.debug(_("Executing python scriptlet..."))
+
+ # Create fork.
+ pid = os.fork()
+
+ if not pid:
+ # child code
+
+ # The child chroots into the pakfire path.
+ if not self.pakfire.path == "/":
+ os.chroot(self.pakfire.path)
+
+ # Create a clean global environment, where only
+ # builtin functions are available and the os and sys modules.
+ _globals = {
+ "os" : os,
+ "sys" : sys,
+ }
+
+ # Compile the scriptlet and execute it.
+ try:
+ obj = compile(self.scriptlet, "<string>", "exec")
+ eval(obj, _globals, {})
+
+ except Exception, e:
+ print _("Exception occured: %s") % e
+ os._exit(1)
+
+ # End the child process without cleaning up.
+ os._exit(0)
+
+ else:
+ # parent code
+
+ # Wait until the child process has finished.
+ os.waitpid(pid, 0)
+
class ActionScriptPreIn(ActionScript):
script_action = "prein"
LEXER_PACKAGE_END = LEXER_BLOCK_END
LEXER_PACKAGE_INHERIT = re.compile(r"^template ([A-Z0-9]+)$")
-LEXER_SCRIPTLET_BEGIN = re.compile(r"^script ([a-z]+)\s?(/[A-Za-z0-9\-\_/]+)?$")
+LEXER_SCRIPTLET_BEGIN = re.compile(r"^script ([a-z]+)\s?(shell|python)?$")
LEXER_SCRIPTLET_LINE = LEXER_BLOCK_LINE
LEXER_SCRIPTLET_END = LEXER_BLOCK_END
if self.scriptlets.has_key(name):
raise Exception, "Scriptlet %s is already defined" % name
- path = m.group(2)
- if path:
- self.scriptlets[name] = {
- "lang" : "bin",
- "path" : self.expand_string(path),
- }
- return
+ lang = m.group(2) or "shell"
+ lines = [
+ "#<lang: %s>" % lang,
+ ]
- lines = []
while True:
line = self.get_line(self._lineno, raw=True)
raise LexerUnhandledLine, "%d: %s" % (self.lineno, line)
self.scriptlets[name] = {
- "lang" : "shell",
- "scriptlet" : "\n".join(lines),
+ "lang" : lang,
+ "scriptlet" : self.expand_string("\n".join(lines)),
}
def get_scriptlet(self, name):
# Write script to a file.
scriptlet_file = self.mktemp()
- if scriptlet["lang"] == "bin":
+ lang = scriptlet["lang"]
+
+ if lang == "bin":
path = lang["path"]
try:
f = open(path, "b")
f.close()
s.close()
- elif scriptlet["lang"] == "shell":
+ elif lang == "shell":
s = open(scriptlet_file, "w")
# Write shell script to file.
s.write("#!/bin/sh -e\n\n")
s.write(scriptlet["scriptlet"])
s.write("\n\nexit 0\n")
-
s.close()
if scriptlet_name in SCRIPTS_PREREQUIRES:
prerequires += self.builder.find_prerequires(scriptlet_file)
+ elif lang == "python":
+ # Write the code to the scriptlet file.
+ s = open(scriptlet_file, "w")
+ s.write(scriptlet["scriptlet"])
+ s.close()
+
else:
raise Exception, "Unknown scriptlet language: %s" % scriptlet["lang"]