Monday, November 5, 2012

Automount USB devices with no desktop environment

I'm running a slim Debian install with Xmonad as my window manager, and need a lightweight automounter for USB devices.  I don't need to worry about icons popping up since I have no desktop environment.  usbmount meets those specs.  As of this writing it is an orphaned package, but is a relatively simple udev script, so I don't anticipate too many surprises.  Setup for generic USB devices is simple, just
ROOTPROMPT$> apt-get install usbmount
   At this point your system should automount ext[3,4] filesystems according to the particular device ownership.  VFAT filesystems don't have such properties so we have to tell usbmount how to handle them.  The instructions in the usbmount.conf file are thorough, so in brief we have to write the desired mount options for the filesystem type into the config file.  I want to mount vfat usb devices to the 'floppy' group with read and write privileges.  To do this open /etc/usbmount/usbmount.conf file as root and set the FS_MOUNTOPTIONS as follows:
FS_MOUNTOPTIONS="-fstype=vfat,gid=floppy,dmask=0007,fmask=0117"
Now the system should automount ext3, ext4 and vfat filesystems upon disk insertion.
   Other devices can be tricky.  I have an HP touchpad that does not have a partition table.  When plugged into the computer, the touchpad asks whether I want it to behave as as USB mass storage device.  After I select yes, is shows up as /dev/sd[b-h] depending on how many other devices I have plugged in.  The example below shows the device as /dev/sdb.
$> dmesg
/////skip a bunch//////
[ 3005.685270] sdb:
[ 3030.915649] usb 1-5: USB disconnect, address 8
[ 3035.340043] usb 1-5: new high speed USB device using ehci_hcd and address 9
[ 3035.474728] usb 1-5: New USB device found, idVendor=0830, idProduct=8074
[ 3035.474735] usb 1-5: New USB device strings: Mfr=2, Product=3, SerialNumber=4
[ 3035.474739] usb 1-5: Product: webOS-device
[ 3035.474743] usb 1-5: Manufacturer: HP
[ 3035.474746] usb 1-5: SerialNumber: 0123456789ABCDEF
[ 3035.474950] usb 1-5: configuration #1 chosen from 1 choice
[ 3035.482227] scsi7 : SCSI emulation for USB Mass Storage devices
[ 3035.486189] usb-storage: device found at 9
[ 3035.486194] usb-storage: waiting for device to settle before scanning
[ 3040.484486] usb-storage: device scan complete
[ 3040.489848] scsi 7:0:0:0: Direct-Access HP webOS-device 0327 PQ: 0 ANSI: 2
[ 3040.493881] sd 7:0:0:0: Attached scsi generic sg2 type 0
[ 3040.509961] sd 7:0:0:0: [sdb] Attached SCSI removable disk
[ 3152.892176] sd 7:0:0:0: [sdb] 57720832 512-byte logical blocks: (29.5 GB/27.5 GiB)
[ 3152.995534] sd 7:0:0:0: [sdb] Assuming drive cache: write through
fdisk shows no partition, just the entire block device.
ROOTPROMPT$> fdisk -l
/*skip other disc info*/
Disk /dev/sdb: 29.6 GB, 29553065984 bytes
64 heads, 32 sectors/track, 28184 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
I can mount it as root and see it is a vfat device.
ROOTPROMPT$> mount /dev/sdb /media/touchpad
ROOTPROMPT$> exit
$> df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdb vfat 28853344 1854128 26999216 7% /media/touchpad
I tried adding a UUID based mount rule for the touchpad into the fstab,  but that didn't work until after I ran blkid on the device, which requires root access.
   I read up on writing udev rules at various websites.  The three I found useful are:
http://www.reactivated.net/writing_udev_rules.html - Good explanations, but udevinfo has been replaced by udevadm, so you have to adjust the examples.
http://workaround.org/mount-usb-memory-sticks - Good, but dated and uses udevinfo
http://wiki.debian.org/udev - debian specific udev page with udevadm examples.
   As root, create the rules file in the /etc/udev/rules.d directory.  I created /etc/udev/rules.d/10-touchpad-rules file.  Lower numbers at the beginning of the file increase precedence.  The following command gives a bunch of information, I've trimmed most of it out since I only needed a few pieces to write my rule.
ROOTPROMPT$> udevadm info -q all -n /dev/sdb
/* skip irrelevant details*/
E: UDEV_LOG=3
E: DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-6/1-6:1.0/host2/target2:0:0/2:0:0:0/block/sdb
E: MAJOR=8
E: MINOR=16
E: DEVNAME=/dev/sdb
E: DEVTYPE=disk
E: SUBSYSTEM=block
E: ID_VENDOR=HP
E: ID_VENDOR_ENC=HP\x20\x20\x20\x20\x20\x20
E: ID_VENDOR_ID=0830
E: ID_MODEL=webOS-device
E: ID_MODEL_ENC=webOS-device\x20\x20\x20\x20
   My rule is one line long and is the only entry in the /etc/udev/rules.d/10-touchpad-rules file:
KERNEL=="sd?", SUBSYSTEM=="block", ATTRS{model}=="webOS-device", SYMLINK+="touchpad"
The KERNEL identifies a block device (with no partition number), the SUBSYSTEM checks for a value of 'block', and the ATTRS{model} checks the ID_MODEL value given from the udevadm command.  If they match the device is symlinked to /dev/touchpad.  As is, my system cannot discriminate between HP touchpads, and if two were plugged in I think they would both symlink to /dev/touchpad.  I don't envision plugging multiple touchpads into my computer though.  The Udev rule creates the device identifier.  Add the following line to /etc/fstab to enable mounting by the user.  Don't forget the newline if at the end of the file.  Archwiki has a good write up on the fstab file to understand the options below.
/dev/touchpad /media/touchpad auto rw,user,noauto  0 0
Plug in the touchpad, and select the 'usbmount' option on that device, then mount it on the computer with
$> mount /media/touchpad
Before unplugging the disk run the following:
$> umount /media/touchpad
$> eject /dev/touchpad

Monday, October 8, 2012

MplabX with Xmonad

Download the mplabx install files from microchip.  From the same page, grab the install files for the compiler for the family of controllers you will work with.  I downloaded the mplabx-ide-v1.41-linux-installer.run for the IDE and the xc32-v1.11-linux-installer.run.tar for the PIC32 compiler.  Login as root, change the permissions, and install the IDE as follows.  These commands assume the current working directory contains the install files.
ROOTPROMPT$> chmod 770 mplabx-ide-v1.41-linux-installer.run
ROOTPROMPT$> ./mplabx-ide-v1.41-linux-installer.run
   I selected all the defaults through the install wizard.  After the IDE is installed, untar and  install the compiler(s).
ROOTPROMPT$> tar -xf xc32-v1.11-linux-installer.run.tar
ROOTPROMPT$> chmod 770 xc32-v1.11-linux-installer.run
ROOTPROMPT$> ./xc32-v1.11-linux-installer.run
   When prompted by the wizard, I selected to add the compiler location to the end of the PATH variable, and to use this setting for all users on this machine.  Otherwise I used the defaults.  For reference, everything for the compiler and IDE is installed to the /opt/microchip/ directory including the required java files, so no need to worry about installing the appropriate jdk with this version.  Exit root, and start the IDE from the terminal as follows.
$> mplab_ide
   You will probably get a floating splashscreen as if the program is starting, but then just a tiled  but empty grey window.  This is a java error with Xmonad as explained in section 4.12 of the FAQ linked.  Of the suggestions, Changing the AWT_TOOLKIT - as described in the link - worked for me.  To test it, run:
$> export AWT_TOOLKIT=MToolkit
$> mplab_ide
  And the IDE should launch correctly.  If this works, add the 'export AWT_TOOLKIT=MToolkit' line to your .bashrc file to have the export done automatically when the shell is started.  Otherwise you have to manually enter the export command to every new shell instance.


update 06DEC2012:
If building a project does nothing, and you see no compiler messages in the output window, make sure MAKE is installed on your machine.  The forums details a little of the  Linux MPLABX build does nothing problem, which is easily resolved.

Friday, October 5, 2012

Xscreensaver with Xmonad

Install xscreensaver from the repository, then add the highlighted line to your .xinitrc file.  Make sure it is before the final call to xmonad in the .xinitrc
if [ -f $HOME/.xresources ]; then
xrdb -merge $HOME/.xresources
fi
if [ -f $HOME/.xmodmap ]; then
/usr/bin/xmodmap $HOME/.xmodmap
fi
xscreensaver -no-splash &
xmonad

This will launch the xscreensaver daemon when X is started.  To configure the user options run
$> xscreensaver-demo

To lock the screen from the command line run
$> xscreensaver-command -lock

Tuesday, September 4, 2012

xmonad screenshot hotkeys

Install scrot.  Add the following to the key bindings portion of your /home/USER/.xmonad/xmonad.hs file.
   --take a screenshot of entire display
   , ((modm , xK_Print ), spawn "scrot screen_%Y-%m-%d-%H-%M-%S.png -d 1")

   --take a screenshot of focused window
   , ((modm .|. controlMask, xK_Print ), spawn "scrot window_%Y-%m-%d-%H-%M-%S.png -d 1-u")
then refresh xmonad with mod+q.  XK_Print is the Print Screen keysym name.  Now mod+PrtScr will take a screen shot of the entire display, and ctrl+mod+PrtScr will take a screen shot of the focused window.  The captured image is placed in the /home/USER/ directory.  The file name is prefixed either window or screen, and date+time stamped.  You can use the -e option of scrot to move the resulting file to a different directory.  For example:  scrot window_%Y-%m-%d-%H-%M-%S.png -d 1 -u -e 'mv $f /home/USER/image/'.  the $f is the scrot variable for the captured image path.
   Here is my current xmonad.hs file, which is this xmonad.hs example with some minor modifications.
-- xmonad example config file for xmonad-0.9
--
-- A template showing all available configuration hooks,
-- and how to override the defaults in your own xmonad.hs conf file.
--
-- Normally, you'd only override those defaults you care about.
--
-- NOTE: Those updating from earlier xmonad versions, who use
-- EwmhDesktops, safeSpawn, WindowGo, or the simple-status-bar
-- setup functions (dzen, xmobar) probably need to change
-- xmonad.hs, please see the notes below, or the following
-- link for more details:
--
-- http://www.haskell.org/haskellwiki/Xmonad/Notable_changes_since_0.8
--
 
import XMonad
import Data.Monoid
import System.Exit
 
import qualified XMonad.StackSet as W
import qualified Data.Map        as M
 
-- The preferred terminal program, which is used in a binding below and by
-- certain contrib modules.
--
myTerminal      = "xterm"
 
-- Whether focus follows the mouse pointer.
myFocusFollowsMouse :: Bool
myFocusFollowsMouse = True
 
-- Width of the window border in pixels.
--
myBorderWidth   = 1
 
-- modMask lets you specify which modkey you want to use. The default
-- is mod1Mask ("left alt").  You may also consider using mod3Mask
-- ("right alt"), which does not conflict with emacs keybindings. The
-- "windows key" is usually mod4Mask.
--
myModMask       = mod4Mask
 
-- NOTE: from 0.9.1 on numlock mask is set automatically. The numlockMask
-- setting should be removed from configs.
--
-- You can safely remove this even on earlier xmonad versions unless you
-- need to set it to something other than the default mod2Mask, (e.g. OSX).
--
-- The mask for the numlock key. Numlock status is "masked" from the
-- current modifier status, so the keybindings will work with numlock on or
-- off. You may need to change this on some systems.
--
-- You can find the numlock modifier by running "xmodmap" and looking for a
-- modifier with Num_Lock bound to it:
--
-- > $ xmodmap | grep Num
-- > mod2        Num_Lock (0x4d)
--
-- Set numlockMask = 0 if you don't have a numlock key, or want to treat
-- numlock status separately.
--
-- myNumlockMask   = mod2Mask -- deprecated in xmonad-0.9.1
------------------------------------------------------------
 
 
-- The default number of workspaces (virtual screens) and their names.
-- By default we use numeric strings, but any string may be used as a
-- workspace name. The number of workspaces is determined by the length
-- of this list.
--
-- A tagging example:
--
-- > workspaces = ["web", "irc", "code" ] ++ map show [4..9]
--
myWorkspaces    = ["1","2","3","4","5","6","7","8","9"]
 
-- Border colors for unfocused and focused windows, respectively.
--
myNormalBorderColor  = "#dddddd"
myFocusedBorderColor = "#ff0000"
 
------------------------------------------------------------------------
-- Key bindings. Add, modify or remove key bindings here.
--
myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
 
    -- launch a terminal
    [ ((modm .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf)
 
    -- launch dmenu
    , ((modm,               xK_p     ), spawn "exe=`dmenu_path | dmenu` && eval \"exec $exe\"")
 
    -- launch gmrun
    , ((modm .|. shiftMask, xK_p     ), spawn "gmrun")

    --take a screenshot of entire display
    , ((modm ,              xK_Print ), spawn "scrot screen_%Y-%m-%d-%H-%M-%S.png -d 1")

    --take a screenshot of focused window
    , ((modm .|. controlMask, xK_Print ), spawn "scrot window_%Y-%m-%d-%H-%M-%S.png -d 1 -u")

    -- close focused window
    , ((modm .|. shiftMask, xK_c     ), kill)
 
     -- Rotate through the available layout algorithms
    , ((modm,               xK_space ), sendMessage NextLayout)
 
    --  Reset the layouts on the current workspace to default
    , ((modm .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf)
 
    -- Resize viewed windows to the correct size
    , ((modm,               xK_n     ), refresh)
 
    -- Move focus to the next window
    , ((modm,               xK_Tab   ), windows W.focusDown)
 
    -- Move focus to the next window
    , ((modm,               xK_j     ), windows W.focusDown)
 
    -- Move focus to the previous window
    , ((modm,               xK_k     ), windows W.focusUp  )
 
    -- Move focus to the master window
    , ((modm,               xK_m     ), windows W.focusMaster  )
 
    -- Swap the focused window and the master window
    , ((modm,               xK_Return), windows W.swapMaster)
 
    -- Swap the focused window with the next window
    , ((modm .|. shiftMask, xK_j     ), windows W.swapDown  )
 
    -- Swap the focused window with the previous window
    , ((modm .|. shiftMask, xK_k     ), windows W.swapUp    )
 
    -- Shrink the master area
    , ((modm,               xK_h     ), sendMessage Shrink)
 
    -- Expand the master area
    , ((modm,               xK_l     ), sendMessage Expand)
 
    -- Push window back into tiling
    , ((modm,               xK_t     ), withFocused $ windows . W.sink)
 
    -- Increment the number of windows in the master area
    , ((modm              , xK_comma ), sendMessage (IncMasterN 1))
 
    -- Deincrement the number of windows in the master area
    , ((modm              , xK_period), sendMessage (IncMasterN (-1)))
 
    -- Toggle the status bar gap
    -- Use this binding with avoidStruts from Hooks.ManageDocks.
    -- See also the statusBar function from Hooks.DynamicLog.
    --
    -- , ((modm              , xK_b     ), sendMessage ToggleStruts)
 
    -- Quit xmonad
    , ((modm .|. shiftMask, xK_q     ), io (exitWith ExitSuccess))
 
    -- Restart xmonad
    , ((modm              , xK_q     ), spawn "xmonad --recompile; xmonad --restart")
    ]
    ++
 
    --
    -- mod-[1..9], Switch to workspace N
    --
    -- mod-[1..9], Switch to workspace N
    -- mod-shift-[1..9], Move client to workspace N
    --
    [((m .|. modm, k), windows $ f i)
        | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
        , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
    ++
 
    --
    -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
    -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
    --
    [((m .|. modm, key), screenWorkspace sc >>= flip whenJust (windows . f))
        | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
        , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
 
 
------------------------------------------------------------------------
-- Mouse bindings: default actions bound to mouse events
--
myMouseBindings (XConfig {XMonad.modMask = modm}) = M.fromList $
 
    -- mod-button1, Set the window to floating mode and move by dragging
    [ ((modm, button1), (\w -> focus w >> mouseMoveWindow w
                                       >> windows W.shiftMaster))
 
    -- mod-button2, Raise the window to the top of the stack
    , ((modm, button2), (\w -> focus w >> windows W.shiftMaster))
 
    -- mod-button3, Set the window to floating mode and resize by dragging
    , ((modm, button3), (\w -> focus w >> mouseResizeWindow w
                                       >> windows W.shiftMaster))
 
    -- you may also bind events to the mouse scroll wheel (button4 and button5)
    ]
 
------------------------------------------------------------------------
-- Layouts:
 
-- You can specify and transform your layouts by modifying these values.
-- If you change layout bindings be sure to use 'mod-shift-space' after
-- restarting (with 'mod-q') to reset your layout state to the new
-- defaults, as xmonad preserves your old layout settings by default.
--
-- * NOTE: XMonad.Hooks.EwmhDesktops users must remove the obsolete
-- ewmhDesktopsLayout modifier from layoutHook. It no longer exists.
-- Instead use the 'ewmh' function from that module to modify your
-- defaultConfig as a whole. (See also logHook, handleEventHook, and
-- startupHook ewmh notes.)
--
-- The available layouts.  Note that each layout is separated by |||,
-- which denotes layout choice.
--
myLayout = tiled ||| Mirror tiled ||| Full
  where
    -- default tiling algorithm partitions the screen into two panes
    tiled   = Tall nmaster delta ratio
 
    -- The default number of windows in the master pane
    nmaster = 1
 
    -- Default proportion of screen occupied by master pane
    ratio   = 1/2
 
    -- Percent of screen to increment by when resizing panes
    delta   = 3/100
 
------------------------------------------------------------------------
-- Window rules:
 
-- Execute arbitrary actions and WindowSet manipulations when managing
-- a new window. You can use this to, for example, always float a
-- particular program, or have a client always appear on a particular
-- workspace.
--
-- To find the property name associated with a program, use
-- > xprop | grep WM_CLASS
-- and click on the client you're interested in.
--
-- To match on the WM_NAME, you can use 'title' in the same way that
-- 'className' and 'resource' are used below.
--
myManageHook = composeAll
    [ className =? "MPlayer"        --> doFloat
    , className =? "Gimp"           --> doFloat
    , resource  =? "desktop_window" --> doIgnore
    , resource  =? "kdesktop"       --> doIgnore ]
 
------------------------------------------------------------------------
-- Event handling
 
-- Defines a custom handler function for X Events. The function should
-- return (All True) if the default handler is to be run afterwards. To
-- combine event hooks use mappend or mconcat from Data.Monoid.
--
-- * NOTE: EwmhDesktops users should use the 'ewmh' function from
-- XMonad.Hooks.EwmhDesktops to modify their defaultConfig as a whole.
-- It will add EWMH event handling to your custom event hooks by
-- combining them with ewmhDesktopsEventHook.
--
myEventHook = mempty
 
------------------------------------------------------------------------
-- Status bars and logging
 
-- Perform an arbitrary action on each internal state change or X event.
-- See the 'XMonad.Hooks.DynamicLog' extension for examples.
--
--
-- * NOTE: EwmhDesktops users should use the 'ewmh' function from
-- XMonad.Hooks.EwmhDesktops to modify their defaultConfig as a whole.
-- It will add EWMH logHook actions to your custom log hook by
-- combining it with ewmhDesktopsLogHook.
--
myLogHook = return ()
 
------------------------------------------------------------------------
-- Startup hook
 
-- Perform an arbitrary action each time xmonad starts or is restarted
-- with mod-q.  Used by, e.g., XMonad.Layout.PerWorkspace to initialize
-- per-workspace layout choices.
--
-- By default, do nothing.
--
-- * NOTE: EwmhDesktops users should use the 'ewmh' function from
-- XMonad.Hooks.EwmhDesktops to modify their defaultConfig as a whole.
-- It will add initialization of EWMH support to your custom startup
-- hook by combining it with ewmhDesktopsStartup.
--
myStartupHook = return ()
 
------------------------------------------------------------------------
-- Now run xmonad with all the defaults we set up.
 
-- Run xmonad with the settings you specify. No need to modify this.
--
main = xmonad defaults
 
-- A structure containing your configuration settings, overriding
-- fields in the default config. Any you don't override, will
-- use the defaults defined in xmonad/XMonad/Config.hs
--
-- No need to modify this.
--
defaults = defaultConfig {
      -- simple stuff
        terminal           = myTerminal,
        focusFollowsMouse  = myFocusFollowsMouse,
        borderWidth        = myBorderWidth,
        modMask            = myModMask,
        -- numlockMask deprecated in 0.9.1
        -- numlockMask        = myNumlockMask,
        workspaces         = myWorkspaces,
        normalBorderColor  = myNormalBorderColor,
        focusedBorderColor = myFocusedBorderColor,
 
      -- key bindings
        keys               = myKeys,
        mouseBindings      = myMouseBindings,
 
      -- hooks, layouts
        layoutHook         = myLayout,
        manageHook         = myManageHook,
        handleEventHook    = myEventHook,
        logHook            = myLogHook,
        startupHook        = myStartupHook
    }

Sunday, September 2, 2012

PTP camera with Xmonad

My camera supports the Picture Transfer Protocol (PTP) rather than the USB Mass Storage device Class (UMSC) protocol.  My bare bones debian install could not mount it.  This was easily resolved by installing gphotofs and fuse.
ROOTPROMPT$> apt-get install gphotofs 
Which will also install the fuse dependencies.  Then add the appropriate users to the fuse group.
ROOTPROMPT$> adduser USERNAME fuse
Reboot.  Plug the camera into the computer.  I haven't yet bothered to mount the camera to the /media directory.  I simply made a /home/USER/camera directory and mount to there when I need to move pictures.
$> mkdir /home/USER/camera
$> gphotofs /home/USER/camera
The camera is then mounted to the /home/USER/camera directory as a normal filesystem, and you can traverse it with common commands such as ls, cd, etc..
   The following command unmounts the camera.  This will not work if you have any terminals open to the camera directory.
$> fusermount -u camera

Thursday, August 30, 2012

Configure bash prompt

I like a simple prompt that shows only the working directory rather than the full path. I don't do a lot of remote work, so I don't need the user and host information.  I color my prompt purple because ls uses that color only for symbolic links (magenta) so my prompt is not similar to typical ls ouput.  This differentiates the prompt from a wall of green (commands and files) and blue (directories) text.  Configure the bash prompt in the /home/USER/.bashrc file.  First, uncomment the force_color_prompt option as shown below:
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes
   The comments are part of the /home/USER/.bashrc file and the variable is commented out by default.  Next change the PS1 variable for both color and non color options from the default USER@HOST:FULLPATH$ to a simple CURRENTDIRECTORY$.  Comment out the default prompt and add the customized prompt below it.  That way you can revert if you make a mistake.
if [ "$color_prompt" = yes ]; then
#    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;35m\]\W\$\[\033[0;0m\] '
else
#  PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
   PS1='${debian_chroot:+($debian_chroot)}\[\033[01;0m\]\W\$ '
fi
unset color_prompt force_color_prompt
   To shorten the prompt change '\u@\h:\w\$ ' to '\W$'. The escape character '\033' (or \e) opens the color code, multiple color codes are separated with ';',  and the color code command is closed with 'm'.  I set the color prompt purple by changing the "\033[01;32m" (in the commented out line) to "\033[01;35m".  IBM has a good summary of color prompts, with a color chart, although they don't give the code, so I posted an example below.  The linux documentation project has thorough documentation of bash configuration.
   Here is a simple script to show the basic 8 color and 8 background combinations available to most shells.   The result of this script is shown in the subsequent screenshot.
#!/bin/bash
#show combinations of 8 colors and 8 backgrounds available to most shells

echo -ne "    "
for c in {0..7} 
do 
    echo -ne "  \033[1;37m 4${c}  \033[0m"
done

echo -e "\n"
for b in {0..7} 
do 
    echo -ne "\033[1;37m  3${b} \033[0m"
    for c in {0..7} 
    do 
    echo -ne "\033[4${c}m \033[3${b}m norm " 
    done
    echo -ne "\033[0m\n\033[1;37m  3${b} "
   for c in {0..7}
    do
    echo -ne "\033[4${c}m \033[1;3${b}m bold " 
    done
    echo -e "\033[0m\n"
done
   I change the /root/.bashrc file to have a prompt with ROOT in red, folder in yellow, and red text.  It is obnoxious, and is meant make a root shell obviously different so I don't do anything dumb.  I do not change my /root/.emacs file so a root emacs frame is obvious, for the same reasons.  The screenshot shows a user emacs frame on the left, then on the right (descending) a root emacs frame, a root xterm, and a user xterm.
You can get really crazy with 256 colors and other features.  Run this script to test if your shell supoprts 256 colors, and see if you like the results.
#!/bin/bash
#show 256 colors
for c in {0..255} ; do
    echo -e "\e[38;05;${c}m ${c} bash colors" 
done

Sunday, August 26, 2012

Change xmonad modkey

Copy this example xmonad.hs to your /home/USER/.xmonad/xmonad.hs file. Note the .xmonad directory is hidden.  Xmonad defaults the alt key as the modkey, which conflicts with emacs key binding.  Fortunately the developers cover this right in the example file as shown in this excerpt:
-- modMask lets you specify which modkey you want to use. The default
-- is mod1Mask ("left alt").  You may also consider using mod3Mask
-- ("right alt"), which does not conflict with emacs keybindings. The
-- "windows key" is usually mod4Mask.
--
myModMask       = mod1Mask
So change that last line to
myModMask       = mod4Mask
and the windows key is now the xmonad mod key.  But because my keyboard doesn't have a right windows key, and I like symmetry I want the menu key (the key with the cursor and drop down menu icon) to also function as my mod key.  This can be done with the xmodmap command.  First run xev from the terminal, which will pop up a blank window.  While the blank window is the focus, keyboard events (presses and releases) will be captured and the information about them displayed in the terminal window that called xev.    
   For example, this is the result when I press the menu key:
KeyPress event, serial 27, synthetic NO, window 0x1200001,
    root 0x160, subw 0x0, time 29169837, (62,330), root:(741,331),
    state 0x0, keycode 135 (keysym 0xff67, Menu), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 27, synthetic NO, window 0x1200001,
    root 0x160, subw 0x0, time 29169893, (62,330), root:(741,331),
    state 0x0, keycode 135 (keysym 0xff67, Menu), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False
The important bit is the " (keysym 0xff67, Menu)", which is the keysim information.  Now, run xmodmap to check the existing modifier keys.
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Alt_R (0x6c),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3      
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)
This shows that Menu is not a modifier.  I want to make the menu key function identical to the windows key (Super_L) such that either functions as mod key for xmonad.  Do this in the following /home/USER/.xmodmap file.
! Comments start with !
! translate Menu into Super_L keycodes.
keysym Menu = Super_L
Test with by running xmodmap .xmodmap command in the terminal, then pressing mod-q which 'restarts' xmonad but has no effect on the current display.  However, the menu key should function as the mod key now.  Add a call to xmodmap to .xinitrc to call this translation on startup.
if [ -f $HOME/.Xresources]; then
    xrdb -merge ~/.Xresources
fi

if [ -f $HOME/.xmodmap ]; then
    /usr/bin/xmodmap $HOME/.xmodmap
fi
xmonad
Then reboot and test it out.  Warning, I'm pretty sure this renders any bindings to the Menu keysym useless, but do not care since I never use it.  Your needs may differ.

Grant users shutdown and reboot privilege

This far in my Xmonad setup I've had to su as root to shutdown or reboot.  Use sudo to allow normal users to shutdown the system. Install the sudo package.
ROOTPROMPT$> apt-get install sudo

UPDATE: The /etc/sudoers file (at least since sudo 1.8.5) suggests adding local content to /etc/sudoers.d instead of altering the /etc/sudoers file with visudo.  I created the following power_conf file to have the same effect as the visudo method described later:
#/etc/sudoers.d/poweroff_conf
[USERNAME] [HOST] = NOPASSWD: /sbin/shutdown -h now, /sbin/poweroff, /sbin/reboot

The manual suggest 0440 permissions for all files in this directory.
ROOTPROMPT$> chmod 0440 /etc/sudoers.d/power_conf

Previous Method: The old way to grant normal users these privileges is to directly modify the /etc/sudoers file using visudo (installed with the sudo package).
#/etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

Defaults        env_reset

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL) ALL

# Allow members of group sudo to execute any command
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL
[USERNAME] [HOSTNAME] = NOPASSWD: /sbin/shutdown -h now, /sbin/poweroff, /sbin/reboot
#
#includedir /etc/sudoers.d
Add the highlighted line to your /etc/sudoers file, substituting your username for [USERNAME] and your hostname for [HOSTNAME].  The 'NOPASSWD' command lets the user issue these commands without entering their password.  This command gives shutdown, poweroff, and reboot privileges to the user, but only for the commands issued exactly as entered in this file.  For example, to shutdown as user:

USERPROMPT$ sudo /sbin/shutdown -h now 

will work, but

USERPROMPT$ sudo /sbin/shutdown

will not.  I learned how to set this up from http://www.debian-administration.org/articles/33.  Be careful which privileges you grant to users.

Saturday, August 25, 2012

Customize emacs

I've switched to Xmonad as a window manager.  Previous entries covered the xmonad install and xterm configuration.  I'll now configure emacs with a black background and grey text, since green is already used by xterm and I like a soft text color but want my emacs windows easily differentiable from the xterm windows.  I turn off the menu bar, the tool bar, and the scroll bar since I limit my use of the mouse and these widgets just waste space.  I also turn off the emacs startup screen.  The /home/USER/.emacs file contains the user specific configurations.  Mine is pasted below.
(set-background-color "black")
(set-foreground-color "grey")
(setq inhibit-startup-message t)
(menu-bar-mode -1) 
(tool-bar-mode -1)
(scroll-bar-mode -1)
   Each of these commands - except for the startup message - can be tested in the emacs window by typing m-x then the command.  For example m-x set-foreground-color then return will prompt you for the new color setting.  The commands with true/false and on/off options will not prompt you but simply toggle between the settings.
   The screenshot below shows an emacs frame on the left (with two windows open), a chrome browser window on the top right and an xterm on the bottom right.  The top emacs window is the filesize tutorial using the boost filesystem, and shows the C/C++ syntax highlighting in this color scheme.  The bottom emacs window is my .emacs file and shows the Lisp syntax highlighting in this color scheme.
   If you ever need to access the emacs menu bar you can pop it up using ctrl-mouse3.  http://emacswiki.org/ and http://www.masteringemacs.org/ are my main sources for emacs knowledge.

Customize xterm

Edit the /home/USER/.Xresources to customize the xterminal.  I like green text on a black background, and the default font size is too small for me.  First, run the xfontsel from the terminal, and adjust the parameters to your liking and system availability. The image below shows my fontsel with fmly set to 'fixed',  wght set to 'medium', and pxlsz set to 14.  The english alphabet appears in the window if you have a font that matches your settings.  If the english alphabet is not visible (Chinese or some other alphabet appears) you need to adjust your settings until the english alphabet appears (assuming you want english).  The string between the parameters and the alphabet is used to set the xterm font.  Copy it.

In this case, I copy "-*-fixed-medium-*-*-*-14-*-*-*-*-*-*-*".  Now open or create the /home/USER/.xresources file.  Mine is pasted below, and sets green text - size medium font - on a black background.  My terminal saves the previous 512 lines in the history.
!Comments start with !

xterm*background: black
xterm*foreground: green
xterm*font: -*-fixed-medium-*-*-*-14-*-*-*-*-*-*-* 
xterm*saveLines:  512
See http://invisible-island.net/xterm/ for full xterm documentation.
   The following /home/USER/.xinitrc file checks for an xresources file, then runs xmonad.  This will find your xterm customizations once you run the startx command.
if [ -f $HOME/.xresources ]; then
    xrdb -merge $HOME/.xresources
fi

xmonad

Tuesday, August 21, 2012

Xmonad on a fresh debian install

   I've decided to try Xmonad as my window manager.  Xmonad is a tiling window manager that automatically arranges the application windows in the display such that the entire screen is used.  Unlike the more common stacking or compositing window managers, Xmonad does not allow overlap.  Since the entire screen is used, I don't need a desktop environment either.  The numerous default keyboard commands and the ease of customization can reduce the need to use the mouse.
   Rather than suffer through removing the desktop and related packages I will do a fresh install of the core debian system.  Grab the iso for your architecture from the debian website.  Proceed through the install as normal except when you get to the tasksel menu, de-select the "Desktop Environment" option, which is at the top of the list.  The taskel menu is shown in the figure below, and you want all options unchecked for a bare bones debian install.
   Reboot the machine after the install is complete.  You will login on a TTY window, then su to login as root, and install the following packages.  'ROOTPROMPT$' is just your TTY prompt.
ROOTPROMPT$> apt-get install xorg 
ROOTPROMPT$> apt-get install xmonad
ROOTPROMPT$> apt-get install alsa-base alsa-utils
ROOTPROMPT$> apt-get install chromium-browser
ROOTPROMPT$> apt-get install emacs
   Feel free to substitute your browser and text editor of choice in those last two commands.  Configure alsa with the following command, then exit root.
ROOTPROMPT$> alsactl init
ROOTPROMPT$> exit
Your system should now have sound. UPDATE: Running through my own install instructions for a new machine, I did not have sound after this step.  I fixed my low volume with snd_hda_intel module problem based on this snd_hda_intel howto.
   The following command sets xmonad to be called as the window manager when X is started.  If you have other window managers installed you will need to comment them out.  However, if you are following this tutorial that should not be the case.  Read more about the debian specifics of .xinitrc, or a general synopsis of .xinitrc.
$> echo "xmonad" >> /home/USER/.xinitrc
Now you can start X11, which will call xmonad as the window manager.
$> startx
You will get a blank screen, and need to press alt+shift+enter to start xterm (the default terminal emulator).  From xterm you can launch your browser and start reading through the xmonad default key commands.  This screenshot shows my simple desktop with a chromium window as the master (on the left) and a root terminal (top) and a user terminal (bottom) on the right.  Following only the preceding instructions will get you an xterm with black text on a white background.  Subsequent posts will cover xterm and bash customization, as well as some additional xmonad configuration.