Saturday, February 23, 2008

Bash Scripting: A new beginning

Recently, I found that due to excessive amount of work, I have to automate tasks as much as possible. So, here I am learning to script as much as possible in my linux box. I've just started to script in Bash and here's the first working script.

#!/bin/bash
#
# This script suppose to setup the machine to connect to Jalawave
# using rfcomm0 interface and reports any error it encounters.
# The following is the logic.
# 1. Check whether the prerequisite is met. Abort if not.
# 2. Check whether rfcomm0 exists. If it isn't, then bind it
# using rfcomm.
# 3. Check whether interface ppp0 exists. If it doesn't exist,
# execute "wvdial bluetooth" in the background and wait
# until ppp0 interface created.
# 4. Check whether the default gateway to Jalawave has been
# created by the route program. Create one if it's not
# been created yet.
# 5. Update the nameserver configuration to the right value
#

# Error codes
E_NOT_ROOT=66 # Todo: you have to fix the error code
E_WVDIAL_STOP=67

COM_DEVICE=rfcomm0
PPP_INTERFACE=ppp0
JALA_GW=10.6.6.6

#
# 1. Check whether the prerequisite is met. Abort if it isn't.
#

#
# Check whether we are superuser
#
if [ "$UID" -ne 0 ]; then
echo "Error! You are not a superuser. You have to run this script as superuser.";
exit $E_NOT_ROOT;
else
echo "Executing script to connect to Jalawave via bluetooth 3G modem.."
fi

#
# Check whether awk exists
#
if [ ! -x /usr/bin/awk ];then
echo "Error! Awk isn't installed. Aborting.."
exit 0
fi

#
# Check whether grep exists
#
if [ ! -x /usr/bin/grep ];then
echo "Error! Grep isn't installed. Aborting.."
exit 0
fi


#
# 2. Check whether rfcomm0 exists. If it isn't, then bind it
# using rfcomm.
echo "Configuring $COM_DEVICE.."

PHY_COM=$(ls /dev | grep $COM_DEVICE | awk '{print $1}')
if [ "$PHY_COM" != "$COM_DEVICE" ]; then
echo "$COM_DEVICE doesn't exist. Creating $COM_DEVICE.."

# Todo: handle other device(s) in the future
rfcomm bind $COM_DEVICE
fi

#
# 3. Check whether interface ppp0 exists. If it doesn't exist,
# execute "wvdial bluetooth" in the background and wait
# until ppp0 interface created.
#
PHY_PPP=$(ifconfig | grep $PPP_INTERFACE | awk '{print $1}')
if [ "$PHY_PPP" != "$PPP_INTERFACE" ]; then
echo "Executing wvdial in the background.."
wvdial bluetooth 2>/var/log/wvdial_log.txt &
echo "You can examine Wvdial output at /var/log/wvdial_log.txt"

# wait until the PPP device created
echo "Waiting for $PPP_INTERFACE to be created.."
while [ "$PHY_PPP" != "$PPP_INTERFACE" ]
do
PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')

# check whether the background wvdial process is still alive
WVDIAL_PS=$(ps -C wvdial | awk '{print $4}' | grep 'wvdial')
if [ "$WVDIAL_PS" != "wvdial" ]; then
echo "Wvdial terminated abruptly. Aborting.."
exit $E_WVDIAL_STOP
fi

# delay a little bit
sleep 1
done

else
echo "$PPP_INTERFACE interface exists as $PHY_PPP"
fi

#
# 4. Check whether the default gateway to Jalawave has been
# created by the route program. Create one if it's not
# been created yet.
#
echo "Checking for Jalawave gateway.."
MY_GW=$(route -n | awk '{print $2}' | grep $JALA_GW)
if [ "$MY_GW" != "JALA_GW" ]; then
echo "Jalawave gateway doesn't exist!"
echo "Creating default route to Jalawave gateway.."
route add default gw $JALA_GW $PPP_INTERFACE
echo "Default route created"
fi

#
# 5. Update the nameserver configuration to the right value
#
echo "Updating nameserver setting.."
cat /etc/ppp/resolv.conf > /etc/resolv.conf

echo "Connected."
exit 0


Of course this one still has a lot of bugs. I will refine it from time to time.
The second script is used to disconnect from the ISP.


#!/bin/bash
#
# This script suppose to disconnect from Jalawave
# The following is the logic.
# 1. Check whether the prerequisites are met.
# 2. Kill wvdial.
# 3. Wait for the ppp0 interface to be destroyed.
# 4. Release rfcomm0 binding.
#

# Error codes
E_NOT_ROOT=66 # Todo: you have to fix the error code

RFCOMM_DEVICE=rfcomm0
PPP_INTERFACE=ppp0

#
# 1. Check whether the prerequisite is met. Abort if it isn't.
#
if [ "$UID" -ne 0 ]; then
echo "Error! You are not a superuser. You have to run this script as superuser.";
exit $E_NOT_ROOT;
else
echo "Executing script to disconnect from Jalawave via bluetooth 3G modem.."
fi

#
# 2. Kill wvdial.
#

# check whether the background wvdial process is still alive
WVDIAL_PS=$(ps -C wvdial | awk '{print $4}' | grep 'wvdial')
if [ "$WVDIAL_PS" == "wvdial" ]; then
echo "Killing wvdial process.."
killall wvdial
fi

#
# 3. Wait until the PPP_INTERFACE destroyed before releasing
# rfcomm0 binding.
#

PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')

if [ "$PHY_PPP" == "$PPP_INTERFACE" ]; then
echo "Waiting for $PPP_INTERFACE to be destroyed.."
fi

while [ "$PHY_PPP" == "$PPP_INTERFACE" ]
do
PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')
sleep 1
done

#
# 4. Release rfcomm0 binding.
#
if [ -e "/dev/$RFCOMM_DEVICE" ]; then
echo "Releasing $RFCOMM_DEVICE binding.."
rfcomm release $RFCOMM_DEVICE
fi

echo "Disconnected."

exit 0

Monday, February 4, 2008

Upgrading from kernel 2.6.22.15 to 2.6.24

It's been a while I'm using Linux Slackware 12 with kernel 2.6.22.15. This was the most stable kernel version for my aging Compaq Presario W2718 laptop. It's also the one with most hardware features working as expected. Kernel 2.6.23 and its stable point releases (2.6.23.x) were not up to my expectation as they have problems in the sound drivers. I cannot get my laptop sound working reliably when using audacious, even though xine audio works just fine. I've upgraded my audacious to its latest version when using kernel 2.6.22.15 but it's still problematic and I found that quite a lot of people have the same problem with kernel 2.6.23.x releases. With the release of kernel 2.6.24 a few days ago, I have a chance to try upgrading my kernel once more. With a few hours testing as of now, it seems to be better than 2.6.22.15 that I use previously. Now, I have my Broadcom BCM4318 Wifi chip up and supposed to be working. I couldn't get it to work with the linux-wireless patch to kernel 2.6.22.15 -- Too bad I have no Wifi access point to test it against as of now :(. As for the Bluetooth, it seems to be working better than before.


To cut it short, here's how I upgraded from kernel 2.6.22.15 to 2.6.24:



  1. Download the needed patches from www.kernel.org or its ftp:

    • patch-2.6.22.15.bz2

    • patch-2.6.23.bz2

    • patch-2.6.24.bz2


  2. Decompress the patches:

    bzip2 -d -k [patch_file_name]



  3. Apply the patches to the kernel 2.6.22.15 source code by using the following commands in the root directory of the source code:

    patch -R -p1 < /path/to/patch/dir/patch-2.6.22.15
    patch -p1 < /path/to/patch/dir/patch-2.6.23
    patch -p1 < /path/to/patch/dir/patch-2.6.24

    Take a very close look that we are "reverse-patching" from 2.6.22.15 to 2.6.22 prior to "forward-patching" to kernel version 2.6.23. This is because the base kernel patch i.e., 2.6.x only applies to other 2.6.y kernel version. That's why you have to revert back to 2.6.22 before moving up to 2.6.23 and then to 2.6.24. Also note that the 2.6.x.y patches only applies to 2.6.x base kernel not to 2.6.x.w.

  4. Bake the new kernel

    make silentoldconfig
    make -j4

    Because I compiled on a faster machine, I do the following to pack the result and
    scp the result back to my laptop:

    make tarbz2-pkg
    [..scp the packed result to my laptop..]



  5. Test the new kernel.Hmmm... yummy.. >:). I've carried-out preliminary test on the kernel. Here's the result:
    • The bluetooth support is working better than ever

    • The wireless LAN support is still problematic, iwlist can display available network but dhclient or dhcpcd always fail. I'm using ndiswrapper and the Windows version of the WLAN driver instead. It works flawlessly but with the caveat that I have to disable all of the Broadcom BCM43xx related drivers in the kernel modules. I'll talk about it in the next point.



  6. Replace the native Linux 2.6.24 Broadcom BCM43xx driver with ndiswrapper and the Broadcom BCM43xx Windows XP driver. Here's how to do it:

    • Disable the BCM43xx native Linux driver by adding it into blacklist driver. To do so, edit /etc/modprobe.d/blacklist, add the following lines:

      # because we are using ndiswrapper driver for the network card, default
      # Broadcom BCM43xx and its corresponding drivers should not be loaded
      blacklist b43
      blacklist bcm43xx
      blacklist ssb


    • Compile and install ndiswrapper.

    • Install the Windows driver. I'm using the Broadcom BCM4318 driver that comes with my Compaq Presario W2718. The driver file is bcmwl5.sys and driver installation file is bcmwl5.inf.Place these files in one directory and run:

      bash-3$ ndiswrapper -i bcmwl5.inf

      Once the driver installation has been completed. Reboot the machine and then configure the interface with iwconfig. You scan the available accesspoints with
      iwlist wlan0 scanning

      and then to connect to one of the access point, set the essid with
      iwconfig wlan0 essid the_access_point_name

      and then obtain the ipaddress with
      dhcpcd wlan0
      or
      dhclient wlan0

      That's it, you should be online by now ;-).



  7. At this point, I'm stripping out every unneeded things from the kernel.
    To do that, trace sysfs for every used modules in the huge kernel and note
    them. Then look for them during kernel configuration, make sure to enable them.
    I'll talk about it later.



That's all for now. I'll keep posting my test results and other kernel works.