Command Line Porting
Volume Number: 16
Issue Number: 7
Column Tag: Programming
Porting Command Line Interface Programs to the
by Thurman Gillespy III, M.D.
How To Add a GUI to UNIX Programs with Minimal
Changes to the CLI Source Code
There is a wealth of source code available for the UNIX (and DOS) OS that uses a
command line interface (CLI). Many of these programs have been ported to Windows
but not to the Mac OS. This article describes a method for adding a graphic user
interface (GUI) to a CLI program with minimal changes to the CLI source code.
Why Port?
Why bother to port a UNIX program to the Macintosh? Most likely, there is a specific
program that meets the needs of your workgroup or interest area. However, an
additional benefit I would like to emphasize is the opportunity to "brush up" on parts
of the Mac OS API. Been too lazy to deal with Navigation Services? Never done a code
resource or shared library? Ready to tackle a Carbon compliant app? Porting a CLI
program is an excellent opportunity to hone your skills on a small project that you can
later apply to your own work. And do you tire of hearing that there is "so much more
software available for Windows" than for the Macintosh? Here is one small way you
can alleviate the discrepancy!
The Golden Rule of Porting
I propose a simple "golden rule of porting" to guide your porting project.
ALTER THE SOURCE CODE AS LITTLE AS POSSIBLE
At first, this rule appears paradoxical. Doesn't a port from UNIX to Macintosh involve
substantial code changes? As you will see, a CLI program can have a GUI added with
minimal changes to the original source code. Furthermore, the rule is practical. It's
not your code, so leave it alone! By not altering the CLI code, you make the porting
project easier, you leave the burden of maintaining the CLI program with the original
author and you make it easier to update the Macintosh version of the program when the
CLI code is updated.
Anatomy of a CLI Program
Before getting started, let's briefly review the structure of a CLI program. There are
several key terms to understand: the standard console, the standard input and output,
and how the OS handles the command line arguments.
The Standard Console and the Standard Input and Output
The Standard C Library assumes an interactive input and output environment known as
the standard console. The standard console is typically an interactive computer screen
where users can enter information from the keyboard and view output on the screen.
Many of the C library input and output functions can read from the standard input
(input entered into the standard console, also known as stdin) and can write to the
standard output (output displayed on the standard console screen, also known as
stdout). The standard input and output are collectively referred to as the stdio.
Functions that read and write to the stdio include printf, scanf, getchar, putchar and
the C++ inserter and extractor operators << and >>. Of course, the C library can read
and write to other data streams including files and network connections.
For example, printf writes to the standard output. This code snippet
printf("Hello, world!\n");
will print the words "Hello, world!" (without the quotes) and a newline on the
standard console (see Figure 6, below).
The Command Line Interface
CLI programs have a main function with the following prototype:
int main(int argc, char *argv[]);
The compiled CLI program is invoked from the standard console by typing the program
name and adding optional parameters after the name which are known as the command
line arguments. The arguments are processed by the OS and are passed to the main
function as the argc and argv parameters. argc is the number of parameters passed to
the application (plus one) and argv is a vector that points to an array of C strings. By
convention, argv is structured as follows:
Listing 1. The argv vector
argv[0] ==> program name
argv[1] ==> first parameter
argv[argc - 1] ==> last parameter
argv[argc] ==> NULL pointer
Every command line argument separated by white space is parsed into a separate argv
string. For example, here is how the command line arguments for a program named
midi2abc are translated into argc and argv.
Listing 2. Converting command line arguments to argc and argv
// invoking the program from the console
midi2abc -f mytune.midi -a 2
// argc and argv
argc = 5
argv[0] ==> "midi2abc
argv[1] ==> "-f
argv[2] ==> "mytune.midi
argv[3] ==> "-a
argv[4] ==> "2
argv[5] ==> NULL
Project Overview
To port the CLI code with as few changes as possible, we want our project separated
into two components: a Macintosh GUI "front end" program that passes the argc and
argv parameters to a separate component that contains the CLI code. We accomplish
this separation by compiling the CLI code as a code resource or shared library that is
called by the Macintosh GUI program. In addition, we need glue code to handle the C
standard library functions that read and write to the stdio. A diagram of the technique
is shown in Figure 1.
Figure 1. Porting overview
This porting method will work best on UNIX programs with well defined input and
output that are typically invoked from the command line.
Define the Objectives
After you've identified the code to be ported, sketch out your objectives before getting
started. Here are some points you should consider.
• What is the purpose of the ported program?