From a1c8bd2337f1665d43b44da9e0332b954ec0a06e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Sun, 11 Jan 2015 11:42:30 +0100
Subject: [PATCH] wrapper script: workaround kernel limitation in shebang line
 length

http://stackoverflow.com/a/10826085
---
 slapos/recipe/librecipe/generic.py | 20 +++++++++++++++++---
 slapos/recipe/wrapper.py           | 15 +++++++++++----
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/slapos/recipe/librecipe/generic.py b/slapos/recipe/librecipe/generic.py
index 9019abe6f..f56c64760 100644
--- a/slapos/recipe/librecipe/generic.py
+++ b/slapos/recipe/librecipe/generic.py
@@ -134,13 +134,14 @@ class GenericBaseRecipe(object):
       pidfile=None
   ):
     """
-    Creates a very simple (one command) shell script for process replacement.
+    Creates a shell script for process replacement.
     Takes care of quoting.
+    Takes care of #! line limitation when the wrapped command is a script.
     if pidfile parameter is specified, then it will make the wrapper a singleton,
     accepting to run only if no other instance is running.
     """
 
-    lines = [ '#!/bin/sh' ]
+    lines = [ '#!/bin/bash' ]
 
     for comment in comments:
       lines.append('# %s' % comment)
@@ -164,7 +165,20 @@ class GenericBaseRecipe(object):
           fi
           echo $$ > $pidfile""" % (pidfile, command)))
 
-    lines.append('exec %s' % shlex.quote(command))
+    # Inspired by http://stackoverflow.com/a/10826085
+    lines.append(dedent("""\
+    COMMAND=%s
+
+    # If the wrapped command uses a shebang, execute the referenced
+    # executable passing the script path as first argument.
+    # This is to workaround the limitation of 127 characters in #!
+    if [[ -f $COMMAND && x$(head -c2 "$COMMAND") = x"#!" ]]; then
+      SHEBANG=$(head -1 "$COMMAND")
+      INTERPRETER=( ${SHEBANG#\#!} )
+      COMMAND="${INTERPRETER[@]} $COMMAND"
+    fi
+
+    exec $COMMAND """ % shlex.quote(command)))
 
     for param in parameters:
       if len(lines[-1]) < 40:
diff --git a/slapos/recipe/wrapper.py b/slapos/recipe/wrapper.py
index cb0f1c266..cb1cddb61 100644
--- a/slapos/recipe/wrapper.py
+++ b/slapos/recipe/wrapper.py
@@ -54,8 +54,15 @@ class Recipe(GenericBaseRecipe):
         if environment is not None:
             environment = dict((k.strip(), v.strip()) for k, v in [
               line.split('=') for line in environment.splitlines() if line.strip() ])
-        return [self.createPythonScript(
-            wrapper_path,
+
+        # We create a python script and a wrapper around the python
+        # script because the python script might have a too long #! line
+        python_script = self.createPythonScript(
+            wrapper_path+'.py',
             'slapos.recipe.librecipe.execute.generic_exec',
-            (command_line, wait_files, environment,),
-        )]
+            (command_line, wait_files, environment,), )
+        return [python_script, self.createWrapper(
+             name=wrapper_path,
+             command=python_script,
+             parameters_extra=parameters_extra) ]
+
-- 
2.30.9