Wednesday, April 21, 2010

IcedTea Java Console: How to debug Java Applets on Unix / Linux based systems

If you've ever used the IcedTea Java plugin, you may have noticed that it does not have a console like it's Windows based cousin.

How do you debug or see the Java output without a console? The answer is very simple: If you are using IcedTea it's because you are running a Unix / Linux based system. You have built-in consoles all around you!

THE QUICK SOLUTION: (for the impatient)

Before running your applet in a browser, open a terminal window and type:

$ watch -n 1 'cat $HOME/.icedteaplugin/java.stdout'

Now run your applet and see the output fill up the screen.

THE FULL EXPLANATION:

Open a terminal and go to your icedteaplugin personal settings folder. It should be named .icedteaplugin in your $HOME directory:

$ cd $HOME/.icedteaplugin

Do a directory listing and you will see a few files and a directory.

$ ls

cache
java.stdout
java.stderr


cache is the directory which contains java applets that have been accessed before. If you ever debug an applet you will know that sometimes it's useful to 'clear' the cache. You can individually remove the cached applet that you are debugging, to force IcedTea to download the latest version, by deleting the file.

java.stdout contains standard output from a running java applet, or if none is running it may contain data from the last running applet.

java.stderr contains standard error output.

Now that you know where all the data is, how can you see the output in real time?

Well, you can. At least you can see the output in near real time by using the useful Unix/Linux watch and cat commands.

If you are already in your $HOME/.icedteaplugin directory, type:

$ watch -n 1 'cat ./java.stdout'

If you open another terminal window, type:

$ watch -n 1 'cat $HOME/.icedteaplugin/java.stderr'

Use man watch and man cat for all the optional parameters, but note that the -n option for watch specifies the update rate in seconds.

Tuesday, February 2, 2010

Truncate in C# and C++

The Problem:  A colleague and I were working on a problem in .NET when trying to truncate a number.  The Math.Truncate method would cut off any digits beyond the decimal point without having the ability to specify the precision.

We needed a function that would truncate at various precision levels.

The Solution:  Our solution was to first multiply the number to truncate by the proper tens, hundreds, or thousands of the precision, use Math.Truncate and finally divide by the same to get our decimal position.

C# Code:
public static decimal Truncate(decimal num, int pos)
{
    int64 lDecimalPosition = 1;
    decimal tmp = 0;

    for (int i=0; i
    {
        lDecimalPosition *= 10;
    }
    
    // multiply by 10, 100, 1000, etc...
    tmp = num * lDecimalPosition;
    tmp = Math.Truncate(tmp);
    // divide by 10, 100, 1000, etc...
    tmp = tmp / lDecimalPosition;

    return tmp;
}

Next I tried to convert this to C++ as an experiment.  C++ does not have a Math.Truncate method so I needed to rely on implicit conversion.

The Bug:  C++ does not define the maximum values for types; they are defined by the compiler vendor and platform.  It is not possible to be certain that a large value using a double will not be truncated too short when it is implicitly converted to long long int.  As a matter of fact long long int is currently only supported by C++0x. (see the below function)

C++ Code:
double truncate(double z, int decimal)
{
    unsigned long lDecimalPosition = 1;
    unsigned long tmp = 0;
    long long int llMax = numeric_limits::max();
    
    for (int i=0; i<decimal; i++)
    {
        lDecimalPosition *= 10;
    }
    if (llMax < (z * lDecimalPosition) )
    {
        throw 10;
    }
    tmp = z * lDecimalPosition;

    /* explicit conversion to double to prevent 
    truncate after the division, otherwise 
    value would be truncated to long long int 
    automatically once the division has been 
    calculated. */
    z = (double) tmp / lDecimalPosition;
    return z;
}

WARNING: This code will function only with the simplest of double values passed in.  Since the type "Double" is stored as a floating point value there will be precision loss at some point.

A simple program demonstrates this:
#include <cstdlib>
#include <iostream>
#include <iomanip>
using namespace std;

int main(int argc, char** argv) {
    cout << setprecision(17);     
    cout << "1.1 as a double " << (double) 1.1 << endl;    
    return (EXIT_SUCCESS);
}

output:

1.1 as a double 1.1000000000000001

Ouch!

Wednesday, January 20, 2010

January's Warm Weather - Vancouver, B.C.

I don't remember such mild temperatures in January.  Although Vancouver has a typical coastal climate, these past few weeks I've seen flowers blooming, trees burgeoning, and mosquitoes flying about.

Environment Canada recorded a maximum temperature of 10.3C on January 17th, the day I took this shot.  The warmest was on the 19th at 14.1C.


Historical weather is available for January 2010 from the EC website.

Friday, January 15, 2010

WakeOnLan ported to C#

Paul Mutton wrote a great article on how to use Wake-On-Lan which includes a tutorial on how to create a Magic Packet sender in Java.  He even provides the source of his java implementation: http://www.jibble.org/wake-on-lan/

I took the liberty of converting it to C# with a few minor modifications.  It allows a user to specify a Port number manually.

WHY C#?  Well why not?  I'm using C# at work so it comes naturally.  Mono gives me the ability to run code on both Windows and Linux.  Yes, so does Java.  There are a variety of tools out there and I like to familiarize myself with a good number of them.  In this spirit, I am currently writing a small connection testing tool in Java using Swing.  Maybe I'll write another port of Wake-On-LAN in C++ for fun.

Here is the C# code below:


using System;
using System.Net;
using System.Net.Sockets;

namespace WakeOnLan
{
    class Program
    {       
        static void Main(string[] args)
        {
            string macAdd = "";
            string ip = "";
            string port = "9";
            int iPort = 0;

            if (args.Length < 2) {
                System.Console.WriteLine("Usage: wakeonlan <broadcast-ip> <mac-address> [<port>]");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00:0D:61:08:22:4A");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00-0D-61-08-22-4A");
                System.Environment.Exit(1);
            }

            ip = args[0];
            macAdd = args[1];
            if (args.Length > 2)           
                port = args[2];

            if (!IsNumeric(port))
            {
                System.Console.WriteLine("Port entered was not a number...");
                return; // quit
            }                     

            iPort = Int32.Parse(port);

            if (iPort > 65535 || iPort < 0)
            {
                System.Console.WriteLine("Port value is invalid");
                return;
            }

            byte[] mac = getMacBytes(macAdd);
            //byte[] mac = new byte[] { 0x00, 0x0F, 0x1F, 0x20, 0x2D, 0x35 };
            WakeUp(mac, iPort, ip);
        }

        ///
        /// Check whether string can be converted to a number value
        ///
        private static bool IsNumeric(string num)
        {
            try
            {
                double d = Double.Parse(num);
                return true;
            }
            catch
            {
                return false;
            }
        }

        ///
        /// Sends a Wake-On-Lan packet to the specified MAC address.
        ///
        private static void WakeUp(byte[] mac, Int32 iPort, string myIP)
        {
            //
            // WOL packet is sent over UDP 255.255.255.0:40000.
            //
            UdpClient client = new UdpClient();
            client.Connect(myIP, iPort);

            //
            // WOL packet contains a 6-bytes trailer and 16 times a 6-bytes sequence 
            // containing the MAC address.
            byte[] packet = new byte[17 * 6];

            //
            // Trailer of 6 times 0xFF.
            //
            for (int i = 0; i < 6; i++)
                packet[i] = 0xFF;

            //
            // Body of magic packet contains 16 times the MAC address.
            //
            for (int i = 1; i <= 16; i++)
                for (int j = 0; j < 6; j++)
                    packet[i * 6 + j] = mac[j];

            //
            // Submit WOL packet.
            //
            client.Send(packet, packet.Length);
            System.Console.WriteLine("Wake-on-LAN packet sent.");
        }
   
        private static byte[] getMacBytes(String macStr)
        {
            byte[] bytes = new byte[6];
            string[] hex = macStr.Split(new Char[] { ':', '-' });
            if (hex.Length != 6) {
                throw new ArgumentException("Invalid MAC address.");
            }
            try {
                for (int i = 0; i < 6; i++) {
                    Int32 intVal = Int32.Parse(hex[i], System.Globalization.NumberStyles.AllowHexSpecifier);
                    bytes[i] = (byte)intVal;
                }
            }
            catch (FormatException e) {
                throw new ArgumentException("Invalid hex digit in MAC address.");
            }
            return bytes;
        }
    }
}

Thursday, January 14, 2010

Enabling Wake On Lan on Fedora 16

April 18, 2012: Update - Many users are asking on various forums about WOL on Fedora 16.  My current Operating System is now Fedora 16 and the instructions below are perfectly functional.

Here are simple instructions to setup Wake On Lan on Fedora 14 and above or other versions of linux in general.

Wake-on-lan is a useful tool, but there are tricks to getting it to work correctly under Fedora. Enabling wake-on-lan manually on the network card does not suffice to allow my computer to be awaken remotely. (Lazy computer).

First check the current settings:

# ethtool eth0
Settings for eth0:
    ...
    Supports Wake-on: g
    Wake-on: d
    ...

'd' means wake-on-lan is currently disabled.

I can enable it manually by running the following command:

# ethtool -s eth0 wol g

Unfortunately a snag occurs during the shutdown process; wake-on-lan is disabled automatically.

In order to keep it active after shutdown I must create and use the following script: /etc/init.d/wol.sh

#!/bin/sh
# chkconfig: 0123456 55 10
ethtool -s eth0 wol g

Add execute permission to the file

# chmod +x /etc/init.d/wol.sh

Finally, add the script to my services configuration:

# chkconfig --add /etc/init.d/wol.sh

This allows wake-on-lan to remain active during the shutdown process.

NOTE: Verify the chkconfig priority settings as well as the runlevels that the script runs under as they may be slightly incorrect.

I would very much like to know if anyone can provide improvements to this solution, or even an alternate solution.

First post marks a milestone

As this is the first post, I would like to take this opportunity to welcome you to my blog.

The title provides a good summary of what this blog is about.

I hope you will find some topics are of interest or good use. As a side note, this blog will help me track solutions to various problems I face while administering my Linux system and it's installed software packages.

A little background about me:

- I am a .NET programmer by trade.
- I have a keen interest in C++ programming.
- My system is currently running Fedora 11 with KDE 4.3.
- I run Windows Vista Business Edition through Sun's VirtualBox.
- I am an amateur photographer.
- My camera is the Canon Digital Rebel ( reviewed here: http://www.dpreview.com/reviews/canoneos300d/ )