A GUI for ps(1) Built with Mozilla

Give your command-line tasks a GUI with the Mozilla platform.

One of the more powerful features of Linux is the simple way that new commands can be constructed using aliases, shell scripts and other textual tricks. These techniques rely on a command-line interface, but what if you need a tool with a GUI interface? Few techniques exist that are both easy to use and professional looking. This article discusses a promising technique that uses the Mozilla platform. It focuses on a rather hard but standard problem: how to display the hierarchical information delivered by the ps(1) command usefully. A recent version of Mozilla (at least 1.4) is required.

Numerous GUI toolkits are available for Linux, from Xt to Tcl/Tk. Tutorials for these kits usually start with a button example. That's very routine, so let's see it and move on. In Mozilla, GUIs are described using XML syntax. A document named button.xul that specifies a button looks like this:

<?xml version="1.0"?>
<window xmlns="http://www.mozilla.org/keymaster/
  <button label="Press Me"/>

The unmanageably long string, http://www.mozilla.org/keymaster/gatekeeper/etc..., tells Mozilla this file isn't HTML. It's instead XUL, a GUI description language that is Mozilla-specific and a dialect of XML. Make the button's window appear with this command:

mozilla -chrome button.xul

This example is simple and not worth dwelling on, although there's a lot going on even for a simple button. A ps(1) display is a far more ambitious goal, so let's leap forward.

Instead of the simple <button> widget, one of Mozilla and XUL's bigger guns is required, the <tree> widget. Some coding also is required and a lot more XML. Here, the focus is on fast development, not on seamless perfection. The coding part comes first.

To begin, ps(1) does the initial data gathering. Listing 1 shows the file psdata.ksh, with mode 777.

The output holds all the interesting fields, comma-separated with no header line. Mandatory components are PID and PPID; the rest are optional but informative fields, such as COMMAND. That's all traditional Linux requires.

The rest of the coding depends on Mozilla technology. The standard compiled distributions provide at least two executables, mozilla and regxpcom. Here, a binary named xpcshell is used as well. This binary is Mozilla's JavaScript equivalent of the Perl interpreter; it has no GUI support. xpcshell sometimes is a good starting point for development, but it is never essential. To acquire this binary, a full compilation of Mozilla is required. First, check toolchain requirements against www.mozilla.org/build. Next, grab the source by FTP or remote CVS. A major release rather than a nightly release is recommended. Once unpacked, follow standard compilation steps:

cd mozilla
./configure --disable-debug
make install

Debug versions are slow and have messy diagnostics; although harmless, they're avoided here. The build takes an hour-plus to finish and requires up to 1GB of space. The resulting binaries are located in mozilla/dist/bin. They can be run from that directory or from anywhere if the MOZILLA_FIVE_HOME and LD_LIBRARY_PATH environment variables are set and exported to that directory's absolute path. Now all the required binaries and shell scripts are available.

With Perl, the output of ps(1) needs to be sucked up into a coding environment. In this case, that's a JavaScript interpreter. To do this, you need more than language syntax—you need support for I/O. In Perl, support is built into core language functions. By comparison, JavaScript has no I/O functions. In Mozilla, that I/O support is added using objects. Such objects cannot come from a scripting library, because the core language has no I/O. So, a Perl use or require doesn't work. There are no back-tick operations either, such as echo `pwd`. Instead, Mozilla has XPCOM.

XPCOM is an implementation of Microsoft's COM, and it works portably on Linux/UNIX, Windows and Macintosh. It's restricted to a single process at the moment; there's no DCOM. XPCOM/COM is the fastest way to add new functionality to a scripting environment. It hooks up a compiled (say C or C++) object to an object reference in the scripting language. The nearest Perl equivalent is XM, but XPCOM does not require the re-linking that XM demands. Mozilla includes thousands of XPCOM objects by default. XPCOM is not some Java-like virtual machine at work, however. XPCOM objects usually are compiled code that runs efficiently on the bare metal.

It might seem strange to use Microsoft ideas on Linux, but XPCOM is fully open source and occupies a UNIX niche that has long been unaddressed: Linux/UNIX lacks a useful intermediate-sized component model. There have been CORBA and dynamic link libraries in the past, but those things are, respectively, very heavyweight and very lightweight. XPCOM is suited perfectly to middle-sized jobs, to application development of large binaries and to performance-critical work. Here it's simply extremely handy.

Use of XPCOM or COM typically includes many calls to the Windows QueryInterface() method. For the sake of Linux programmer sensibilities, this article uses createInstance() and getService() instead. QueryInterface() is available too.

Back to the code. Let's suck up the output of the ps(1) wrapper. Listing 2 shows how.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Support material for

Anonymous's picture

I'm the author. I've placed a download containing some notes and minor fixes on the Web to ease the process of experimentation a bit. Get them here.

- Nigel.

Re: A GUI for ps(1) Built with Mozilla

stoneknife's picture

For the most part I liked this article, particularly as I could use some of the theory behind it for a project of my own. I would like to point out, though, that neither the listings nor the text indicate directly what file names the listings might assume. Some of that can be figured out but it would have been nicer to have that available within the text.

When typed in, and also later downloaded from the archive sight, the code from the listings failed to output what is reported in the figures.. at least for the final. I'm no JavaScript programmer by any means but it appears that the initial definition of 'psdata' (listing 2) should not be 'null' but a new something, probably Array, as that has an attribute of 'push' (as used later in the code).

It would also have been nice for the second JavaScript excerpt (listing 7) to have some kind of indication that it should be inserted into the initial JavaScript (listing 2).

Ok... so I learned something in having to dig into the workings to get it working. It was a good start anyway aside from my frustration..

Re: A GUI for ps(1) Built with Mozilla

Anonymous's picture

Notice also that execute_ps has a full path to the executable specified. This has to be changed as well.

After making the recommended changes in the first reply, and the above mentioned change. It crashes in a miserable fashion. No clue what the error means. It appears that certain assumptions were made in navigating the data tree, and these aren't valid across versions of Mozilla.

I really like the potential of XUL and it's got enough excitement here at work, that they're talking about rolling out Mozilla to 1000 PC's if it works as promised. It's a pity that the example in this article can't be made to work simply.

Re: A GUI for ps(1) Built with Mozilla

BArchis's picture

I've been banging my head on this for a few days, and have been able to get it to work with Mozilla built from source, as well as a binary downloaded from mozilla.org. Some thoughts:

1. The package >>must<< be registered as chrome and the .xul file invoked as 'chrome://...' or it won't work: you'll get an empty form because the JavaScript security won't be satisfied. It's probably easier to set up the registration and the .../chrome/psviewer/content directory first and then start building the code inside it.

2. When you build Mozilla from source, you get xpcshell, which allows you to invoke JavaScript files from the command line. It can help in getting the portion of code in Listing 2 working, but will not help with the combined (Listing 2 and Listing 7) JavaScript, because the operating context (i.e. we invoked the JavaScript from an .xul document) is missing.

3. Combining Listings 2 and 7 is a little more involved than simply concatenating them. You want to have all the declarations, followed by all the mainline code, followed by all the functions. (Maybe they don't absolutely have to be in order: I'm not a JavaScript jock. But it's much easier to follow what's happening.)

4. If you'd like, you can put the JavaScript inside the .xul file.

So now I've got it working, almost: if I invoke it as:


(whether from the command line or in the address box)
it works (it even updates if I hit the Refresh button!), but if I invoke it as:


(or point File Open to the .xul file)
I get an empty form.

Why do I say 'almost'? Since I have this cool picture of the running processes on my screen, I'd really like to print it. But when I try to print it, the text disappears from the table, and when I try to do a Print Preview, Mozilla tosses its cookies with a segmentation fault.

Perhaps that's an exercise for another month....