On 09/16/13 20:48, Craig R. Skinner wrote:
On 2013-09-16 Mon 15:12 PM |, Paul de Weerd wrote:
Hi Craig,

--- cat bad_script.sh ------------------------------------------------
# This is a VERY BAD example of a script!  This will break your
# shebang thingambob

echo Now what...
----------------------------------------------------------------------

I think you'd be better of making sure the first two characters in the
file are actually "#!":

        head -n1 ${FILE} | grep '^#!' | sed 's/^#![[:blank:]]*//'


Good idea Paul.

Implemented below, along with rudimentary testing for a valid
interpreter:


Index: rc.subr
===================================================================
RCS file: /cvs/src/etc/rc.d/rc.subr,v
retrieving revision 1.70
diff -u -r1.70 rc.subr
--- rc.subr     11 Jul 2013 09:34:33 -0000      1.70
+++ rc.subr     16 Sep 2013 18:19:14 -0000
@@ -221,4 +221,15 @@
  unset _rcflags _rcuser

  pexp="${daemon}${daemon_flags:+ ${daemon_flags}}"
+file ${daemon} | fgrep -q script &&
+{
+       shebang=$(head -n 1 ${daemon} | grep '^#!' | sed 's/^#![[:blank:]]*//')
+       interpreter=$(echo ${shebang} | cut -d' ' -f1)

sed can do it all. Really. Notes:

- I separate re_quote() cause I think it can be useful in other places.
- I think re_quote() is (basic) regex complete.
- I don't care if the interpreter is (or seems) nonexistant, as that
  shouldn't be a runtime error.
- I'm sure sed may die horribly if you try to feed it a 9GB oneline
  file. However, if so, it should not produce any output anyway. ;)
  If this would ever be considered a real problem, dd(1) would help
  (as espie already mentioned).

        re_quote() { sed 's/\([]^$*.\\[]\)/\\\1/g'; }

        interpreter=$(
                sed -n 's/^#![[:space:]]*\(.*\)/\1 /p;q' "${daemon}" |
                re_quote)
        pexp="$interpreter$pexp"

Moreover,

- you probably want to unset $interpreter when done.
- we might want to re_quote the entire $pexp later instead.

/Alexander

+       if [[ -f ${interpreter} && -x ${interpreter} ]]
+       then
+               pexp="${shebang} ${pexp}"
+       else
+               rc_err "$0: invalid interpreter: ${interpreter}"
+       fi
+}
  rcexec="su -l -c ${daemon_class} -s /bin/sh ${daemon_user} -c"


Test scripts:

#-=-= /etc/rc.d/rcshebangtester -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#!/bin/sh

#daemon="/home/me/bin/rcshebangtester.dud"
#daemon="/home/me/bin/rcshebangtester.ksh"
daemon="/home/me/bin/rcshebangtester.pl"

. /etc/rc.d/rc.subr

rc_bg=YES
#pexp="/bin/ksh ${daemon}"
#pexp="/usr/bin/perl -T ${daemon}"
#pexp="/usr/bin/perl ${daemon}"

rc_cmd $1

#-=-= /home/me/bin/rcshebangtester.dud -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#!/var/empty
#!       /dev/null
#! /usr/lib/libc.a
# swap about above

echo 'Busted!'

#-=-= /home/me/bin/rcshebangtester.ksh =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#! /bin/ksh -x
#!      /bin/ksh
# swap about above

while true
do
        uptime
        sleep 1
done

#-=-= /home/me/bin/rcshebangtester.pl =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#!       /usr/bin/perl -T
#!/usr/bin/perl
# swap about above

use strict;
use warnings;

for(;;)
{
        print time(), "\n";
        sleep 1;
}

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

$ sudo /etc/rc.d/rcshebangtester -d -f start; \
cat /var/run/rc.d/rcshebangtester; echo; sleep 5; \
sudo /etc/rc.d/rcshebangtester -d -f stop
doing rc_read_runfile
doing rc_check
rcshebangtester
doing rc_start
1379357218
1379357219
doing rc_wait start
doing rc_check
doing rc_write_runfile
(ok)
/usr/bin/perl -T /home/me/bin/rcshebangtester.pl
1379357220
1379357221
1379357222
1379357223
1379357224
doing rc_read_runfile
doing rc_check
rcshebangtester
doing rc_stop
doing rc_wait stop
doing rc_check
doing rc_rm_runfile
(ok)


#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


Any other thoughts?


Reply via email to