hprofile 2.0 ReadMe
-------------------

READ THIS FILE BEFORE YOU DO ANYTHING STUPID (That is, read it, then go do
something stupid). No, seriously. You may think you know all there is to know 
about everything there is anything to know anything about, but you don't know 
jack about hprofile until you've read the readme. Or put differently - these
scripts have the potential to screw your system over in more than one way, and
if you just randomly drop files in /etc/hprofile/files, alter a few boot 
scripts and think that's that, you're more than likely to lose a few pretty
long and important configuration files. You have been warned! That said, this
program works wonders for me, and there's no reason why it shouldn't for you.

0. The quick and dirty installation guide:

Work from the examples! 

  - Run the 'install' script as root to install the scripts and example 
     configuration. 
  - Run "hprofile -h" and "hprunlevel -h" to get an overview of their 
     capabilities. 
  - Have a look at the example configurations in /etc/hprofile. 

The thing to realise quickly is that a "profile type" is a grouping of profiles
for a specific type of configuration (e.g. a 'power' profile type contains 
profiles like AC, Battery or Performance). Each profile type has a configuration
directory in /etc/hprofile/profiles (and possibly in ~/.hprofile/profiles/) 
where it defines scripts to be run when profiles are applied or stopped, files 
to be substituted (for each file that varies between profiles, there is one 
version per profile, with an extension of ".<profile>", in a directory which 
mirrors its intended location in the file system), a list of which profiles are
valid (optional), and a script called 'ptest' which should output the name of
the currently valid profile (e.g. after examining some state of the system,
or even asking the user).

Read on for more detailed help.

1. Preface

hprofile was written my Martin Aspeli <optilude@gmx.net>, and is released under
the GNU General Public License, version 2.0 (see the file COPYING). It comes
with NO WARRANTY WHATSOEVER. It works great for me, but if it decides to delete
all your files, blackmail your boss and run away with your mother-in-law, don't
come crying to me! Bug report and suggestions for improvements are always 
welcome, however.

2. Usage

The following sections describe how hprofile works and how to use it.

2.1. Overview

hprofile is a system consisting of three scripts, hprofile, hpdet and 
hprunlevel. I wrote it so that I could use my installation of Gentoo Linux
both in VMWare for Windows and for dual-booting. VMWare Workstation 3.0 comes
with some of this support, but their "dualconf" system was not flexible 
enough for me. Theoretically, you can use hprofile for any system where you'll
need different versions of core configuration files depending on the state your
computer is in. One example apart from VMWare would be a laptop which may or
may not be in a docking station.

As of version 2, hprofile has grown to include more general support for 
profiles. You can now run arbitrary scripts before and after a profile is
applied, and you can manage several types of profiles. The functionality offered
by hprofile version 1 is catered for by the 'boot' profile. Other profiles can
be defined to cater for different needs. For example, I use a 'net' profile to
manage my wireless network settings.

2.2. Defining and applying profiles

A "profile" is basically a collection of configuration files that need to be 
different depending on some external condition. Profiles are grouped into
types. For example, you can have a 'boot' profile that sets files such as
scripts in /etc/modules.d/ or /etc/X11/XF86Config depending on the state of
your hardware at bootup. Separately, you can have a 'net' profile that controls
the state of your network files, such as /etc/hosts or /etc/resolv.conf. Each
profile type must have a unique name, as must each profile. The 'boot' profile
called 'vmware' is referred to as 'boot.vmware' and is different from the 
profile 'boot.dualboot'. You could have a separate 'net' profile called 
'net.vmware', too. To switch profiles, you can run "hprofile <type>.<profile>",
for example "hprofile boot.vmware". It is also possible to automatically 
determine the profile using the "hpdet" script. In this case, run 
"hprofile <type>" only (e.g. "hprofile boot"). See the discussion on hpdet and
ptest below. Lastly, the 'boot' profile is special in that it can be associated
with a bootup runlevel. See the discssion on 'hprunlevel' below.

To define a profile type, create a directory in /etc/hprofile/profiles. For 
example, /etc/hprofile/profiles/boot is used to hold the configuration files
pertaining to the 'boot' profile. This directory should contain the following:

	- default    -> A text file containing the name of the default profile of
                   this type (and nothing else!).
	- files/     -> A directory mirroring the parts of the filesystem where
                   profile-specific files are found (more below).
	- ptest      -> An executable script used to determine the current profile.
                   The script should output the name of the current profile 
                   (only), or output nothing if it is unable to determine the
                   profile. In this case, the fallback profile specified in the
                   file 'default' will be assumed. This is only relevant where
                   hprofile or hprunlevel is called without a specific profile,
                   only a profile type.

Optional executable scripts:

	- pre-start  -> A script which, if present, will be run before file switching
                   takes place when the profile is applied.
	- post-start -> A script which, if present, will be run after file switching
                   takes place when the profile is applied.
	- stop       -> A script which, if present, will be run when the the current
                   profile is replaced, or if you run 'hprofile -s <type>'.
	- scripts/*  -> This directory contains executable scripts, at most two for
                   each profile, name <profile>.start and <profile>.stop. If
                   present, these will be run when the profile is started
                   (after configuration files have been switched) and stopped.

Optional configuration files:

	- profiles   -> A file listing all valid profiles of this type, one per line,
                   (and nothing else!). If this file is present, it will 
                   constrain the profiles considered by hprofile (i.e. hprofile
                   won't apply any profiles not listed in the profiles file); if
                   not, hprofile will look through the files in the 'files' 
                   directory and check their extensions to find profile names, 
                   which is a lot less efficient and could produce false 
                   positives.

The files/ directory is where the magic happens. This mirrors the file system
with configuration files. Each file is suffixed with the profile name. Hence,
the file /etc/hprofile/profiles/boot/files/etc/X11/XF86Config.vmware is the
VMWare-specific version of /etc/X11/XF86Config. The corresponding 
XF86Config.dualboot is the dualboot version. If you run 'hprofile boot.vmware',
a symbolic link will be created from /etc/X11/XF86Config to the file
/etc/hprofile/profiles/boot/files/etc/X11/XF86Config.vmware. The original will
be backed up to /etc/hprofile/profile/boot/files/etc/X11/XF86Config.bak if it
did not come from any of the 'boot' profiles.

Before this substitution takes place, the pre-start script found in
/etc/hprofile/profiles/<type>/pre-start will be run, if it exists and is 
executable. After the substitution takes place, the post-start script in
/etc/hprofile/profiles/<type>/post-start will be run, if it exists and is 
executable. In both cases, the name of the profile being switched too (e.g. 
'vmware' or 'dualboot' in the 'boot' profile example above) is passed to the 
script as a command-line argument. The name of the current profile is then 
stored in a plain text file in /var/run/hprofile/<type>. When a new profile
is applied subsequently, the previous profile's stop script, found in
/etc/hprofile/profiles/<type>/stop, is run, should it exist. This is passed
the name of the current profile (before the new profile is applied), as
found in the state file in /var/run/hprofile. You can also manually "stop" a
profile by running "hprofile -s <type>". This is useful if you start some
service from the post-start script, and wish to stop it in the stop script.

The functionality described above is all system-wide. hprofile assumes it runs
with root privileges, and pre-start, post-start and stop scripts are all run
with root privileges. In addition to this, each user listed in /etc/passwd with
a valid home directory, can create a ~/.hprofile/profiles/<type> directory. This
directory can then contain a similar mirroring as that of 
/etc/hprofile/profiles/<type>/files, but of the user's home directory. Hence, 
if the user wants to use a different ~/.xscreensaver file, say, to avoid 
enabling OpenGL graphics-intensive screensavers in a VMWare session (VMWare does
not have hardware-accelerated graphics), he can create the file 
~/.hprofile/profiles/boot/files/.xscreensaver.dualboot for the 'dualboot'
profile and ~/.hprofile/profiles/boot/files/.xscreensaver.vmware for the 
'vmware' profile. For obvious security reasons, this will only work on files 
inside the user's home directory! Hence, if the user creates
~/.hprofile/profiles/boot/files/etc/passwd.vmware he will not be able to 
overwrite /etc/passwd (can't blame a boy for tryin' though, can you?), but if 
there is a ~/etc/passwd for that user, that will be replaced. (If you understand
why that is, you've probably got a pretty good grasp on how hprofile works.) 

Users can also create pre-start, post-start or stop scripts for each profile
type, but for security reasons, these have to run with the privileges of the
user in question. To accomplish this, hprofile uses the 'sudo' tool, so make
sure it is installed. 

The order of execution of events when a new profile is applied, is as follows:

 1. Stop scripts for the current profile, presuming there is one
  1.1. User-level scripts (for each user):
   1.1.1. First, ~/.hprofile/profiles/<profile type>/stop
   1.1.2. Then, ~/.hprofile/profiles/<profile type>/scripts/<profile>.stop
  1.2. Global stop scripts
   1.2.1. First, /etc/hprofile/profiles/<profile type>/stop
   1.2.2. Then, /etc/hprofile/profiles/<profile type>/scrips/<profile>.stop

 2. Pre-start scripts for the new profile
  2.1. User-level: ~/.hprofile/profiles/<profile type>/pre-start
  2.2. Global: /etc/hprofile/profiles/<profile type>/pre-start

 3. Configuration files switched

 4. Post-start scripts for the new profile
  4.1. User-level:
   4.1.1. First, ~/.hprofile/profiles/<profile type>/scripts/<profile>.start
   4.1.2. Then, ~/.hprofile/profiles/<profile type>/post-start
  4.2. Global:
   4.2.1. First, /etc/hprofile/profiles/<profile type>/scripts/<profile>.start
   4.2.2. Then, /etc/hprofile/profiles/<profile type>/post-start
	 
Naturally, if any scripts are missing, they are simply not executed. If any
pre-start script returns an error (a non-zero exit code), processing of the
profile (for the individual user only, if a user-level pre-start script fails)
will be aborted.

To turn user profiles off, set "userprofiles=0" in /etc/hprofile/conf. See that
file for more configuration options.

2.3. Automatically determining the current profile

The script 'hpdet' is used to automatically determine the correct profile of
a given type at the present time. Call "hpdet <type>" (e.g. "hpdet boot") to
determine the profile. To determine the profile, hpdet will call the script
'ptest' in the profile type directory (e.g. /etc/hprofile/profiles/boot/ptest),
which should print (only) the name of the currently valid profile to the 
standard output. One way that ptest could accomplish this would be to grep
through the output of dmesg or examining /proc or /dev to assertain some
state external to the system. Another way would be to look for options
passed on the kernel command line (you can set this via the lilo append line,
or as part of the "kernel" line if you're using grub), which you can access
via /proc/cmdline. Alternatively, you could ask the user, or do anything else
that makes sense. If 'ptest' does not output anything (i.e. it was unable to
determine the profile), 'hpdet' will assume the file 'default' in the profile
directory contains (only) the name of the default or "fall-back" profile.

2.5. hprunlevel - Selecting the startup runlevel based on the hardware profiles

You'll probably want to associate different runlevels with your hardware
profiles to start certain services only in some profiles (the vmware guest tools
are a good example). To make this easier, put the names of a profiles, followed
by some whitespace followed by a digit representing the runlevel, one on each 
line (and nothing else), in /etc/hprofile/runlevels. For example:

  dualboot  4
  vmware    5

These profiles refer to the 'boot' profiles, found in 
/etc/hprofile/profiles/boot. 

Then use the 'hprunlevel' script, called with the profile as the first argument,
which examines this file and echoes the runlevel, which can then be used to
tell init to switch runlevels. Alternatively, 'hprunlevel' can use 'hpdet' as
described above to find the currently valid 'boot' profile, presuming you've set
up the 'boot' profile 'ptest' script sensibly.

I've found that the best way of selecting a runlevel at startup, is to use the
default runlevel (usually runlevel 3) as a dummy, that contains only
one service, which prints a warning that something went wrong in runlevel
selection. At the very end of the "boot" runlevel (the one that has all the
scripts that get run once only, when the system is booted, before init enters
the default runlevel), put a script (this means start its name with S99 in
most distros, and set a dependency of "after *" in Gentoo Linux) that does
something like the following:

  runlevel=$(/usr/local/sbin/hprunlevel)
  echo "Switching to runlevel ${runlevel}"
  /sbin/init ${runlevel}

This will switch to the correct "real" runlevel. If you want to avoid that, 
you can try to use hprofile to switch some of the scripts in /etc/init.d around,
using dummies for services you don't want for a given profile. In this case,
it becomes very important to make sure hprofile runs before any "normal"
bootup services, preferably right after filesystems have been mounted.

Please note that this will require some trial an error. Two key points to keep
in mind is that you can always go single-user to fix something that went wrong
(do "linux s" on a LILO or GRUB command line), and do keep backups of your 
entire runlevels directory (/etc/rc.d on many systems; /etc/runlevels on 
Gentoo). 

3. Installation

The script install in the distribution directory will copy skeleton files to
/etc/hprofile and copy the three scripts (hprofile, hpdet, hprunlevel) to
/usr/local/sbin. Modify this script or perform the installation manually if 
you want them elsewhere.

You'll then need to edit /etc/hprofile/profiles/boot/ptest to determine
the current 'boot' profile and echo it (see above) and/or modify the LILO 
append line or GRUB menu to specify profiles (see above). If you want hprofile 
to run at bootup (you probably do), you'll need to put calls to 
/usr/local/sbin/hprofile (and possibly /usr/local/sbin/hprunlevel) in your 
startup scripts (on some systems, /etc/init.d/boot.local may be a good place),
preferably right after local filesystems have been mounted. If you use 
hprunlevel, you'll need to also modify the file /etc/hprofile/runlevels, and
make sure that the runlevels correspond to those in /etc/inittab and 
/etc/init.d/rc.d or /etc/rc.d or /etc/runlevels. 

Next, you'll have to place the profile-specific versions of any files you want
used in /etc/hprofile/profiles/<type>/files, in directories mirroring their 
intended locations in the filesystem hierarchy. One likely example is 
/etc/modules.conf. Presuming you want vmware and dualboot as your profiles, 
copy /etc/modules.conf to both /etc/hprofile/etc/modules.conf.vmware and 
/etc/hprofile/etc/modules.conf.dualboot, and modify them to your liking. And
MAKE A BACKUP OF THE ORIGINAL. Don't think you won't mess it up. You will. I
promise!

In fact, throughout this process - KEEP BACKUPS! You're bound to mess 
something up the first time! Also, test hprofile (after you've made backups!) 
before rebooting, as you may render your system unbootable.

4. The example configurations

The following sections describe the example configurations and how they work.
Note that the example configurations are found in the directory 
example-profiles, because otherwise you could risk accidently overwriting your
configuration files with mine! However, versions of the example profiles without
any configuration files in the 'files' directory are installed in the profiles
directory by default, to give you some scripts and settings to base your own
configuration on.

4.1. The 'boot' profiles - VMWare vs. dual boot

The 'boot' profile, as mentioned above, is special in that it can be associated
with a runlevel. The example boot profile here is based on my configuration,
which distinguishes between the hardware emulated by VMWare and my real 
hardware. Some of the locations of these files may be specific to Gentoo Linux.

The file /etc/modules.autoload.d/kernel-2.6 contains modules which will be
loaded at startup. The file /etc/conf.d/net contains Gentoo network 
configuration. The file /etc/modules.d/alsa contains ALSA sound settings.

This profile does not make use of any scripts, but it is loaded at startup.
Look at the files in the extra/rc-scripts directory to see the Gentoo init
scripts that load the profile. Note that Gentoo is quite different from 
RedHat-based systems when it comes to init scripts, so you may need to roll
your own scripts - if you do, please email them to me (optilude@gmx.net), and
I'll include them in the future.

To gentoo users: The init scripts hprunlevel and hprofile exist in the boot
runlevel, and I have two extra runlevels in /etc/runlevels called dualboot and
vmware. These are set to runlevels 4 and 5 respectively in /etc/inittab, and
contain all services for those two runlevels; the default runlevel is empty
except for the hprunlevel-warning service. Also note that for hprofile to be
run before the 'modules' service, you need to add a hidden file ".critical" in
/etc/runlevels/boot. This file should contain the following line only:

	checkroot hostname hprofile modules checkfs localmount

This is because recent versions of the gentoo boot scripts define some boot
services as "critical", which are started first, regardless of other scripts'
dependencies. hprofile needs to run before modules (presuming you want to 
change which modules are loaded at bootup using hprofile), so we need to define
it as a "critical" service.

4.2. The 'net' profiles - Connecting to multiple networks

This profile uses scripts and configuration files to connect to multiple 
networks. It's worth browsing through the start and stop scripts in the 
'scripts' directory to see how they work. Again, some of this will be Gentoo 
specific, but it should be a useful starting point.

The thing to notice here is that ptest outputs the current profile every time,
which is based on the assumption that you'll want to keep using the same 
network profile until you manually switch it. To make this work properly across
reboots, though, the rc script (found in extra/rc-scripts/gentoo/net.profile)
actually starts the *previous* profile at boot. The reason is that at shutdown,
the profile is stopped (to ensure the network is stopped properly), using
"hprofile -s net". This in turn makes the "current" profile the "previous" one.
Get it? :-) The net result is that the last profile you set is "remembered" 
the next time you boot.

You could be even more clever, by making a net 'ptest' script which would
select the network profile by probing the network (e.g. by trying to get a
DHCP address and seeing which subnet it's on). As always, example setups are
more than welcome to optilude@gmx.net.

4.3. The 'power' profiles - Saving battery life

This profile uses only scripts in the 'scripts' directory, and does not switch 
any configuration files. It uses the "speedfreq" command to change the CPU
speed (I have an Intel Pentium-M/Centrino chip, but speedfreq should be able to
scale down other types of CPU as well), and ASUS-specific ACPI extensions to
change the brightness of the display. Unless you have a Centrino based ASUS-made
laptop, you probably have to change these if you want to use them, but it should
be fairly straightforward. I have seen reports of others using xgamma to change
the brightness, but this never worked for me. If you have a working set of
power profile scripts, please email them to me (optilude@gmx.net), and I'll
include them in the distribution in the future.

5. Limitations

There is no way to specify that a given file should not be present in a given 
profile. If a given file exists in one profile but not another, hprofile will
simply leave whatever is there when switching to the profile that doesn't have
the file.

The procedure to find out which users in /etc/passwd are actually valid users
(that is, real people who can log in, and not just daemon users) is somewhat
unelegant, and requires access to /etc/shadow (it only reads this file once to
find out which users have non-* password fields, but still), which you may or
may not appreciate. Suggestions for a better way to list all real users on the
system would be appreciated.

If you can come up with other features you want added to (or bugs removed from)
hprofile, please drop me a line (or a patch) at optilude@gmx.net.

6. Extras

Some extra scripts can be found in the 'extra' directory (these are not 
installed by default). At present, this includes:

 - Init scripts for Gentoo Linux to load the 'boot' profile and select the boot 
    profile runlevel.
 - A script called 'select-profile' which lets you graphically select a profile
    of a given type by running 'select-profile <type>'. This uses zenity, part 
    of Gnome, to display a menu.
 - An example /etc/acpi directory which defines ACPI rules and scripts to change
    the power profile automatically when the AC adapter is plugged in or pulled
    out.

7. Warning

I've tested this with the example profiles on Gentoo Linux on my laptop. I 
haven't had any problems with it, and it works great for me, but consider 
yourself a field tester if you try to use it!

8. Contact

If you need more help or have suggestions or bug reports, please don't hesitate
to contact me at optilude@gmx.net.
