Thursday, August 4, 2011

Get pressed key in bash, works in VMware esx

 
Here is my last bash script, it gets the pressed key in bash, enjoy.
#!/bin/bash
 
 
function identify_key {
 
local key="$@"
local printable=""
 
case "$key" in
   "1b") echo "ESC ($key)";;
   "09") echo "TAB ($key)";;
   "1b 1b") echo "DOUBLE ESC ($key)";;
   "7f") echo "BKS ($key)";;
   "1b 5b 41") echo "UP ($key)";;
 
   "1b 5b 42") echo "DOWN ($key)";;
   "1b 5b 43") echo "RIGHT ($key)";;
   "1b 5b 44") echo "LEFT ($key)";;
 
   "1b 5b 47") echo "NUM5 ($key)";;
   "1b 5b 50") echo "PAUSE ($key)";;
 
   "1b 5b 31 7e") echo "HOME ($key)";;
   "1b 5b 32 7e") echo "INS ($key)";;
   "1b 5b 33 7e") echo "DEL ($key)";;
   "1b 5b 34 7e") echo "END ($key)";;
   "1b 5b 35 7e") echo "PGUP ($key)";;
   "1b 5b 36 7e") echo "PGDN ($key)";;
 
   "1b 5b 5b 41") echo "F1 ($key)";;
   "1b 5b 5b 42") echo "F2 ($key)";;
   "1b 5b 5b 43") echo "F3 ($key)";;
   "1b 5b 5b 44") echo "F4 ($key)";;
   "1b 5b 5b 45") echo "F5 ($key)";;
   "1b 5b 31 37 7e") echo "F6 ($key)";;
   "1b 5b 31 38 7e") echo "F7 ($key)";;
   "1b 5b 31 39 7e") echo "F8 ($key)";;
   "1b 5b 32 30 7e") echo "F9 ($key)";;
   "1b 5b 32 31 7e") echo "F10 ($key)";;
   "1b 5b 32 33 7e") echo "F11 ($key)";;
   "1b 5b 32 34 7e") echo "F12 ($key)";;
 
   "1b 1b 5b 5b 41") echo "ALT+F1 ($key)";;
   "1b 1b 5b 5b 42") echo "ALT+F2 ($key)";;
   "1b 1b 5b 5b 43") echo "ALT+F3 ($key)";;
   "1b 1b 5b 5b 44") echo "ALT+F4 ($key)";;
   "1b 1b 5b 5b 45") echo "ALT+F5 ($key)";;
   "1b 1b 5b 31 37 7e") echo "ALT+F6 ($key)";;
   "1b 1b 5b 31 38 7e") echo "ALT+F7 ($key)";;
   "1b 1b 5b 31 39 7e") echo "ALT+F8 ($key)";;
   "1b 1b 5b 32 30 7e") echo "ALT+F9 ($key)";;
   "1b 1b 5b 32 31 7e") echo "ALT+F10 ($key)";;
   "1b 1b 5b 32 33 7e") echo "ALT+F11 ($key)";;
   "1b 1b 5b 32 34 7e") echo "ALT+F12 ($key)";;
   "") echo "SPACE or INTRO";;
   *) # check if it's ALT+xx
      if [ ${#key} -gt 2 ] && [ "${key:0:2}" == "1b" ]; then
         # if string length greather than 2 and starts by Escape (1b)
         printable="\x"${key:3}   # erases the starting '1b ' 
         printf "ALT+%b (%s)\n" "$printable" "$key"
      else
         printable="\x"$key
         printf "%b (%s)\n" "$printable" "$key"
      fi
      ;;
esac
}
 
 
 
function key_5b {
# process '1b 5b ...' keys and return values
 
  local key=$1
  local keyA=""
  local keyB=""
  local keyC=""
 
  keyA=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
  case "$keyA" in
     "31" | "32" | "33" | "34" | "35" | "36") # Must read the following key
             read -rsn1 -t 1 key   # Wait 1 second max for next key
             if [ "$key" == "" ]; then
                # 'ESC + [ + A|B|C|....F' keys pressed (very fast)
                 echo "$keyA"
             else
                 keyB=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
                 if [ "$keyB" == "7e" ]; then
                    # got '~', uses to be the last key so return "XX 7e" where XX is [31|32|33|34|35|36]
                    echo "$keyA $keyB"
                 else
                    read -rsn1 -t 1 key   # Wait 1 second max for next key
                    if [ "$key" == "" ]; then
                       # 'A|B|C|....F + XX' keys pressed (very fast)
                       echo "$keyA $keyB"
                    else
                       keyC=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
                       # max depth level, so return
                       echo "$keyA $keyB $keyC"
                    fi
                 fi
              fi
              ;;
        "5b") # read another key and return (uses to be F1 ... F5 keys) '1b 5b 5b [41|42|43|44|45]'
              read -rsn1 -t 1 key   # Wait 1 second max for next key
              keyB=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
              echo "$keyA $keyB"
              ;;
           *) # Uses to be UP or other arrow keys '1b 5b [41|42|43|44]' so return
              echo "$keyA"
              ;;
  esac
}
 
 
 
function getkey {
  local key=""
  local key1=""
  local key2=""
  local key3=""
  local key4=""
 
oldifs="$IFS"
IFS=" "
 
 
  read -rsn1 key
  key1=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
  if [ "$key1" == "1b" ]; then
     read -rsn1 -t 1 key   # Wait 1 second max for next key
     if [ ! "$key" == "" ]; then
        key2=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
        case "$key2" in
           "1b") # it could be a double ESC or an ALT+Fx key
                 read -rsn1 -t 1 key   # Wait 1 second max for next key
                 if [ "$key" == "" ]; then
                    # "1b 1b" 'ESC' key pressed 2 times (very fast)
                    echo "$key1 $key2"
                 else
                    # "1b 1b ..." Uses to be ALT+F? key pressed
                    key3=`echo -n "$key" |  hexdump -ve '1/1 "%.2x\n"'`; key=""
                    if [ "$key3" == "5b" ]; then
                       read -rsn1 -t 1 key   # Wait 1 second max for next key
                       if [ "$key" == "" ]; then
                          # "1b 1b 5b" 'ESC + ESC + [' keys pressed (very fast)
                          echo "$key1 $key2 $key3"
                       else
                          echo "$key1 $key2 $key3 $(key_5b $key)"
                       fi
 
                    else
                       # Unknown key '1b 1b XX' so return
                       echo "$key1 $key2 $key3"
                    fi
                 fi
                 ;;
           "5b") # Several posibilities "1b 5b ..."
                 read -rsn1 -t 1 key   # Wait 1 second max for next key
                 if [ "$key" == "" ]; then
                    # "1b 5b" 'ESC + [' keys pressed (very fast)
                    echo "$key1 $key2"
                 else
                    echo "$key1 $key2 $(key_5b $key)"
                 fi
 
                 ;;
              *) # ESC + Other key pressed (very fast) or ALT+xx
                 echo "$key1 $key2"
                 ;;
        esac
     else
        # ESC key pressed
        echo "$key1"
     fi
  else
     echo "$key1"
  fi
 
IFS="$oldifs"
  return 0
}
 
 
while true
do
  echo "----------------------------"
  tecla=$(getkey)
  identify_key $tecla
done

Friday, July 15, 2011

Excel macro for uppercase conversion


Here is an excel macro for convert to uppercase the text contained in the current cell or a selected range.

Sub Uppercase()
RowsCount = Selection.Rows.Count
ColumnsCount = Selection.Columns.Count
if RowsCount = 0 or ColumnsCount=0 then
   MsgBox "ERROR: Please select a range or cell"
else

 Set Area = Selection
 For Each Cell In Area
  
' Change to uppercase.    Cell.Value = UCase(Cell.value)
 Next Cell

end if End Sub

Monday, June 27, 2011

Virtualizing a Suse Enterprise Server 9 on VMware vSphere

Recently I’ve virtualized an old  Suse Enterprise Server 9 with VMware. Here you can find some tips if you need to do something like that.

The best procedure would be adding the kernel modules for LSI Parallel controller on the physical machine and run /sbin/mkinitrd before P2V process, but if you are not allowed to modify the physical machine this is the only way I know to virtualize it.

I’ve done the P2V process using VMware’s Coldclone CD v4.1.1, first I’ve injected the physical machine’s SCSI drivers using peTool.exe

peTool.exe -i coldclone.iso -d STORAGE

Where STORAGE is a folder containing the TXTSETUP.OEM file and the drivers for my SCSI controller (LSI MegaRaid SCSI 320-2X).

Once the virtual machine is created I’ve got a boot error, the virtual machine can’t find /dev/sda1, is still trying to boot using the old MegaRaid SCSI controller:

image

In the virtualized machine I’ve chosen a LSI Logic Parallel SCSI controller:

image

Now I’ve to create a customized initrd that loads at init level my new SCSI drivers, so I’ll boot the virtualized machine using SysRescCD

image

Now you need to mount the boot disk, so I’ll use the following command:

mount /dev/sda1 /mnt/backup

Now you must edit the file /mnt/backup/etc/sysconfig/kernel and change the INITRD_MODULES variable. This is the actual value, note the reference to the physical megaraid SCSI controller:

image

You must edit this file using vi, nano or other editor and change INITRD_MODULES like that:

image

Note that mptscsih is the driver that Suse uses for LSI Logic Parallel SCSI controller.

Now we must modify the initrd RAM boot disk image file, you can find here in page 10 Novell’s documentation for this task.

We are going to decompress the file /boot/initrd and store it in the file /tmp/ramdisk:

gunzip </mnt/backup/boot/initrd > /tmp/ramdisk

Now you must mount the file in /mnt/ramdisk:

mkdir /mnt/ramdisk
mount -o loop /tmp/ramdisk /mnt/ramdisk

Now you must delete the megaraid drivers not needed anymore:

rm -rf /mnt/ramdisk/lib/modules/2.6.5-7.201-smp/kernel/drivers/scsi/megaraid

Note that 2.6.5-7.201-smp folder depends on the system’s kernel version, it can be different in your case.

Now we are going to add the new SCSI drivers:

mkdir /mnt/ramdisk/lib/modules/2.6.5-7.201-smp/kernel/drivers/message
mkdir /mnt/ramdisk/lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion
cp /mnt/backup/lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion/mptbase.ko /mnt/ramdisk/lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion
cp /mnt/backup/lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion/mptscsih.ko /mnt/ramdisk/lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion

You must also modify the file /mnt/backup/boot/linuxrc and locate the lines with the following text:

echo "Loading kernel/drivers/scsi/megaraid/megaraid_mm.ko"
insmod /lib/modules/2.6.5-7.201-smp/kernel/drivers/scsi/megaraid/megaraid_mm.ko

echo "Loading kernel/drivers/scsi/megaraid/megaraid_mbox.ko"
insmod /lib/modules/2.6.5-7.201-smp/kernel/drivers/scsi/megaraid/megaraid_mbox.ko

And replace them with:

echo "Loading kernel/drivers/message/fusion/mptbase.ko"
insmod /lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion/mptbase.ko

echo "Loading kernel/drivers/message/fusion/mptscsih.ko"
insmod /lib/modules/2.6.5-7.201-smp/kernel/drivers/message/fusion/mptscsih.ko

Now we must backup up the original initrd file, note that initrd is a link to initrd-2.6.5-7.201-smp file, so you must backup that file first:

mv /mnt/backup/boot/initrd-2.6.5-7.201-smp /mnt/backup/boot/initrd-2.6.5-7.201-smp.orig

And gzip the new one with the LSI Logic Parallel SCSI drivers:

umount /mnt/ramdisk
gzip </tmp/ramdisk > /mnt/backup/boot/initrd-2.6.5-7.201-smp

Now umount /dev/sda1 device and reboot the virtual machine, remember to disconnect the SysRescCD CD and boot from hard disk.

umount /dev/sda1
init 0

On next boot you will have to reconfigure the graphical settings, but you should choose Text mode only because the VMware graphic card is not supported until you install the vmware tools package.

image

You must also delete the /etc/sysconfig/network/ifcfg-eth-id-xx:xx:xx:xx:xx:xx file for the old physical ethernet card. And then set the network settings using yast from command line.