[Galaxy S I9000 Android Development] Chainfire:
Took me a few minutes to figure this out, so I thought to share :)

This is taken from some scripts I use in CF-Root, you might need to change it slightly for other CWM3 kernels (like prefixing busybox to various commands, etc).

updater-script

Assumptions:

- rootfs is mounted as rw, so we can write temporary files anywhere (ram disk)

- you put a "myscript.sh" in the system folder inside the update

All this script does is extract whatever you have in update.zip/system folder to /tmp/update, and run the myscript.sh file.

ui_print("Extracting files ...");
package_extract_dir("system", "/tmp/update");
set_perm(0, 0, 0755, "/tmp/update/myscript.sh");
run_program("/tmp/update/myscript.sh");

myscript.sh

Assumptions:

- all busybox commands are symlinked in /sbin, this is usually the case for CWM3 kernels

#!/sbin/busybox sh

# get file descriptor for output
OUTFD=$(ps | grep -v "grep" | grep -o -E "update_binary(.*)" | cut -d " " -f 3);

# same as progress command in updater-script, for example:
#
# progress 0.25 10
#
# will update the next 25% of the progress bar over a period of 10 seconds

progress() {
if [ $OUTFD != "" ]; then
echo "progress ${1} ${2} " 1>&$OUTFD;
fi;
}

# same as set_progress command in updater-script, for example:
#
# set_progress 0.25
#
# sets progress bar to 25%

set_progress() {
if [ $OUTFD != "" ]; then
echo "set_progress ${1} " 1>&$OUTFD;
fi;
}

# same as ui_print command in updater_script, for example:
#
# ui_print "hello world!"
#
# will output "hello world!" to recovery, while
#
# ui_print
#
# outputs an empty line

ui_print() {
if [ $OUTFD != "" ]; then
echo "ui_print ${1} " 1>&$OUTFD;
echo "ui_print " 1>&$OUTFD;
else
echo "${1}";
fi;
}

# --- example usage ---

# empty line after "Extracting ..." from updater-script
ui_print;

# give the user some status
ui_print "doing something (1 of 4)";
# assume this won't take more than 30 seconds
progress 0.25 30;
# you'd do something useful here
sleep 15s;
# update status
ui_print "- done with something (1 of 4)";
# we're done, make sure the progress bar is at 25%
set_progress 0.25;
# empty line
ui_print;

# repeat this a few times ;)

ui_print "doing something (2 of 4)";
progress 0.25 30;
sleep 15s;
ui_print "- done with something (2 of 4)";
set_progress 0.50;
ui_print;

ui_print "doing something (3 of 4)";
progress 0.25 30;
sleep 15s;
ui_print "- done with something (3 of 4)";
set_progress 0.75;
ui_print;

ui_print "doing something (4 of 4)";
progress 0.25 30;
sleep 15s;
ui_print "- done with something (4 of 4)";
set_progress 1.00;
ui_print;

# done !
ui_print "done! rebooting!";

How, what, why ?

While updater-script is fine for a lot of things, like installing a new ROM and whatnot, anything sufficiently complicated still has to be done through shell scripts, because a great many things just cannot be easily done in edify. It's nice to be able to give the user some status when doing these operations. There are modded versions of CWM that make the same thing possible in other ways, like simply writing to STDOUT or STDERR. This requires either a custom update_binary or recovery binary, though.

This works because communication between recovery and update_binary is through a file descriptor (pipe). Recovery runs update_binary with the FD as command line parameter. Because the shell script is run as a child process of update_binary, it can write the same commands to that FD (commands recovery listens for), because child processes inherited FD numbers and access rights.

So, all the script has to do is figure out which FD to write to, and pass it the right commands. Finding the FD isn't difficult, as it is passed on the command line and so is listed in the output of ps. Some grep and cut magic retrieve it. See the OUTFD=$(...) line. The right commands are defined in the functions at the top.

Note: this is all taken from my rfs<=>ext4 conversion script for CF-Root/ext4. Slightly adjusted, hopefully it still works as expected ;)

Enjoy!