shellinabox for Android

Introduction

After fighting with many bugs to get everything to run, I finally got shellinabox to run on my Android phone!

shellinabox on android

shellinabox on android

Steps

I will probably post an updated article related on the exact steps on how to build (or just provide the executables) but the main issues were:

a) compile openssl so that libcrypto.a could be built with no-dso option (to avoid references to dlopen / etc calls which forced the Android executable to try to use bionic at runtime). Default Makefile is almost ok for static build, just CC / RUNLIB / AR need to be updated to point to arm-eabi equivalents.

b) compile openssh as Android doesn’t have /bin/login, and shellinabox would require SSH connection. Using LDFLAGS=”-static” created the static build.

c)compile shellinaboxd statically. It was difficult, as the configuration script, even if it does have options to try to create it statically, it fails and there are still references to libc.so.0. You need to statically link against libc, avoid the duplicates with warn method (between libc and launcher.c).

d) create fake /etc/passwd and /etc/group files, and use busybox’s passwd to create a root password for the phone (which is the same as the password for DroidSSHd server running already on the phone).

e) patch launcher.c to include also /system/xbin as member of PATH environment variable – I’ve submitted a bug report here: http://code.google.com/p/shellinabox/issues/detail?id=143

It works :) for now but only plain HTTP connection, I will attempt to setup HTTPS whenever I find the next free timeslot.

PHP and Lighttpd for Android

Introduction

Below you can find an bundle of PHP 5.3.8 (CGI only) and Lighttpd 1.4.29 (FastCGI module included) which are cross compiled for ARMv5 CPUs (Android platforms mainly).

As you mail well know, both PHP and Lighttpd offer modules that could be loaded at run-time based on settings within configuration files. The bundle doesn’t include all modules, due to difficulties encountered when compiling for ARM platforms. Those modules that are included are statically linked in the executables (so no additional files are needed) nor configuration files need to be updated to load them.

Screenshots

Below you can see screenshots with the phone browser opening localhost address. Once you unpack the archive, there’s an index.php file which just calls phpinfo() to show the details about the build.

Of course, you can remove the file and put your own scripts :)

phpinfo() on Sony Arc

phpinfo() on Sony Arc

phpinfo() on Sony X10 Mini

phpinfo() on Sony X10 Mini

PHP Modules

The list of PHP modules that are statically linked:

[root@arc]/sdcard# php -m
[PHP Modules]
cgi-fcgi
Core
ctype
date
dom
ereg
fileinfo
filter
ftp
gd
hash
iconv
json
libxml
pcre
PDO
pdo_sqlite
Phar
posix
Reflection
session
SimpleXML
soap
sockets
SPL
SQLite
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

Lighttpd Modules

mod_indexfile
mod_userdir
mod_dirlisting
mod_status
mod_simple_vhost
mod_evhost
mod_secdownload
mod_cgi
mod_fastcgi
mod_scgi
mod_ssi
mod_proxy
mod_staticfile
mod_evasive
mod_compress
mod_usertrack
mod_expire
mod_accesslog

Download

This comes with NO WARRANTY. Use it at your own risk!

php-5.3.8_lighttpd_1.4.29_armv5.tar.gz

License

Please check README.txt file found in /system/README.txt within the bundle.

PHP executable is offered under PHP license, Lighttpd executable under Lighttpd license, all other files in the bundle are offered under New BSD License (3 clause BSD license).

Installing

The bundle tries to mimic as much as possible the layout of a Debian installation of the two files. However, due to file system layout on Android phones (binaries under /system folder), the folders are one step down, under /system folder:

`-- system
    |-- bin
    |   |-- lighttpd -> /system/xbin/lighttpd-static
    |   `-- php -> /system/xbin/php-cgi
    |-- etc
    |   |-- lighttpd
    |   |   `-- lighttpd.conf
    |   `-- php
    |       `-- php.ini
    |-- var
    |   |-- log
    |   `-- www
    |       `-- index.php
    `-- xbin
        |-- fcgiserver
        |-- lighttpd-static
        |-- php-cgi
        |-- reload_fcgi.sh
        `-- reload_lighttpd.sh

Prerequisites:

  • rooted phone with busybox installed.
  • mount the /system partition as RW.

Using DroidSSHd on the phone and connecting with Putty (or equivalent) makes the whole process faster.

After you copy the archive above into the root of your SD Card, installation is easy:

cd /
tar xf /sdcard/php-5.3.8_lighttpd_1.4.29_armv5.tar.gz
reload-fcgi.sh
reload-lighttpd.sh

You might notice that the owner / group of the files is 1000:1000. Ignore that, as long as you execute them as root, there’s no issue (those are the IDs of my username on the PC I created the tar.gz archive and tar tries to conserve the user / creation time / etc from when the archive was created).

The last two commands start the FCGI server (PHP with 4 children processes), and then launch lighttpd server as daemon.

The default port is 80.
Default htdocs folder is /system/var/www.

The configuration files are under /system/etc/lighttpd/lighttpd.conf and /system/etc/php/php.ini. To restart either PHP or Lighttpd, please use one of the commands above.

It is mandatory that you are on the root folder when you extract the archive. tar will take care of creating all the missing folders, creating the links, etc, as long as you are on the root folder.

You can now open the phone’s browser and point it at localhost :) and the phpinfo() page should appear.

Example usage

Installing Simple Machines Forum 2.0.1 on Android

Before executing the commands below, you need the “Full Install” smf_2-0-1_install.tar.gz archive downloaded from SMF and then copied onto your /sdcard root folder.

# cd /system/var/www
# ls
index.php
# mkdir forum
# cd forum
# tar xf /sdcard/smf_2-0-1_install.tar.gz
# reload_fcgi.sh
# reload_lighttpd.sh

Last two commands are optional, if you already started the FastCGI server as well as lighttpd.

You should now connect to http://localhost/forum and finish installation of the forum.

Enjoy :)

Targul de vechituri, Valea Cascadelor

Am fost azi pana in targul de vechituri din Valea Cascadelor, Bucuresti.

Este una din micile-mi placeri ale vietii, plimbarea prin mormane de vechituri in speranta ca gasesc ceva cu care sa ‘rezonez’. Sentimentul acesta de nostalgie vine mereu insotit de revolta contra chinezariilor, nu stiu de ce, dar sunt si multe tarabe unde se vand nu vechituri, ci chinezarii ieftine noi. Ma rog, incerc sa fac abstractie de ele… De obicei caut bibelouri vechi, aparate de radio vechi, ceasuri vechi, samd …

La mijlocul excursiei fac o pauza pentru niste mici (1 Leu micul, 0.5 Lei painea si 0.5 Lei mustarul, 3 Lei paharul de vin):

Mici, Mustar, Paine si un pahar de vin.

Mici, Mustar, Paine si un pahar de vin.

Am rezonat cu:

Bibelou catel, facut la Cluj (inca are eticheta pe el):

Bibelou Catel - 1

Bibelou Catel - 1

Bibelou Catel - 2

Bibelou Catel - 2

Bibelou Foca si Minge, facut in 1997 la Dorohoi:

Bibelou Foca si minge - 1

Bibelou Foca si minge - 1

Bibelou Foca si minge - 2

Bibelou Foca si minge - 2

Si doua carnete, unul de sindicat, si unul de munca, din 1950 / 1960:

Carnete RSR

Carnete RSR

Abia astept sa merg din nou peste cateva luni :)

tvtime / lircrc – how to configure the remote control of the tv tuner.

This post tries to summarise how to configure the tv tuner’s remote control to be used with tv time on Ubuntu 11.04. My TV Tuner is an AverMedia AVerTV Studio 507 (m507) board just like this one.

The difficulty to configure it comes from a couple of issues:

  1. tvtime is a very old application (apparently it was last updated on 2005). It has few patches (as version 1.0.2 delivered with Ubuntu 11.04) which makes it play with Alsa. It still works, but the tutorials / configuration files are out of date and won’t work by default.
  2. some remote control buttons are by default mapped to a multimedia key (for example the Power button on the remote brings the “Shutdown” popup instead of starting / stopping the tv tuner application). But once lirc configured, the remote control keys will be routed through lirc instead of the default mapping.

One advantage is that the tuner works as is with kernel version 2.6.38 that comes bundled with Ubuntu. TV time should show a crystal clear image, but there’s a lot of work to get it to respond to the remote control buttons.

a) Configuring saa7314 module

The first thing to do is to activate the correct module with the correct options. In my case, the values from /etc/modprobe.d/options.conf are:

# value taken from here: http://www.mjmwired.net/kernel/Documentation/video4linux/CARDLIST.saa7134 for id: 1461:a11b (102 works)
options saa7134 card=102 tuner=38 i2c_scan=1 radio_nr=1 ir_debug=1

alias char-major-81-0 saa7134
alias char-major-81-1 off
alias char-major-81-2 off
alias char-major-81-3 off

# options saa7134 card=157 tuner=38
# install saa7134 /sbin/modprobe --ignore-install saa7134; /sbin/modprobe saa7134 -alsa
options saa7134-alsa index=1
options ir-core debug=1

The most important thing to notice is that you might not get your card set up properly since the documents are again out of date. TV Time showed a perfect image using card=157 tuner=38 argument but apparently, the remote keys were not detected, and this stopped progress for a while. It was actually until I read the source code of the module that I discovered that GPIO support for saa7314 module was activated only for card=102 (although according to the documentation, 157 is the value for my card).

Once proper arguments are given (card=102 and ir_debug = 1) that I got the remote keys apparing in dmesg:

[14441.724011] saa7133[0]/ir: build_key gpio=0x20c mask=0x7c8 data=17
[14443.752010] saa7133[0]/ir: build_key gpio=0x3d4 mask=0x7c8 data=30
[14443.908014] saa7133[0]/ir: build_key gpio=0x3c4 mask=0x7c8 data=30
[14444.844045] saa7133[0]/ir: build_key gpio=0x61c mask=0x7c8 data=49
[14445.000010] saa7133[0]/ir: build_key gpio=0x60c mask=0x7c8 data=49

This is mandatory to appear, if you don’t have these logs (push a remote button, then issue dmesg and check at the end, you should see two lines for each button – which mean a press and a release for that button).

If you have those appearing in dmesg, the volume / mute / number buttons should work already in TV Time. However, as you will notice, CHANNEL_UP / CHANNEL_DOWN keys do not work (since there’s no X11 mapping for them, they are specific to a TV viewing application for example). Also, the Power button will in fact trigger the “Shutdown” popup in Ubuntu (which will eventually shut the system down).

A couple of observations here:

  1. The volume / mute work using the system volume and there are nice popups indicating the action (like you would be using the multimedia keys on a real keyboard). Unfortunately once the routing will be done from lirc the volume stops to work.
  2. The sound should work in TV Time (if it doesn’t there are few options: “tvtime --mixer=hw:0/Line” or “tvtime --mixer=default/Line“. If these still don’t make it work you need to remove the .tvtime folder and recreate the channels (sometimes tvtime screws up the configuration)
    rm -rf .tvtime
    tvtime-configure --norm=pal --frequencies=europe

If sound works and remote keys appear in dmesg, then this step is done.

b) Identify /dev/input/eventX source for the remote

To identify which event source it is used by the remote sensor, you need to:

$ cat /proc/bus/input/devices
...
I: Bus=0001 Vendor=1461 Product=a11b Version=0001
N: Name="saa7134 IR (Avermedia AVerTV St"
P: Phys=pci-0000:05:00.0/ir0
S: Sysfs=/devices/pci0000:00/0000:00:1e.0/0000:05:00.0/rc/rc0/input5
U: Uniq=
H: Handlers=kbd event5
B: PROP=0
B: EV=100013
B: KEY=fc310 82140000 0 0 0 0 2148000 180 4001 9e0000 0 0 ffc
B: MSC=10

and watch for saa7314 in the output. Beneath it, the Handlers say event5 so that will be the event source. In my case it is 5, but that number will probably be different in your case.

To test that it works, execute the command below and then start pushing remote buttons. You should get buttons like shown below:

$ sudo evtest /dev/input/event5
...
Event: time 1315810851.586142, type 1 (Key), code 114 (VolumeDown), value 1
Event: time 1315810851.586144, -------------- Report Sync ------------
Event: time 1315810851.742136, type 1 (Key), code 114 (VolumeDown), value 0
Event: time 1315810851.742140, -------------- Report Sync ------------

c) installing lirc

First you need the latest lirc version installed. If you don’t have it, run the install command below, otherwise, lirc needs to be reconfigured with “dpkg-reconfigure lirc"

apt-get install lirc

During installation, you will be asked to choose the “Remote Control configuration”. Make sure you select “Linux input layer (/dev/input/eventX)” option, then continue installation / reconfiguration.

On the “Custom event interface for your dev/input device” window, you should select the “…event-ir” value:

lirc dev/input event-ir

lirc dev/input event-ir

Lirc will restart automatically.

To check that remote control buttons are detected now via LIRC, you need to run the command below and watch for output:

$ irw
0000000080010073 00 KEY_VOLUMEUP devinput
0000000080010193 00 KEY_CHANNELDOWN devinput
0000000080010006 00 KEY_5 devinput

One thing to notice is also the remote key/button names: KEY_VOLUMEUP, KEY_CHANNEL_DOWN, etc .. These values are needed on the last step, configuring irexec with .lircrc file.

d) irexec with .lircrc file

TVTime is controlled using two additional programs:

  1. irexec – which can trigger a program based on a remote button press
  2. tvtime-command – which sends a TVTime command to tvtime

A sample ~/.lircrc file is attached here.

You need to put this file into your home folder.

The next step is to run irexec as a daemon. It will interpret .lircrc file and send the according commands. irexec must be executed as the user the commands (not as root). Once you login to your session, you need to:

$ irexec -d

Few things to notice about the .lircrc file provided above:

  1. it enables the KEY_ZOOM (named “Full screen” on remote) to simulate key ‘F’ in tvtime, by sending the command TOGGLE_FULLSCREEN to tvtime:
    begin
    prog = irexec
    button = KEY_ZOOM
    config = tvtime-command TOGGLE_FULLSCREEN
    end
  2. It enables the KEY_VIDEO (named “Source” on the remote) to switch between the aspect ratio (4:3 to 16:9 and viceversa) useful for landscape LCD / LED screens:
    begin
    prog = irexec
    button = KEY_VIDEO
    config = tvtime-command TOGGLE_ASPECT
    end
  3. Most important is that the volume keys / mute keys are NOT sent to tvtime, but to the X11 server (and thus the volume up / down popup work!). This is done by faking the multimedia keys Volume Up / Volume Down / Mute keys:
    begin
    prog = irexec
    button = KEY_MUTE
    config = xsendkeycode 121 1; xsendkeycode 121 0
    end
    begin
    prog = irexec
    button = KEY_VOLUMEUP
    config = xsendkeycode 123 1; xsendkeycode 123 0
    end
    
    begin
    prog = irexec
    button = KEY_VOLUMEDOWN
    config = xsendkeycode 122 1; xsendkeycode 122 0
    end
    

To fake the system volume up / down keys, I used a program xsendkeycode which you have to install using command:

$ apt-get install lineakd

This program will simulate a keypress by using the given raw key code. 1 and 0 means key is pressed, then key is released. To find out the raw key code, the current key mapping has to be investigated:

viulian@adevaraciune:~$ xmodmap -pk | grep -i audio
121        0x1008ff12 (XF86AudioMute)    0x0000 (NoSymbol)    0x1008ff12 (XF86AudioMute)
122        0x1008ff11 (XF86AudioLowerVolume)    0x0000 (NoSymbol)    0x1008ff11 (XF86AudioLowerVolume)
123        0x1008ff13 (XF86AudioRaiseVolume)    0x0000 (NoSymbol)    0x1008ff13 (XF86AudioRaiseVolume)
171        0x1008ff17 (XF86AudioNext)    0x0000 (NoSymbol)    0x1008ff17 (XF86AudioNext)
172        0x1008ff14 (XF86AudioPlay)    0x1008ff31 (XF86AudioPause)    0x1008ff14 (XF86AudioPlay)0x1008ff31 (XF86AudioPause)
173        0x1008ff16 (XF86AudioPrev)    0x0000 (NoSymbol)    0x1008ff16 (XF86AudioPrev)
174        0x1008ff15 (XF86AudioStop)    0x1008ff2c (XF86Eject)    0x1008ff15 (XF86AudioStop)    0x1008ff2c (XF86Eject)
175        0x1008ff1c (XF86AudioRecord)    0x0000 (NoSymbol)    0x1008ff1c (XF86AudioRecord)
176        0x1008ff3e (XF86AudioRewind)    0x0000 (NoSymbol)    0x1008ff3e (XF86AudioRewind)
208        0x1008ff14 (XF86AudioPlay)    0x0000 (NoSymbol)    0x1008ff14 (XF86AudioPlay)
209        0x1008ff31 (XF86AudioPause)    0x0000 (NoSymbol)    0x1008ff31 (XF86AudioPause)
215        0x1008ff14 (XF86AudioPlay)    0x0000 (NoSymbol)    0x1008ff14 (XF86AudioPlay)
216        0x1008ff97 (XF86AudioForward)    0x0000 (NoSymbol)    0x1008ff97 (XF86AudioForward)
234        0x1008ff32 (XF86AudioMedia)    0x0000 (NoSymbol)    0x1008ff32 (XF86AudioMedia)

As you can see, the XF86AudioLowerVolume has raw key code 123 on my system, XF86AudioRaiseVolume has raw key code 122 and XF86AudioMute has 121.

You need to update .lircrc file to match the values from your system, in case they are different.

The sample .lircrc configuration file from TVTime website is also wrong as it assumes some remote button key names (POWER, 1, 2 …) which do not exist. They are now named KEY_POWER, KEY_1, KEY_2 etc… To find out what remote command button names are used by lirc / irexec, execute irw as described at point c).

TVTime also supports various other commands, to find them all:

$ man tvtime-command
...
BRIGHTNESS_DOWN
Lowers the brightness setting on the input.

BRIGHTNESS_UP
Increases the brightness setting on the input.
....

Thus, if you want to add support for brightness down, just add a new block into .lircrc file:

begin
prog = irexec
button = KEY_RED
config = tvtime-command BRIGHTNESS_DOWN
end

which, when you will press the red key on the remote (it has two black arrows pointing left) it will actually trigger brightness down in TVTime.

e) run irexec at login time

To have irexec executed at login time, just go to System -> Preferences -> Startup Applications and click Add:

irexec at startup / login

irexec at startup / login

Conclusions

This took me some figuring out since there are lots of outdated documentation, configuration files and tutorials out there. If you have any comments, please do not hesitate to post the. The trouble is that given the amount of systems, mappings, versions, etc, it is probably very difficult to make it work as on Windows (where everything worked flawless). Ubuntu still has a lot of catching up to do to bring true multimedia experience without any command line fiddling etc.

But now I have a fully working remote control.

Removing Ubuntu 11.04 Crapware

I am running Ubuntu for the past 3 years, both as hosting environment as well as home …

I want to keep a list of useless things in Ubuntu, as I see them being pushed upon the users creating more issues that solving.

1) AppArmor.

Although security paranoia would make someone reinforce everything in a production environment, on a home environment AppArmor does more bad than good when it comes to Lexmark drivers (or in fact other printer drivers). By default, cupsd daemon is locked by apparmor and thus will fail to load the additional Lexmark binaries. One could use the

sudo aa-complain cupsd

to enable cupsd to run in a more relaxed mode. But this only works until the first reboot. Fixing the configuration file brings no joy, more and more programs needed to be added to the exclusion list, etc.

The only solution ?

apt-get --purge remove apparmor

2) Network Manager

Good idea, poor implementation. It might work with the on what I assume the 2-3 laptops the developers are using to test it, but not with my Belkin USB adapter, which Network Manager fails to connect to Wireless. The adapter works OK, the module complies OK, since stopping Network Manager and configuring with ifup / ifdown works perfect. But Network Manager insists on disconnecting it every 2-3 seconds. Crap.

I thus removed and purged Network Manager and the nm-applet completely and switched to wicd which works perfect and it even has an applet of its own.

3) nouveau

Didn’t read much about nouveau, but I was scared that my videoboard (8800GT with Zalman VT1000 copper cooler) was always at 100% using Unity and thus hovering around 75C. Yes, the board can do 100C safely, but I just don’t feel right with something reaching water boiling temperature inside my PC.

Now this one was trickier. Driver is buggy and doesn’t allow overclocking (or underclocking which was my goal).

If you remove Unity and nouveau, Ubuntu 11.04 doesn’t boot into GUI anymore. You have to start it in a safe graphics mode (I did it using “single” as an argument to the kernel) and then use the Additional Drivers to activate “nvidia-current”. Then, with some “CoolBits” “1″ inside xorg.conf I could tweak the board into Desktop mode.

Section "Device"
	Identifier	"Default Device"
	Option		"Coolbits" "1"
	Option  	"RegistryDwords" "PowerMizerEnable=0x1; PerfLevelSrc=0x2222; PowerMizerDefault=0x3; PowerMizerDefaultAC=0x1"
	Option		"NoLogo"	"True"
EndSection

One thing to notice is that you also need to set the default login session to start without any effects (3D uses more power) and you do this by clicking on the “Power Off” button on the top right corner, select “System settings” and then on the “System” area you will find the “Login Screen” application. There, you need to unlock it and then select “Ubuntu Classic (no effects)”

4) pulseaudio

Unfortunately, I can’t remove this one since it became integrated with the whole system. But it still has issues after years of being live. Don’t know why my Soundblaster Live 5+1 still deactivates the subwoofer (and I always have to reselect the type).

Ubuntu 11.04 Network Manager and Belkin driver.

After compiling the driver for my Belkin addapter:

# lsusb
...
Bus 002 Device 002: ID 050d:935b Belkin Components

I noticed that even if ra0 interface was present, I had to manually

ifdown ra0
ifup ra0

to get it to connect, as the Network Manager applet in Ubuntu 11.04 failed to manage it (it displayed a grayed out wifi signal with an exclamation mark on it).

After searching the Internet, it seems that the only thing to make it was running was to edit the file /etc/NetworkManager/NetworkManager.conf and edit the managed=false to managed=true:

# This file is installed into /etc/NetworkManager, and is loaded by
# NetworkManager by default.  To override, specify: '--config file'
# during NM startup.  This can be done by appending to DAEMON_OPTS in
# the file:
#
# /etc/default/NetworkManager
#

[main]
plugins=ifupdown,keyfile

[ifupdown]
managed=true

Now it is working!

According to the man page here:

managed=false | true
Controls whether interfaces listed in the ‘interfaces’ file are
managed by NetworkManager. If set to true, then interfaces
listed in /etc/network/interfaces are managed by NetworkManager.
If set to false, then any interface listed in
/etc/network/interfaces will be ignored by NetworkManager.
Remember that NetworkManager controls the default route, so
because the interface is ignored, NetworkManager may assign the
default route to some other interface. When the option is
missing, false value is taken as default.

Later update:

Unfortunatelly, Network Manager was not reliable. It kept disconnecting and reconnecting – and I had to get rid of it.

Now I’m using wicd as a network manager replacement.

Lexmark x2650 fix for Ubuntu 11.04

Workaround for Lexmark x2650 not working in Ubuntu:

sudo aa-complain cupsd

Without it, AppArmor will stop the third party cupsd driver (lxm08) to work properly:

Excerpt from /var/log/syslog :

...
Sep  3 13:53:05 adevaraciune kernel: [ 2646.795015] type=1400 audit(1315047185.373:121): apparmor="DENIED" operation="exec" parent=1208 profile="/usr/sbin/cupsd" name="/usr/local/lexmark/lxk08/bin/printdriver" pid=5107 comm="cupsd" requested_mask="x" denied_mask="x" fsuid=7 ouid=0
Sep  3 13:53:05 adevaraciune kernel: [ 2646.795465] type=1400 audit(1315047185.373:122): apparmor="DENIED" operation="exec" parent=1208 profile="/usr/sbin/cupsd" name="/usr/local/lexmark/lxk08/bin/lxkusb" pid=5108 comm="cupsd" requested_mask="x" denied_mask="x" fsuid=7 ouid=0
....

I don’t really like where Ubuntu is heading. The most stable version seemed version 9 with broken pulse audio. Updating to 10 did not fix pulseaudio and printer issues appeared. Ubuntu 11.04 does not fix pulseaudio, does not fix printer, and breaks the UI since now you have to wait one second more for the “dock bar” to appear before doing task switching …

I’m sure there’s someone out there working on its distro thinking “this should not be like Ubuntu”…

Running native CGI scripts (perl) with micro-httpd on Android

Introduction

This article describes the software needed so you can have your native web server running CGI scripts on Android. When I mean native, I mean not an .apk file (Java), but a cross compiled version of a C web server which is able to invoke Perl scripts (a native Perl interpreter is also required).

You need to be root as well as be able to remount the /system partition in read write mode. Busybox is a requirement.

I will not be responsible if anything bad happens if you follow this tutorial. Proceed at your own risk!

Due to the limitations of the low level Android API (and difficulty to cross-compile full blown applications – it is not Linux) not all things will work (lack of perl modules, no database, etc).

However, I was determined to run a blog on my phone (just because I felt it was possible). It is useless from many points of views (since mobile carriers block incoming connections to the phone). But fun!

One of the simplest Perl blogs out there is PPLOG. I’ll use it as a demo of how to setup a CGI webserver / application on Android.

Installation

Installation consists in several steps:

  1. micro-httpd
  2. Perl for Android
  3. CGI.pm module for Perl
  4. setting up the blog

micro-httpd

I have managed to cross compile micro-httpd by ACME Labs.

Grab it from here: mini_httpd_1.19.arm.tar.gz

Licenses of mini_httpd and crypt source code are bundled within the archive. The Android binary itself (as well as the patch to build) is free, license is found within the Cross Compiling section below.

After you copy it to your /sdcard/, execute the following commands to set it up. /system/usr/www will be the folder where the configuration file / log file as well as the doc root will be.

cd /system/xbin
tar xf /sdcard/mini_httpd_1.19.arm.tar.gz
# let's make the folders - and then the configuration file
cd /system/usr
mkdir www
mkdir www/htdocs
mkdir www/htdocs/pplog
vi mini_httpd.conf

For more configuration options, please check here.

The configuration file contents:

nochroot
user=root
port=80
dir=/system/usr/www/htdocs
data_dir=/system/usr/www/htdocs
cgipat=**.pl
logfile=/system/usr/www/mini_httpd.log

Now it’s time to start it up:

mini_httpd -C /system/usr/www/mini_httpd.conf

It will complain that it runs as root – but we can’t run it otherwise anyway.

Perl for Android

Perl for Android is an effort to support Perl scripting on Android, using SL4A. While it is targeted for UI applications (and the SL4A uses it to execute Perl code behind the scenes) and use Android’s services (location, etc) to develop UI applications in Android. However, it does offer a native Perl interpreter which can be invoked standalone from native code.

Grab it from here: http://code.google.com/p/android-scripting/downloads/detail?name=perl_for_android_r1.apk&can=2&q=

This is just the installer. After you install it, click the “Install” button to install the Perl interpreter (it will download a bunch (3) .zip files and unpack them for you).

The version at the moment of writing (r1) will install the Perl interpreter at

/data/data/com.googlecode.perlforandroid/files/perl/perl

This will be the shebang all .pl scripts will need to have so that they can be invoked by the server.

#!/data/data/com.googlecode.perlforandroid/files/perl/perl
use CGI;
$cgi = CGI->new;
...

CGI.pm module

This is an important module that is missing from Perl for Android interpreters. Fortunately, it is Perl only (no need to recompile it) and thus, it can be manually installed on Perl’s library folder.

Grab it from here: http://search.cpan.org/CPAN/authors/id/M/MA/MARKSTOS/CGI.pm-3.55.tar.gz

You need to copy it to your SD Card, and type the commands below:

busybox mount -o remount,rw /system
cd /data/local/tmp
tar xf /sdcard/CGI.pm-3.55.tar.gz
cd CGI.pm-3.55/lib
cp -r * /data/data/com.googlecode.perlforandroid/files/perl/5.10.0/
cd /data/local/tmp
rm -r CGI.pm-3.55

PPLOG

Installing PPLOG is simple. First you have to download it: http://code.google.com/p/pplog/downloads/list (Version 1.1b STABLE)

Steps:

a) Extract the contents of the .rar archive, and upload the content of upload this folder to the /system/usr/www/htdocs/pplog folder.

You now should have a structure like this one:

[root@arc]/system/usr/www# tree
.
|-- htdocs
|   `-- pplog
|       |-- bg.gif
|       |-- getPath.pl
|       |-- header.gif
|       |-- pplog.pl
|       |-- reddit.gif
|       |-- smilies
|       |   |-- Thumbs.db
|       |   |-- cool.gif
|       |   |-- cry.png
|       |   |-- doh.gif
|       |   |-- happy.gif
|       |   |-- n_n.png
|       |   `-- worried.gif
|       |-- style.css
|       `-- update to 1.0
|           `-- update.pl
|-- mini_httpd.conf
`-- mini_httpd.log

Two more things left to do: configure pplog and update the .pl scripts to add the shebang.

To configure, edit the /system/usr/www/htdocs/pplog/pplog.pl file like this (module CGI::Carp is missing, but since it is optional, we can safely comment out the line that requires it):

...
# use CGI::Carp qw/fatalsToBrowser/;      # This is optional
...
our $config_adminPass = 'yourpass';
our $config_smiliesFolder = '/system/usr/www/htdocs/pplog';
our $config_smiliesFolderName = 'smilies';
our $config_postsDatabaseFolder = '/system/usr/www/htdocs/pplog/posts';
our $config_commentsDatabaseFolder = '/system/usr/www/htdocs/pplog/comments';
...

To update the shebang edit the two files getPath.pl and pplog.pl and modify the first line:

#!/data/data/com.googlecode.perlforandroid/files/perl/perl

then make both files executables: since they will be executed as CGI and thus need to be executables. This is also the reason we keep the home folder on the /system folder and not on the SD Card.

chmod 755 *.pl

WE’RE DONE!

Now browse to http://[phone_wifi_ip]/pplog/pplog.pl and enjoy your blog!

Perl CGI on Android

Compiling mini_httpd 1.19 for Android

You need:
a) micro-httpd source code from here: http://www.acme.com/software/mini_httpd/mini_httpd-1.19.tar.gz
b) you need the libcrypt headers / sources (*.h and *.c) from here. Just copy them in the mini_httpd folder.
c) the patch: mini_httpd-1.19.arm.patch

The patch is licensed under BSD License:

Copyright © 2011 by Iulian Virtejanu . All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

You will have to modify the patched Makefile to point to your toolchain / setup and then rebuild mini_httpd with make.

Observations

PHP it is not currently possible. This is because of two reasons:
a) PHP for Android guys do not want to offer a CGI version since SL4A is OK with CLI version.
b) Some PHP software does detect if CGI / CLI and behaves acordingly (writing more headers which are added by default by CGI, but not by CLI), but their latest compilation outputs some “FIXME: ” warnings which are read by the web server – but they are not valid HTML content.

There is another php-cgi alternative that I know about, but apparently it is not stable, so I decided not to try it. It might worth check it out though.

Compile an Android kernel module outside the kernel source tree.

I’ve decided to make a short tutorial and present the way I compile kernel modules (outside the kernel sources).

I’ve built few kernel modules (mainly governors – ineractive and smartass, but also cifs / nls-utf8, etc) and I started receiving private messages asking how I did it.

For kernel modules that come with the kernel itself – cifs / tun for example – they just work if you compile the kernel and activate correct config parameters.
Some other modules (such as the smartass governor that doesn’t come with the kernel) you compile outside the kernel source. However they require changes since kernel does not export the symbols the module needs to use – so you have to know what k_all_syms are needed, grab them from the phone and update the kernel module.

So there will be changes there. However, the main steps are:

a) follow tutorials to get the kernel / android ndk to compile. People seem able to do this.
b) then take the module you want (For example cpufreq_smartass.c from here: http://pastebin.com/rR4QUCrk ) and copy it in a new folder on the disk.
c) create a Makefile like the one below, but with your paths of course:

KERNEL_DIR=/home/viulian/android_platform/kernel-2.1.A.0.435/kernel

obj-m := cpufreq_smartass.o
PWD := $(shell pwd)
default:
        $(MAKE) ARCH=arm CROSS_COMPILE=/home/viulian/android_platform/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules
clean:
        $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean

d) execute make

Of course, the module source code needs to be adjusted as you need to put in the CPU frequencies, and also update the k_all_syms pointers .. But you can retrieve them from /proc/kallsyms on the device itself – just look for the method name, and use the address you see in the log.

If you still can’t get it to compile, try to compile a very basic hello_world kernel module. I used the code below when testing:

#include <linux/module.h>  /* Needed by all modules */
#include <linux/kernel.h>  /* Needed for KERN_ALERT */

MODULE_LICENSE("GPL");
MODULE_AUTHOR("viulian, 2011");
MODULE_DESCRIPTION("Demo module for X10i");

int init_module(void)
{
   printk("<1>Hello world\n");

   // A non 0 return means init_module failed; module can't be loaded.
   return 0;
}

void cleanup_module(void)
{
  printk(KERN_ALERT "Goodbye world 1.\n");
}
[/code]

It is not perfect, but if you manage to insmod and then check dmesg, you will see "Hello world" written there.

One more thing, Linux kernel is fussy about the module versions. Even if nothing is changed between two kernel versions related to what a module needs, is enough a small difference in module's modinfo value to make the kernel to refuse the module.

For this, you need to trick your local kernel and adjust EXTRAVERSION value in kernel's main Makefile to have the exact version of the one on the device:

In X10 stock kernel (GB 2.3.3 release), the kernel version is 2.6.29-00054-g5f01537 visible in phone settings.

This means that the kernel on the phone will only accept modules that are compiled for that exact version. But the kernel version is just a string in the module .ko, so is a string comparison - the module might work perfectly, but is not loaded.
There is luck though, the string value comes from a define in kernel's Makefile, which you can change before you compile!

The Makefile in the kernel you are going to use to build the module will have to include these lines at the top:

1VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 29
EXTRAVERSION = -00054-g5f01537

Other than that, it should work ..

Expect phone reboots and difficulty to debug if stuff goes wrong. Android kernel doesn't come with syslog functionality, kernel printk output is found in /proc/kmsg. Dmesg works, but you can't execute if if phone reboots.
I usually had to keep another adb shell opening with 'cat /proc/kmsg' which showed as much as possible from the module's outputs.

Happy compiling on your risk!

PS: I've posted the same tutorial on XDA's website here: http://forum.xda-developers.com/showthread.php?p=17020258#post17020258

Android native web / httpd server with directory indexer.

Introduction

Having a fully fledged natively built web server on Android is not possible because of issues with fork() and pthread inherent to the slim libc implementation from Google, that is bionic. For more details about these Android’s limitations please start here: http://groups.google.com/group/android-ndk/browse_thread/thread/1dfa066e20175c5a/e4c79372d365f5e3.

I was looking to find a small web server / httpd that did the job that:

  • was single threaded (to avoid issues with threads / forks etc)
  • supported basic file browsing so I could download files just using a web browser

The advantage is that you can share anything from your phone, as long as there’s WiFi available (the other phone doesn’t need to be an Android, anything with WiFi and a browser that can download content).

There are a LOT of basic C httpd servers out there written for demo purposes but they can only serve .html files. With some Google foo, I’ve located one which seemed to do the job, and also came free under BSD License.

Download

webserver-1.1.zip

Archive contents:

  • webserver – Android binary
  • LICENSE – initial BSD License
  • android_port.patch – BSD licensed patch for webserver.c
  • README.txt – description on how to install / compile.

The original webserver.c source code is not included, please download it from the creator’s web site.

Change log

v1.0 – 21 Aug 2011
Initial port to Android
v1.1 – 23 Aug 2011
Added command line options
Added listing of all local IPs (helps a lot to find out the WiFi IP)
Added Basic HTTP authentication for security

Installing

Phone needs to be rooted. Also, since most mobile carriers block incoming traffic, you won’t probably be able to access your phone via GSM/3G data connection, only over WiFi.

You need to unpack the archive, and extract the webserver binary to a directory of your choice. Then:

adb push webserver /sdcard/
adb shell
su
cd /system/bin
cp /sdcard/webserver .
chmod 755 webserver
./webserver -u <username> -p <password> -s <port>

If you still want to access your phone remotely even when connected to GSM/3G data only, a much more advanced configuration is needed: http://hex.ro/wp/blog/administer-your-android-phone-from-internet-root-needed/.
There are other software alternatives to access your phone remotely but they also use 3rd party servers which are maintained by their producers.

Stopping the server

a) open a different terminal
b) ps | grep webserver
c) kill <pid_of_webserver>

Compiling the server

a) you need to have a build system which is able to generate native ARM code. For starting, please check this web site: http://betelco.blogspot.com/2010/01/buildingdebugging-android-native-c.html
b) download webserver.c from here: http://www.jbox.dk/sanos/webserver.htm
c) apply the included patch.
d) build it.

Porting process

The contents of the patch are shown below and discussed afterwards:

5a6,10
> // viulian (http://hex.ro) changes for Android - 21 Aug 2011
> //  * changed headers
> //  * using strcasecmp
> //  * workaround strict dirent wich doesn't have d_namlen on Android
> //  * fixed 2 small bugs (file size showed 0 and a peb reference was not found)
7d11
< #include <os.h>
12a17,20
> #include <sys/socket.h>
> #include <linux/in.h>
> #include <arpa/inet.h> // inet_ntoa
> #include <unistd.h> // close
106c114
<   if (stricmp(method, "GET") != 0)
---
>   if (strcasecmp(method, "GET") != 0)
150c158,159
<           if (de->d_namlen < 32) fprintf(f, "%*s", 32 - de->d_namlen, "");
---
>           int namlen = strlen(de->d_name); // viulian
>           if (namlen < 32) fprintf(f, "%*s", 32 - namlen, "");
155c164
<             fprintf(f, "%s %10d\r\n", timebuf, statbuf.st_size);
---
>             fprintf(f, "%s %10llu\r\n", timebuf, statbuf.st_size);
182c191
<   printf("HTTP server listening on port %d at %s\n", PORT, inet_ntoa(peb->ipaddr));
---
>   printf("HTTP server listening on port %d at %s\n", PORT, inet_ntoa(sin.sin_addr)); 

Porting involves many things, but among them:

  • Header files. If the build process reports an error
    warning: implicit declaration of function 'close'

    then you need to search the includes folders for which header contains the definition, and add that to the source file. For the error above, the file unistd.h had to be imported.

  • Adapt functions / structs. On Android, method stricmp does not exists, you need to use strcasecmp for this. Also, struct dirent is missing the d_namlen memeber, and by checking the documentation, that represented the length of the folder name. Length has to be computed ‘manually’
  • Pay attention to warnings reported by the compilers! In the case above, compiler complained about the size of statbuf.st_size not fitting inside the %10d of the printf method. Adjusting that to %10llu fixed the problem, and size were correctly shown, instead of 0

Improvements

There are two major things that I would like to add in the future:

  1. File upload
  2. Sorting alphabetically and folders first

Happy native Android trips :)

←Older