------------------------------------------------------------------------------ API for Hibernate Scriptlets ------------------------------------------------------------------------------ A scriptlet is written in shell code, and is simply sourced into the main script. This means it can potentially change a lot about the way suspending works. For sanity's sake though, their actions should be restricted to work through a small set of functions provided by the main hibernate script. These are documented below. A scriptlet can request both extra command-line arguments, or extra configuration file options. It can execute arbitrary commands during the suspend and resume process. NAMING ------ A scriptlet's name (filename) is restricted to alphanumerics and the underscore (_) character. Otherwise, things will break! It must not conflict with an existing script (the hibernate script will warn if it does). Function and variable names within the scriptlet should be sufficiently unique (eg, prefixed with the name of the scriptlet). STDOUT/STDERR ------------- A scriptlet should use vecho rather than echo, and choose a verbosity level appropriately (see vecho, below). All scriptlet output is automatically sent to $LOGPIPE FUNCTIONS --------- AddSuspendHook NN function_name This will add the given function to the chain of functions called at suspend. NN must be a number between 00 and 99, inclusive (see ORDERING section below). A scriptlet should only add a function to the suspend chain until it knows that it is going to do work (eg, it parses a config option to do something). eg: AddSuspendHook 55 SuspendHair AddResumeHook NN function_name Similar to above. See ORDERING section below. eg: AddSuspendHook 55 ResumeHair AddConfigHandler function_name The given function_name will be called when a configuration file line is read and hasn't been handled already. The entire line is passed as parameters to the function. The function must return 0 if it handled the function, and 1 otherwise. eg: AddConfigHandler HairParseConfig AddConfigHelp <config option name> <help text> Similar to above, but for configuration file options. eg: AddConfigHelp "HairTime <boolean>" "Allows some extra time to wash your hair while suspending." AddOptionHandler function_name The given function_name will be called when a command line option is received that hasn't been handled already. If the option has no parameter, then the function is called with a single paramter, which is the option itself in single quotes (eg, '-t' or '--time'). If the option has a parameter linked with it, the function is called with two parameters - the first is the option, as before and the second is the parameter. The function must return 0 if it handled the function, and 1 otherwise. eg: AddOptionHandler HairParseOptions AddShortOption <option character> Adds a short option to the list of accepted options for the function. eg: AddShortOption t AddLongOption <option name> Adds a long option to the list of accepted options for the function. eg: AddLongOption time AddOptionHelp <option name> <help text> Adds help text to the help screen. The help text must have each paragraph on a single line. eg: AddOptionHelp "-t, --time" "Allows some extra time to wash your hair while suspending. If you find you are often out of shampoo, then specifying this twice may give you enough time to duck out to the shops to get some and still wash your hair." vecho N <echo params> N is a verbosity level between 0 and 4 inclusive. If the given verbosity level is greater than or equal to N, the text will be written to screen and logged to file. Verbosity levels are : 0: silent except for errors 1: print functions executed 2: print functions executed with debugging 3: print functions executed with lots of debugging 4: use shell's -x option to print every command executed (very noisy) HOOK FUNCTIONS -------------- Hook functions are called at the relevant point in the suspend/resume chain with no arguments. Suspend hooks can choose from the following return values: - 0 if they are successful. - 1 if they are unsuccessful but can be overridden with --force. - 2 if they are unsuccessful and the suspend *must* be stopped (a message is written indicating the suspend was aborted. - 3 if the scriptlet requires the suspend script to silently abort *right now*. ORDERING -------- Each scriptlet can register functions to be called at some stage in the suspend process. The stage is identified by a two-digit number, between 01 and 98, inclusive. 00 and 99 are reserved for use by scriptlets that implement a suspend method (eg, TuxOnIce) which require absolute certainty that they are the first and last things executing. On suspend, the scripts are called in ascending order. On resume, the scripts are called in descending order. The following general recommendations apply: 00 for standalone features instead of suspending (probably useful to return 3) 10 suspend capability detection 11 definitely going to suspend by this point 20 user programs stopped 30 services started/stopped 50 filesystems mounted/unmounted 60 networking start/stopped 90-91 kernel modules loaded/unloaded 95-98 all sorts of voodoo to get VT switching happy in all cases 99 reserved Running "bash admin/list-hooks.sh scriptlets.d/" will produce a list of all the hook functions in order of execution if you need to look closely. POSIX COMPLIANCE ---------------- In order to keep the script running correctly under not only bash, but ash and zsh, some extra care needs to be taken when writing scriptlets. The common points to note are: - source: Don't use source. use . instead. You also need to specify a path, even for files in the current directory (./foo). - = not == for string comparisons. For the script to work under zsh, certain options need to be changed in order to make zsh act less sensibly (see setopts at the start of hibernate.sh). WHITESPACE NAZI --------------- Not wanting to be too pedantic, but for consistency, whitespace should be done using "tabstop=8, shiftwidth=4, noexpandtab" and softtabs in vimspeak. This means that it renders well anywhere (tabstops are universally 8 spaces), and tabbing is consistent. Don't worry too much - I'll generally fix the whitespace in any code I commit. SKELETON EXAMPLE ---------------- This needs more work, but gives you the general idea of structure. --- snip: scriptlets.d/skeleton --- AddConfigHandler SkeletonOptions SkeletonSuspend() { return 0 } SkeletonResume() { return 0 } SkeletonOptions() { case $1 in *) return 1 esac if [ -z "$SKELETON_HOOKED" ] ; then AddSuspendHook 20 SkeletonSuspend AddResumeHook 20 SkeletonResume SKELETON_HOOKED=1 fi return 0 } $Id: SCRIPTLET-API 1220 2009-04-01 02:06:57Z nigel $