2015년 10월 25일 일요일

Stepmania 5 with USB PlayDance DDR pad (dragonrise 0079:0011) in Linux

For the past 6 weeks, I've been doing sysadmin tasks remotely, working from home. One good thing about not having to go into the office is I can sleep about 1~2 hours more in the morning. One bad thing is that I am walking a lot less than I used to. I track my steps with a Fitbit Zip and I have a Beeminder steps goal linked through Fitbit's API. If I don't walk at least 7,000 steps per day, my credit card will get charged a penalty by Beeminder.

When working in the office, I routinely surpassed 7,000 steps per day, but working from home, I found I was walking less than 4,000...I was inspired by this post in which a fellow Beeminder user extolled the virtues of DDR (Dance Dance Revolution) for getting some exercise.

I searched some Korean shopping sites and found a USB DDR pad for W23,000 (about $20 at the current exchange rate of W1200/$1):


It's a soft, foldable mat that has sensors inside corresponding to 8 buttons. When I plugged the DDR mat into the USB port on my laptop, dmesg -wH gave me the following info:
...
[Oct25 02:34] usb 5-1: new low-speed USB device number 6 using uhci_hcd
[  +0.183611] input: USB Gamepad  as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/0003:0079:0011.0006/input/input18
[  +0.000565] dragonrise 0003:0079:0011.0006: input,hidraw3: USB HID v1.10 Joystick [USB Gamepad ] on usb-0000:00:1d.0-1/input0

And lsusb returns the following:

[archjun@latitude630 ~]$ lsusb
...
Bus 005 Device 006: ID 0079:0011 DragonRise Inc. Gamepad

In a Google search for this usb ID, I learned that the DragonRise chipset is generally used in handheld game controllers. Apparently now it's also used in DDR dance mats! The DDR mat I purchased is called PlayDance and is manufactured in China but sold on many Korean online shopping sites.

When I first launched Stepmania 5 (which works on Windows and Linux), the DDR pad seemed unresponsive. Before sending it back to the seller, I needed to check if HW input was getting picked up or not.

I referred to the excellent Archlinux documentation on gamepads at the following link:
https://wiki.archlinux.org/index.php/Gamepad

Recent kernels should be able to automatically detect USB joystick hardware. The documentation indicates that in /dev/input/by-id there should be a new device created when the USB gamepad/dancepad is plugged in:

[archjun@latitude630 ~]$ cd /dev/input/by-id
[archjun@latitude630 by-id]$ ls
usb-0079_USB_Gamepad-event-joystick
usb-0079_USB_Gamepad-joystick
usb-KYE_Optical_Mouse-event-mouse
usb-KYE_Optical_Mouse-mouse

After running cat on the the gamepad device, gibberish is printed to the screen every time I step on a dancepad button:

[archjun@latitude630 by-id]$ cat usb-0079_USB_Gamepad-event-joystick 
:� V0r V0r
=� V�J V0r  =� V�J " =� V�J =� VV~
                                          =� VV~

[archjun@latitude630 by-id]$ cat usb-0079_USB_Gamepad-joystick
F=�U �F=�U� F=�Ucat usb-0079_USB_Gamepad-joystick� F=�U� F=�U� F=�U�F=�U� F=�U�F=�UF=�U� F=�U ��F=�U �� �E�U ?G�U I�U �J�U �M�U yN�U �O�U

After verifying that input from the USB pad was being detected by the Linux host, I once again tried Stepmania 5 to see if it would detect the dance pad. I don't know why Stepmania 5 didn't detect input the first time, but the second time the DDR pad worked fine and I was able to map dance pad buttons to actions in the Options menu.

For the first day or two, it was hard to break 3000 steps in an hour, but Now that I've got the hang of it (well, kind of -- my best is Easy 5) I find it's possible for me to record 3000 steps in 30 minutes and break into a sweat if I do enough songs > 130 bpm. So far, DDR seems to be an effective form of indoors exercise!

2015년 10월 18일 일요일

Transferring files without ssh: netcat, darkhttpd, and Python

ssh is indispensable when working on remote machines, but to my surprise (and frustration) many of the big telecoms in Korea have started disabling sshd on most machines due to security audit recommendations. This is ridiculous when you consider that the audits don't flag the rampant use of telnet (which sends all traffic in cleartext) for managing machines on the internal network. At some sites that disable sshd, sysadmins are using old-fashioned ftp in place of sftp or vsftpd!

To do my work, whether it's applying patches or setting up Apache, at a minimum I need to be able to transfer files between machines. When you aren't given access to ssh (which also means no scp or vsftpd), oftentimes netcat (nc), darkhttpd or Python's built-in webservers will do nicely for file transfers.

Netcat

Lots of old-school sysadmins are familiar with using netcat to transfer files between machines, and there are many tutorials on the Internet. Here is an example of using netcat (both GNU netcat/nc and BSD nc will work with each other) to transfer a file to a machine running firewalld dynamic firewall.

By default, firewalld will keep all ports closed except those necessary for web browsing (port 80 http or 443 https) and certain user-defined services like nfs, ssh, etc. The remote machine in this example is on my local network and has sshd and rpcbind (for NFS) running. firewalld will ignore a regular ping scan from nmap, but if we run nmap -Pn hostname, we can see a list of open ports (-Pn Treat all hosts as online -- skip host discovery).

[archjun@latitude630 playground]$ nmap -Pn 192.168.10.57

Starting Nmap 6.47 ( http://nmap.org ) at 2015-10-16 23:07 KST
Nmap scan report for 192.168.10.57
Host is up (0.85s latency).
Not shown: 996 filtered ports
PORT     STATE  SERVICE
22/tcp   open   ssh
111/tcp  open   rpcbind
873/tcp  closed rsync
2049/tcp open   nfs

Before transferring files to a remote machine using netcat, first I need to temporarily open a port for netcat to use. Let's use tcp port 4444:

[archjun@d257 playground]$ sudo firewall-cmd --zone=internal --add-port=4444/tcp
[sudo] password for archjun: 
success

btw, firewalld has the concept of zones which have different security policies. Network interfaces can be placed The internal zone applies to the local network only. The available zones are:

[archjun@d257 playground]$ firewall-cmd --get-zones
block dmz drop external home internal public trusted work

Running nmap from latitude630  on the remote machine d257 now shows tcp port 4444:

[archjun@latitude630 playground]$ nmap -Pn 192.168.10.57

Starting Nmap 6.47 ( http://nmap.org ) at 2015-10-16 23:21 KST
Nmap scan report for 192.168.10.57
Host is up (0.61s latency).
Not shown: 994 filtered ports
PORT     STATE  SERVICE
22/tcp   open   ssh
111/tcp  open   rpcbind
873/tcp  closed rsync
2049/tcp open   nfs
4444/tcp closed krb524

Now from the remote machine d257 I will start BSD nc and tell it to listen on tcp port 4444 and to redirect all traffic to the file rcv_nc_test.txt:

[archjun@d257 playground]$ nc -l 4444 > rcv_nc_test.txt

From the sending machine, I will start GNU netcat/nc and tell it to send the file test_new_vimrc which contains the following text:

abc
#aabcde
hopefully no more temp files generated in editing path..
One more try... hopefully no more .un~ files will be generated
in the edited file's PATH

[archjun@latitude630 playground]$ nc 192.168.10.57 4444 < test_new_vimrc

nc on both the receiver and sender will not give any indication that the transfer is complete, so on the receiving end, I sent Ctrl-C to terminate the netcat session. Let's see if the content of the text file from latitude630 was sent to rcv_nc_test.txt on d257:

[archjun@d257 playground]$ ls
1  3    foo-replace      orig1      orig2  play-w-bash-functions.sh  test_sed_replace.txt
2  foo  netcat_file.svg  orig1.old  orig3  rcv_nc_test.txt

[archjun@d257 playground]$ cat rcv_nc_test.txt 
abc
#aabcde
hopefully no more temp files generated in editing path..
One more try... hopefully no more .un~ files will be generated
in the edited file's PATH

The content of test_new_vimrc from latitude630 was successfully redirected to rcv_nc_test.txt on d257! nc can also transfer binary files just fine.


Built-in Webservers in Python 2 and Python 3

Nowadays on most Linux installations (RHEL/CentOS, Ubuntu) I work on in the field, python 2 is installed by default. Python 2 comes with its own webserver module called SimpleHTTPServer. When it is invoked from the command line, it will by default serve up the current directory over http on port 8000. Since the remote machine is running firewalld, I first have to open tcp port 8000:

[archjun@d257 bin]$ sudo firewall-cmd --zone=internal --add-port=8000/tcp
[sudo] password for archjun: 
success

[archjun@d257 playground]$ python2 -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
192.168.10.63 - - [16/Oct/2015 23:18:36] "GET / HTTP/1.1" 200 -
192.168.10.63 - - [16/Oct/2015 23:18:36] "GET /favicon.ico HTTP/1.1" 404 -
192.168.10.63 - - [16/Oct/2015 23:18:41] "GET /foo-replace HTTP/1.1" 200 -

Note that in Archlinux python 2 must be invoked with python2. Since 2014, python 3 has been the default python in Arch. In Python 3, invoking the built-in webserver is a bit different. The module name is http.server:

[archjun@d257 playground]$ python -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...
192.168.10.63 - - [16/Oct/2015 23:31:54] "GET /test_sed_replace.txt HTTP/1.1" 200 -
192.168.10.63 - - [16/Oct/2015 23:31:58] "GET /play-w-bash-functions.sh HTTP/1.1" 200 -

Now if I navigate to 192.168.10.57:8000 from another machine on the local network, I get the following HTML page listing the contents of ~/playground:


Much easier than configuring apache/httpd, isn't it? Although the page reads, "Directory listing for /" it is actually serving up ~/playground from host d257. Output is the same for SimpleHTTPServer and http.server. If you want to change the port number, simply add the port you wish to use after the module name, i.e. python -m http.server 8080. Note that if you want to use a port below 1024, you must invoke the webserver as root (but be aware of the security risks).


Darkhttpd

I am a big fan of darkhttpd. I normally use it in a PXE server setup with tftpboot and dnsmasq to serve up files over http as I detailed in this post. While python's built-in webserver is fine for serving up a few files in a pinch, darkhttpd will handle tens of GB of transfers without any hiccups, as I can attest to when installing Linux on multiple machines from a PXE server sending files over 1 gigabit Ethernet.

By default, darkhttpd will share the specified directory on tcp port 8080, but you can specify a different port with the --port option:

[archjun@d257 playground]$ darkhttpd . --port 8000
darkhttpd/1.11, copyright (c) 2003-2015 Emil Mikulic.
listening on: http://0.0.0.0:8000/
1445006481 192.168.10.63 "GET /" 200 1024 "" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36"
1445006504 192.168.10.63 "GET /netcat_file.svg" 200 1463 "http://192.168.10.57:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36"

Navigating to 192.168.10.57:8000 from another machine shows the following HTML page:


btw if you launch darkhttpd as root, it will share the specified directory on tcp port 80.


Conclusion

If you ever find yourself on a locked-down machine without ssh, give netcat, python webservers and darkhttpd a try. In the examples above, opening ports using firewalld is quite easy compared to editing and reloading static iptables rules. I am so glad that RHEL 7.x uses firewalld by default!

2015년 10월 11일 일요일

Emacs with racket-mode as a replacement for DrRacket

Recently I've been taking the UBC course Systematic Program Design (SPD) Part 2 on edX. The language used in the course is Basic Student Language (BSL) from the well-known How to Design Programs (HtDP 2nd Edition) curriculum. The DrRacket IDE used in the course is a very convenient tool containing an editor, REPL, stepper and even allows you to copy-and-paste images directly into the editor window after which they can be manipulated in programs.

In Part 1 of the course, I stuck with DrRacket despite being an Emacs user. Later when searching Google for info on using Emacs for HtDP languages and Racket, many Emacs users suggested Geiser mode, but recently a Racket-specific major mode called racket-mode has been developed and is available through the melpa package repository. If you are running Emacs 24+ you can enable melpa with the following line in your .emacs file:

(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)

Then M-x package-list-packages and C-s for racket-mode.

racket-mode works great and can even render images in the REPL:


One thing to watch out for when saving code that includes copy-and-pasted images in the DrRacket editor window, however, is that the saved file will be in a special binary format that is not version control friendly. If you want to use git to track changes in your BSL / Racket code, for example, your code needs to be in text format.

A DrRacket binary file will have a header that looks like the following:

#reader(lib"read.ss""wxme")WXME0108 ## 
#|
   This file uses the GRacket editor format.
   Open this file in DrRacket version 5.3 or later to read it.

   Most likely, it was created by saving a program in DrRacket,
   and it probably contains a program with non-text elements
   (such as images or comment boxes).

            http://racket-lang.org/
|#

In the starter files provided by the instructors, all the comment boxes are graphical; this will also cause your BSL source files to be saved in binary format. To avoid this, you can convert graphical comment boxes to pure text comments by clicking anywhere inside the comment box, opening the Racket menu and selecting Comment Out with Semicolons:



Note you can also create block comments in BSL or Racket with #| some text |# (hash+pipe some text pipe+hash). Regular line comments are denoted by semicolon(s).

In the programs you have to write for HtDP and the SPD edX course, images will be frequently incorporated into your programs. The best way to avoid having your source files become binaries is to not cut-and-paste images directly into the DrRacket editor window. There is a function called (bitmap ...) that is part of the 2htdp/image library that allows you to refer to an image in a file other than your source file.

For example:

(require 2htdp/image)
(define test-image (bitmap "images/cloud.png"))
test-image
(flip-vertical test-image)
(scale 0.5 test-image)

The path to cloud.png is relative to the location of the current open file. Since the image file is not contained in the source, it will not become a big ugly binary when saved.

The results of the code above in the racket-mode REPL window:


Now all you have to do is tell your version control system to ignore all files in the images folder. Since I use git, I added the following file formats to .gitignore in my repo directory:

#Tell git to ignore image files
*.jpeg
*.jpg
*.bmp
*.png
*.gif
#ignore temp files
*~

Now you should be all set to use Emacs as your development environment for HtDP 2e and the UBC Systematic Program Design courses!

References:

http://stackoverflow.com/questions/17895038/best-way-to-define-an-image-variable-in-racket

http://stackoverflow.com/questions/12674288/how-to-run-racket-in-emacs/12675896#12675896


2015년 10월 4일 일요일

Disappearing evalauation period days on Win7 trial VM's from Modern.ie

I use Win7 VM's from modern.ie on both a Linux machine (running Archlinux 4.2.2 kernel) and a Win10 machine. The Win7 VM's are very convenient because they give you an evaluation period of 90 days and the trial can be rearmed up to 3 times for a total of 360 days of use. This is irrespective of whether you have saved a snapshot of your VM; once the snapshot is restored, the number of days that have elapsed since the first installation will be used to calculate how many evaluation days you have remaining.

I installed a Win7 VM for a Linux host just 30 days ago, but when I resumed from a save state, the VM told me my evaluation had expired! I thus rearmed the evaluation period using slmgr/rearm from the windows command prompt cmd.exe (which must be run as Administrator). I expected to see that I would be given 90 additional days of use, but I got the following:



From the screenshot (click above to expand) you can see that after the rearm, only 10 days are remaining (although 90 should be granted) and that there are 4 rearms remaining...

On a laptop running Windows 10 (host), the Win7 VM (guest) from modern.ie runs just fine in Virtualbox and the evaluation period counts down correctly. You can see that I have 54 days remaining on this VM:



I wonder what happened to the Win7 VM on the Linux host that caused the evaluation period timer to get messed up...

Postscript Dec. 20, 2015

The first time you boot your new Win7 VM, you will be asked whether you would like to go online to validate your installation (connect to the licensing server). If you don't connect to the licensing server at least once, your VM will only be valid for 10 days. Although it is possible to reset the counter 3 times, unless you validate online you will only be given 10 days of usage at most. I think what happened is that I accidentally closed the validation window the first time I booted the VM, so I was never given 90 days of full usage before a usage counter reset with slmgr/rearm