[Android Software/Hacking General [Developers Only]] dk_zero-cool:
Okay, I worked a bit on something to add a little more options to init.d scripts for my ROM's. I came up with the below solution and thought I should share it with whomever would like a bit more options in their own ROM's. This is a first draft so some of things can properly be done in other ways, but it works and it does add a lot more options when building startup scripts while it is compatible with regular init.d scripts as well. But fell free to pitch in with ideas if you like.

Note that this thread is directed to ROM cookers, but can be used by anyone that knows how to edit ramdisk's.

So there are several problems with the regular init.d methods. First of all there are two different ways of executing the scripts and it differs from ROM to ROM which method has been implemented. We have the "exec /system/bin/sysinit" which will execute all of the scripts before continuing with the normal boot and we have the service sysinit which will execute all scripts while the normal boot is running. Both are useful for different things but no ROM has both.

Also init.d will just start executing the scripts before/during the normal boot, depended on the method, but what if we need it to execute something at a specific time during boot. Before folder structures and such are created in /data? Or when the phone has completely booted into the GUI. Or before the phone is turned off and so on.

This method will implement different states where different parts of a script can be executed depended on where in the boot process we are. All it requires is a more extended sysinit file and a couple of extra lines in the init.rc file.

File: /init.rc

on early-init
##
# Whatever goes here
##

on init
##
# Whatever goes here
##

on fs
##
# Mount /system
##

# Make sure that we have the synlinks we need to use sysinit
symlink /system/bin/sysinit /system/bin/sysinit.onstart
symlink /system/bin/sysinit /system/bin/sysinit.onfs
symlink /system/bin/sysinit /system/bin/sysinit.onpostfs
symlink /system/bin/sysinit /system/bin/sysinit.onpostfsdata
symlink /system/bin/sysinit /system/bin/sysinit.onboot
symlink /system/bin/sysinit /system/bin/sysinit.onsysinit
symlink /system/bin/sysinit /system/bin/sysinit.onfinalize
symlink /system/bin/sysinit /system/bin/sysinit.oncomplete
symlink /system/bin/sysinit /system/bin/sysinit.onshutdown

exec /system/bin/sysinit.onstart

##
# Mount the rest of the partitions and remount /system without write permissions
##

exec /system/bin/sysinit.onfs

on post-fs
##
# Whatever goes here
##

exec /system/bin/sysinit.onpostfs

on post-fs-data
##
# Whatever goes here
##

exec /system/bin/sysinit.onpostfsdata

##
# If you want to include an additional *.rc file, do it here at the end of post-fs-data
##

on boot
##
# Whatever goes here
##

exec /system/bin/sysinit.onboot

start sysinit

##
# Start any other services
##

on property:init.svc.bootanim=stopped
start syscomplete

on property:sys.boot_completed=1
exec /system/bin/sysinit.onfinalize

on property:sys.shutdown.requested=1
exec /system/bin/sysinit.onshutdown

service sysinit /system/bin/sysinit.onsysinit
disabled
oneshot

service syscomplete /system/bin/sysinit.oncomplete
disabled
oneshot

##
# The rest of the file
##

File: /system/bin/sysinit

#!/system/bin/sh

export PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin

if [ -d /system/etc/init.d ]; then
case $(basename $0) in
"sysinit") INIT_STATE="$1" ;;
*) INIT_STATE="`basename $0 | cut -d '.' -f2`" ;;
esac

while :
do
if [ ! -f /sysinit.stage.prop ]; then
mount -o remount,rw /
touch /sysinit.stages.prop
mount -o remount,ro /
fi

if ( [ "$INIT_STATE" != "onfinalize" ] && [ "$INIT_STATE" != "oncomplete" ] ) || ( [ "$INIT_STATE" = "onfinalize" ] && [ ! -z "`grep onpostsysinit /sysinit.stages.prop`" ] ) || ( [ "$INIT_STATE" = "oncomplete" ] && [ ! -z "`grep onfinalize /sysinit.stages.prop`" ] ); then
if [ "$INIT_STATE" = "onsysinit" ]; then
RUN_STATES="onsysinit onpostsysinit"; sleep 1

elif [ "$INIT_STATE" = "oncomplete" ]; then
RUN_STATES="onservice oncomplete"

else
RUN_STATES="$INIT_STATE"
fi

for x in $RUN_STATES; do
log -p v -t sysinit "Switching to state '$x'..."

case $x in
# Make it compatible with old init scripts
onboot|"") FILES="`find /system/etc/init.d -type f | sort`" ;;
*) FILES="`find /system/etc/init.d -type f -iname '*.rc' | sort`" ;;
esac

for i in $FILES; do
if [ ! -d $i ] && [ -x $i ]; then
log -p v -t sysinit "Executing $i..."

if [ "$x" = "onservice" ]; then
logwrapper $i $x > /dev/null &
else
logwrapper $i $x
fi

else
log -p w -t sysinit "Skipping $i. Not an executable!"
fi
done

mount -o remount,rw /
echo $x >> /sysinit.stages.prop
mount -o remount,ro /
done

break
fi

sleep 1
done
fi

To use this you need to end the names of your init script with .rc like "55<name>.rc" instead of just "55<name>". This is to keep it compatible with regular init.d scripts.

This will allow you to build init.d scripts like this

#!/system/bin/sh

case $1 in
onstart)
# Do something right after the system partition has been mounted RW (No other partitions at this time)
;;

onfs)
# Do something right after the rest of partitions has been mounted and system has been remounted RO, before any of them are used or changed in any way.
;;

onpostfs)
# This is almost the same as onfs, only minor changes has normally been made here
;;

onpostfsdata)
# Do something after the /data partition has been rebuild with folders, permission, ownership and so on
;;

onboot)
# Do something right before Android starts booting and it's services are triggered
;;

onsysinit)
# Do something while Android is booting. This will NOT stall the boot process but run along side it
;;

onpostsysinit)
# Do something as soon as onsysinit has finished
;;

onfinalize)
# Do something when the system is almost booted, this also includes the sysinit parts above
;;

onservice)
# Do some constant work in the background (Service/Daemon)
;;

oncomplete)
# Do something when the phone is fully booted and the boot animation is gone
;;

onshutdown)
# Do something before the phone is turned off or rebooted
;;
esac

EDIT 1

Added 'onfinalize' which is actually the old oncomplete. The new oncomplete runs as a service like onsysinit and onpostsysinit to ensure that you are able to use things like "sleep" without stalling the system.

Rewrote sysinit, much cleaner now

EDIT 2

Added 'onservice' which can be used to run a constant task in the background after the phone has booted