En ung Terry Pratchett skrev “The Carpet People” før han laget Discworld-bøkene, men man gjenkjenner mange elementer fra de senere bøkene her, og fra genrens bestefar. En stor, flat verden (nede i et teppe) med et mytologisk overbygg i en middelalderaktig tid. Handlingen er komprimert, med klassiske fantasy-ingredienser i rask rekkefølge: Den unge høvdingsønnen som tenker mer enn han slåss viser seg å være et duganes lederemne. Et vandringsfølge med et oppdrag. En vismann viser veien. Underlige, litt overjordiske skapninger som ser framtid og fortid er ikke så glade i å gi råd, men gir dem likevel. En vandringsmann som slår følge viser seg å være en stor kriger og potensiell kandidat for tronen. Onde menneskeliknende skapninger prøver å ta herredømme over det gode riket. En hemmelig gang under jorda (teppet), før de blir tatt til fange, men selvsagt rømmer igjen. Krigerstammer på vandring blir gode allierte i det store slaget på slutten. Høres det ikke veldig kjent ut? Joda, men det blir riktig bra selv om oppskriften er kjent. Pratchetts småhysteriske humor er i ferd med å springe ut, og krydrer med gapskratt innimellom. En riktig godbit. Anbefales for fantasy-elskere med glimt i øyet.
Archive for December, 2007
Terry Pratchett: The Carpet People
Monday, December 17th, 2007Build a RHEL5 kernel using a custom configuration
Friday, December 14th, 2007From time to time, RedHat’s predefined kernel configuration does not suit your needs. You may want to disable or enable drivers that are not in the stock config, or you may want to build more specialized kernels. But you want to keep the build framework and all the patches. Here’s a short howto. With small changes, it works on RHEL4 as well. In Fedora, the build framework has become a bit more mature, with more options and less editing of files. You can find their corresponding document at http://fedoraproject.org/wiki/Docs/CustomKernel.
In the following you may replace “i686″ and “i386″ for “x86_64″ if you have an AMD64 or EM64T cpu on your target system. Run the following on a build system. If you are of the more clever users (you are reading this, right?), you’ll replace /usr/src with your private rpm build space, see http://users.linpro.no/ingvar/rpm.html.
Surf to https://rhn.redhat.com/
-> Channels
-> Red Hat Enterprise Linux Server 5
-> IA-32 (i386)
-> Packages
-> Filter by Package: kernel -> Go
-> kernel-some-version
-> Download Source Package
rpm -ivh kernel-2.6-something.src.rpm
yum install ncurses-devel kernel-devel make gcc
cd /usr/src/redhat/SPECS rpmbuild -bp --target=i686 kernel-2.6.spec
cd /usr/src/redhat/SOURCES find . -name kernel\\*config cp kernel-2.6.18-i686.config kernel-2.6.18-i686.config.orig cp kernel-2.6.18-i686.config /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i686/.config
cd /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i686 make oldconfig make menuconfig
vi .config
Enter line on the top with a ‘#’ followed by a space and the output of the command ‘uname -i’ on the target system. For, for example, a 32bit intel box, the top line of .config should read:
# i386
Then copy the file back to the SOURCES directory
cp .config /usr/src/redhat/SOURCES/kernel-2.6.18-i686.config
cd /usr/src/redhat/SPECS vi kernel-2.6.spec
Change the following lines, unless you need extra packages like xen, doc, pae, or kernel-headers. Search for lines that look the ones below. Do not enter new tags. Instead of “local”, you may write anyhting you want in the release tag.
%define buildxen 0 %define builddoc 0 %define buildkdump 0 %define buildheaders 0 %define release 8.1.15.local%{?dist} %ifarch i686 %define buildpae 0
time rpmbuild -bb --target=i686 kernel-2.6.spec
Associative arrays in bash
Tuesday, December 4th, 2007If you do a google search for “associative arrays in bash”, you get a lot of hits that tell you that this is a feature not found in bash (though later versions may include this). Now, I find associative arrays (or hash tables if you like) a very nice feature to have available. And it is not that hard to emulate it in bash. One can use two arrays, one for the keys, and the other for the data elements, and a common counter for the indexes. A more ugly, but faster design could be direct string to variable name translation, with eval doing the dirty work.
Note that this kind of translation may be called seriously bad design, and in an interactive script, it may lead to serious security flaws. But if you know what the strings will look like, this short hand may do the work for you.
Consider the following code snippet:
#!/bin/bash # # Associative arrays in bash, take 1 # Using simple translation with eval # Some test values with doublettes values="a a a a b b c d"; # The incrementer for the keys to the array key=-1 # Start with off-by-one, as incrementing is the first step in the loop for val in $values; do # Need to check for uninitialized value, to get rid of doublettes # (and yes, here test(1) needs the extra character in the test) if eval [ 'x$'$val = "x" ]; then ((key++)) fi # Now, fill the hash with values eval $val=$key; case $val in "a") arr[$key]="alice"; ;; "b") arr[$key]="bob"; ;; "c") arr[$key]="charlie"; ;; "d") arr[$key]="diana"; ;; esac done # Look up the value for a single key 'a' key="a" echo -n "Data entry for key $key is: " eval key="$"$key echo ${arr[$key]}; # Print the contents of the array echo ""; echo "Whole array:" for (( key=0; key < ${#arr[*]}; key++ )) do echo ${arr[$key]} done ## EOF
For more serious scripts, consider as mentioned, putting the keys in its own array, and search it while looking up values. This would take more time, though.
#!/bin/bash
#
# Associative arrays in bash, take 2
# Using two arrays# Some test values with doublettes
values="a a a a b b c d";# Search for existing keys
function getkey {
key=$1
for (( i=0; i < ${#keys[*]}; i++ )) {
if [ "${keys[$i]}" = "$key" ]; then
return $i
fi
}
# Not found, create a new key
keys[$i]=$key
return $i
}# Now, fill the hash with values
for val in $values; do# First, get a new key
getkey $val; key=$?case $val in
"a")
arr[$key]="alice";
;;
"b")
arr[$key]="bob";
;;
"c")
arr[$key]="charlie";
;;
"d")
arr[$key]="diana";
;;
esac
done# Look up the value for a single key 'd'
echo -n "Data entry for key 'd' is "
getkey 'd'; key=$?
echo ${arr[$key]};# Print the complete contents of the hash
echo ""; echo "Whole hash:"
for (( i=0; i < ${#arr[*]}; i++ ))
do
echo -n "%arr{"
echo -n ${keys[$i]}
echo -n "}="
echo ${arr[$i]}
done# EOF