Friday, December 25, 2009

Writing custom SELinux policy for Apache

I am using Drupal and CakePHP and had issues with file caching because of SELinux.

Here is a simple module which adds a new type to handle that:




Store it in a file named let's say apachewrite.te

Now we declare the file context:



You can store this in apachewrite.fc

Now on to compile,package and install the module:



The final step is to relabel the directories:



You can edit the context file and add or alter the expressions. Just do not forget to increment the version of the module in order to update it using -u with semodule.

Wednesday, December 23, 2009

Creating bmp images for snom 370 phones using php and GD

Here is a function for converting jpeg images to appropriate bmp images for Snom 370.

You can supply a URL and therefore use the function to stream web camera images to a snom.

You can actually use imagecreatefromXXX to convert from other formats as well.


Monday, December 21, 2009

How to create a custom layout type in CakePHP

I have start using cakePHP to create an interface for snom phones supporting the XML minibrowser.

Anyway I wanted to create a separate type for that and keep the xml type for future use. So I decided to create a snom type, with layouts and automatic detection.

1. Create a helper in app/views/helpers/snom.php which extends the core XmlHelper:




2. Create the default layout in app/views/layouts/snom/default.ctp. Mine looks like:



The $snom variable is an instance of the SnomHelper from step 1.

3. Create app/controllers/components/custom_request_handler.php:


4. That's it really. You can start using the new type right away. As said the type will be set automatically according to the user agent but you can force it using extensions; in app/config/routes.php add:


In order to use it in your controller simply load the CustomRequestHandler as:


Then make sure that you have the view set in app/views/viewname/snom/action.ctp

For instance for the previous example you would have to have app/views/example/snom/index.ctp

Friday, October 23, 2009

Replacing multiple hard drives including the one containing boot under linux with LVM.

I had a server with 3 old hard drives 2 IDE and 1 SCSI.

One of the IDE discs had the /boot partition ~200MB. The rest was part of an LVM partition which was a logical volume group along with the rest of the drives. The group had 2 logical volumes, 1 for the root and a 2GB one for swap.

I decided to move everything to one SATA drive. Turns out it was a relatively simple and safe process.

The first thing is to create the boot partition on the new drive. Same size ~200MB. I've used fdisk to do that. Then I've created another partition which spanned across the remaining disk. I had to change its type (use the t command) to 8e which is the LVM type.

Next simply mounted the new boot partition: mount /dev/sdc1 /mnt/newboot
Then copy the old boot to the new boot: cp -afv /boot/* /mnt/newboot

Add the new disc's partition into the volume group:

pvcreate /dev/sda2
vgextend VolGroup00 /dev/sda2

Time to to the lvm transfer now, simply pmove each of the old disks to the old one and then remove them from the group:

pmove /dev/hda2 /dev/sda2
vgreduce VolGroup00 /dev/hda2

pmove /dev/hdb1 /dev/sda2
vgreduce VolGroup00 /dev/hdb1

pmove /dev/hdd1 /dev/sda2
vgreduce VolGroup00 /dev/hdd1

All done, now poweroff and remove old discs.

Boot using a live CD,USB or Super grub and install grub and voila!

Albatron PX865PE Lite (V 2.0) booting from USB

Just a small note, for this motherboard which has a tricky boot sequence selection.

In general if you have multiple boot devices connected on the same option group (e.g. Hard Disk, which includes USB sticks) you must disable all but the one you wish to boot from, boot once and then reboot and enable the rest.

That is the motherboard will choose the last known bootable device.

For instance you may have a SATA bootable drive and an IDE bootable drive. You usually boot from the IDE but now you want to change to the SATA one. Simply disable the IDE drive (set None in BIOS), boot, reboot change the option back (to Auto for instance) and it will now boot from the SATA always.

Weird.

Sunday, October 18, 2009

ddclient hangs while getting IP address under certain circumstances

DDClient is a great dynamic IP updating Perl script which supports many providers and has cool features like grabbing the IP from your modem instead some server in the Internet.

However with the latest version 3.8.0 I have had an issue which led to ddclient blocking while trying to read the response from the modem.

I am not an expert in Perl, however I can code. So I had a look at the source. I've managed to find the problematic calls around line 1800:
my $timeout = 0;
local $SIG{'ALRM'} = sub { $timeout = 1; msg(qq{Alarm!\n});};

$0 = sprintf("%s - reading from %s port %s", $program, $peer, $port);

alarm(opt('timeout')) if opt('timeout') > 0;

while (!$timeout && ($_ = <$sd>)) {
$0 = sprintf("%s - read from %s port %s", $program, $peer, $port);
verbose("RECEIVE:", "%s", define($_, ""));
$reply .= $_ if defined $_;
}
if (opt('timeout') > 0) {
alarm(0);
}

I remembered from my early days in learning Perl that the perldoc was clear: Signal Handling in Perl is different from other languages.

So although in C/C++ you would expect the read to return EINTR when the process was interrupted with a SIG_ALRM that does not happen in Perl (not on all platforms anyway). Yes the signal is caught and the handler is called but the read is not interrupted and therefore the sentinel timeout is never checked.

To make things worse the timeout option in the socket constructor does nothing.

The solution is to force the read to end using an eval/die pair:

$0 = sprintf("%s - reading from %s port %s", $program, $peer,
$port);
eval {
local $SIG{'ALRM'} = sub { die "timeout";};
alarm(opt('timeout')) if opt('timeout') > 0;
while (($_ = <$sd>)) {
$0 = sprintf("%s - read from %s port %s", $program,
$peer, $port);
verbose("RECEIVE:", "%s", define($_, ""));
$reply .= $_ if defined $_;
}
if (opt('timeout') > 0) {
alarm(0);
}
};

close($sd);

# if ($timeout) {
if ($@ and $@ =~ /timeout/) {
warning("TIMEOUT: %s after %s seconds", $to,
opt('timeout'));
$reply = '';
}

The commented line is the original code.
So the code in the eval block runs as if it was a perl program within our program. When the signal is caught we kill the little program with die and execution is returned to the main program after the eval block.

Variable $@ holds the last eval return value so that is how we test if a timeout has occurred.

And now this works! I can finally see the timeout messages in the logs. I suspect that some people may never have a problem with this limitation of ddclient. If ddclient will get a response from the http server even a trashy one then it will not hang. I guess that my modem is buggy and it simply does not return a response but holds the connection open which makes ddclient block.

I have filed a patch with the code changes for ddclient.

Thursday, March 26, 2009

Adobe Air for linux sucks!

Remember how I wanted to set up an openbox/air box for presentations? Well I did on the real machine to end up with the Adobe Air application + X processes having on average 80% cpu usage together!

On top of that the AIR application (was just a Glow effect on an Image really, very basic app) was crashing after a few minutes! Now I've installed firefox & flash plugin, converted the air app back to swf and running the movie with half cpu usage among X and firefox. I really wonder how this is possible, the AIR overhead being greater than firefox overhead. I wasn't expecting that...

*Running the test app using firefox for over 24hrs straight. Stable CPU usage, no crashes. Seems to be the solution at least until gnash fully supports SWF9 or I find a projector for linux or someone suggest something better.

*Update: There is a standalone flash player available from Adobe. CPU usage as in firefox more or less. Half the memory usage though. I still need to find if you can execute it in fullscreen...

Thursday, February 26, 2009

Linux autologin

To achieve automatic login for a use in console mode you can use a feature of mingetty.

For new fedora core edit /etc/event.d/tty1 (used to be in inittab) and change:

exec /sbin/mingetty tty1

to

exec /sbin/mingetty --noclear --autologin username tty1

That will autologin username in runlevel 3 at least.

Runtime linking errors under linux...

You may get errors at some point in linux that a library (usually ending in .so.0) cannot be found. But you may be able to see that is there, in /usr/local/lib for instance.

You just need to include the directory for linking:

ldconfig -n /usr/local/lib

Use ldd to see what libraries are linked by a program and whether they are correctly located or not.

Tuesday, February 24, 2009

OpenBox on Fedora 10

I am running a FC5 box which I use as a presentation player sort of using tv out. I thought that gnome was too 'heavy' for the machine with all the other tasks it had to do at the same time. Also for the presentation, firefox + javascript produced a memory monster with crushing attitude.

So I am thinking of going for a minimal installation of FC10 and install the xorg server and openbox as the window manager (standalone) and adobe AIR runtime.

I have set up this system on a virtual pc* and it does great. OpenBox is really lightweight and minimal. It is also very simple to install it.

Install the xorg-X11 stuff you need, that is server, fonts, xinit...
Make sure all dependencies for compiling OpenBox are installed...

Install some more fonts. Well I skipped all fonts which resulted in OpenBox not able to render any text. No harm though, I have installed some fonts using yum and downloaded all the ttf fonts (located in %WINDOWS%/fonts) from an XP machine to /usr/share/fonts. The ttf fonts are much better. After copying fonts don't forget to run fc-cache -fv to rebuild the font cache.

Compile and install openbox.

To run openbox standalone simply edit your /etc/X11/xinit/Xclients (this I feel is fedora specific, different flavours will have different files you need to edit) to make startx use openbox-session as suggested:

below line with STARTKDE=.... :

OPENBOX="$(which openbox-session 2>/dev/null)"

below line with exec "$STARTKDE" :

elif [ -n "$OPENBOX" ]; then
exec "$OPENBOX"

you may add commands in ~/.config/openbox/austart.sh you wish to run when openbox starts.

run Xorg -configure to get an initial conf file, copy it and adjust it as required.

Now try startx. You should be presented with the absolute minimalistic default background and nothing more! Try right clicking the mouse to access the context menu.

I have installed the AIR runtime which I will use to do the presentation from now on. You just need to install gnome-keyring first however AIR will install nicely with no problems. I have also installed the flash plugin and tried out ebay desktop with success.

To autologin read this and to autostart x use start x in .bash_profile for bash.

I believe openbox is ideal for cases like mine but I can see how a fully customized installation can be very impressive for any use.


* Microsoft Virtual PC 2007 + fedora core 10: You need to push the option vga=791 in order to get a proper display. Add this to /boot/grub/menu.lst next to the kernel row to make it permanent. Remove the quiet parameter. Also for X you need to edit the xorg.conf in /etc/X11 and set the display depth to 16.
Also if you get the "Could not detect stabilization, waiting 10 seconds" boot message update mkinitrd and follow the instructions to rebuild the image.