Using Interix
- or -
POSIX under Windows 2k/XP


Introduction

Interix is Microsoft's 'POSIX' (UNIX) subsystem that runs on 'Pro' and 'Server' versions of Windows 2k, XP, or Server 2003. In many ways, it is the 'best of both worlds', allowing you to have a fully functional UNIX shell and environment while running under a Microsoft Windows NT-based operating system. With the Interix system loaded, all of the 'standard' UNIX utilities are available to you, and it includes version 3.3 of the 'gcc' C/C++ compiler. In short, it's like having Linux or *BSD running on your Windows desktop, running as a POSIX sub-system, with 'csh' as the default shell, and 'vi' as the default editor (Windows users, be prepared to learn 'vi' commands. More on this later).

Conveniently, many MS-DOS and NT/2k/XP commands are identical to unix, namely 'cd', 'mkdir', 'rmdir', so the average Windows user that's familiar with 'cmd.exe' or 'command.com' should have no problem using Interix. As an extra added bonus, 'dir' works as you would expect it to under Interx, though within certain limits ('dir' can't resolve symbolic links). So you'll need to learn to use a few obvious UNIX commands, like 'ls', 'rm', 'cp', 'mv', 'ln', 'cat', and (most important) 'man'. Type 'man man' for information on 'man'. It's the UNIX version of the 'help' program that used to ship with MS-DOS.

With the obvious advantages, there are still some compatibility issues that I have discovered, which (interestingly enough) are very correctable. With a little bit of additional effort, you should be able to get your POSIX system running and be able to develop UNIX and Linux software, using the latest GCC compiler and tools, cross-compiling for whatever platform you deem necessary. It should even possible to do this from within Microsoft's visual development environment - with a little creative 'hacking', that is.

At the time of this writing, I'm working on re-building gcc version 3.3 (downloaded from the GNU FTP site as a 'tar.gz' file) such that it functions as a cross-compiler for PalmOS. Not surprisingly, utilities like 'gunzip' and 'tar' do exist under the 'Interix' subsystem, though the 'tar' utility is really a wrapper for an application called 'pax'. So you should get familiar with 'pax' when it's time to untar an archive.
As usual, you can use 'gunzip' to convert a '.tar.gz' file into a '.tar' file. Subsequently, the command line to 'untar' an archive is quite simple:

pax -r -f tarfile.tar
to extract the archive 'tarfile.tar' from within the same directory. Typically, for a tarball named 'tarfile.tar' pax will create a directory 'tarfile' within the current directory, and extract the tarball tree into the new 'tarfile' directory (depending, of course, upon how the tarball itself was created). More on that, later.

Another useful feature is the interaction between the windows file system and the interix directory structure. Interix typically installs to a directory such as 'C:\SFU'. From within this directory is the root structure of the entire POSIX environment (i.e. '/'). For referencing the windows structure from within the POSIX environment, it's slightly more complicated - '/dev/fs/C' references the root directory of drive 'C', and the home directory for a user is typically assigned to something similar to the following:

/dev/fs/C/Documents And Settings/username
where 'username' is the user you logged in as (Administrator, joe, whatever). So there is no problem at all in integrating the file systems, running a windows application from within the POSIX shell, running a POSIX application from within the Windows environment. All of the necessary path translations are done on your behalf. Now, isn't that nice?



Accessing the Windows Network

Conveniently, the '/net' directory is the Interix equivalent of 'Network Neighborhood', only better. Unfortunately, doing an 'ls' of '/net' doesn't seem to give you anything useful, until after you've done an 'ls' of something within '/net'. But doing an 'ls' of a machine name as a sub-directory, or a wildard file name, such as

ls /net/ServerName
gives you a list of all of the SMB shares for the '\\ServerName' machine, as if they were sub-directories, AS WELL AS THE NFS SHARES. And if you specify a wildcard, such as
ls -d /net/*
you'll get a list of machines as though they were sub-directories. Leaving out the '-d' will list the machines and all of their share names. And of course, you can access shares by referencing them with path names such as
ls /net/ServerName/ShareName
and so, unlike *nix systems that run SAMBA, there is no need to mount any devices to access the network, nor is there any need to mount an NFS share either. And now I see a need to offer the same kind of functionality from SAMBA...

However, if you install 'NFS Client', you'll have a few additional applications (some written for win32, some for POSIX) that allow you to do things like mount an NFS share to a drive letter (specifically 'mount.exe' and 'umount.exe'). This way you can access an NFS share from within Win32 applications. It does not seem possible to use something similar to a UNC path for NFS shares, however. So you're apparently stuck with using drive letters from Win32 when accessing NFS shares.



You REALLY Must Fix These Things!

OK, now that I'm done playing MS Sycophant (in its own way, a potential self-referencing acronym like 'GNU') it's time to lay the bad news on you: there are compatibility issues with Interix that really really really need to be corrected.

The first of these issues is the 'make' utility, and the second is the 'grep' utility. The 'make' utility exhibits errors when building certain projects, so replacing it with the latest 'gnu' version is relatively important. And the 'grep' utility that ships with Interix doesn't support all of the standard features you would expect from 'grep', namely '-A' and '-r' functionality. And because of that, it breaks 'configure' if you try to build 'gcc'. None to worry, there is a solution: download 'make' and 'grep' from the GNU site and build them yourself, then rename the original versions as 'oldmake' and 'oldgrep' and you're done. Although I needed to update the 'config.guess' script to do get it to work (the GNU site had a problem a while back and the latest 'config.guess' isn't available - boo!) the modification was straightforward (more on this later) and you can do it yourself. It may even be possible to use the 'config.guess' from 'make' for 'grep' if you download a new enough version of 'make'. Be advised, if you edit any of these files with a Windows application, POSIX (like UNIX) uses instead of to terminate a line, and adding the back in CAN cause trouble. You can open them with Microsoft's Visual Studio environment and it's smart enough to recognize that you are using and not and then preserve this throughout the file, so it's one very nice way to edit these files. Another, of course, is 'vi', but it's "e;not so nice"e; because now you need to learn to use it, and it's not exactly intuitive (but it *IS* a standard). More on this later.

When I downloaded the 'grep' utility (GNU utilities can be found at ftp://ftp.gnu.org/gnu), I copied it into a directory I created for 'local implementation' source (as in UNIX):

/usr/local/src
This directory is a UNIX standard, representing the 'local implementation' source tree. It also causes the output files to be placed into '/usr/local/bin' when you do 'make install'. The 'grep' version I used had a package name grep-2.5.tar.gz, so I copied it into this path under the following name:
/usr/local/src/grep-2.5.tar.gz
Then of course, a series of commands to extract the files (please excuse the review for those who are already familiar, k?)
cd /usr/local/src
gunzip grep-2.5.tar.gz
pax -r -f grep-2.5.tar
and the directory /usr/local/src/grep-2.5 gets created, containing all of the source for grep version 2.5 .

Building a new 'grep' is then relatively straightforward.

cd /usr/local/src/grep-2.5
./configure
make
make install
NOTE: if you receive any build errors, you might want to install the gnu 'make' first... also I had some trouble with the 'config.guess' that was included in the 'grep' source. For now, you too can download an unofficial 'fixed' version HERE, subject to the GPL of course. Or, you can borrow it from another project like 'make'.
Also worthy of mention, on Interix, '/bin' is a synonym for '/usr/bin' via symbolic link. However, '/usr/sbin' exists as a directory, and there is no '/sbin' directory.

Once you've successfully build 'grep', the 'make install' will conveniently place it into the following location:

/usr/local/bin/grep
Because this is typically 'later on' in the path than the Interix utility '/bin/grep', you'll have to either modify your path (recommended), or else rename the Interix version to something else. To modify the path, you can edit '/etc/csh.login' and change the path line to read as follows:
setenv PATH "/usr/local/bin:/bin:/usr/sbin:/opt/gcc.3.3/bin:/usr/contrib/bin:${__x11_dir}/bin:/usr/contrib/win32/bin"
In my opinion, this is the better method. It forces the '/usr/local/bin' versions to run rather than the '/usr/bin' versions whenever you install an updated tool (don't forget to use 'rehash' after you build, so the shell knows which one to use).
Otherwise, if you don't want to modify your path you can execute the following command to rename the original 'grep' as 'oldgrep'.
mv /bin/grep /bin/oldgrep
Once done, you will probably have to type in the command 'rehash' for the current session to recognize that it should run the new 'grep' utility. Then just type 'grep' and test it out, make sure it works, etc.
And, of course, when replacing the 'make' utility, just use a similar process, substituting 'make' (and the appropriate tar.gz file name) where appropriate. The new 'make' will also install itself to the '/usr/local/bin' directory, and you'll need to rename the old 'make' utility from '/bin/make' to '/bin/oldmake'.

Once you have updated 'grep' and 'make', there are a few additional GNU tools that could make your life a lot easier, if you are a software developer. These are:
    m4 UNIX macro processor http://www.gnu.org/software/m4/
    autoconf generate 'configure' scripts http://www.gnu.org/software/autoconf/
    autogen automatic code generation http://www.gnu.org/software/autogen/
    automake automatic make file generation http://www.gnu.org/software/automake/
These tools can help you to create cross-platform portable source files for your software projects. Other tools are available that do the same job, but these particular tools seem to be "e;prominently missing"e; from Interix, while being included in other *nix distributions. You should add them to your Interix installation if you plan on doing any kind of software development under Interix.
Information on building these tools is in a separate section, below.



Building a new GCC

Now that you've updated 'grep' and 'make', you should be able to build 'GCC'. In my case, I downloaded version 3.3 because that version had already been installed. Mixing and matching versions of GCC is sometimes bad (you can experiment with your own system as you like, obviously) so I decided to keep the GCC version 'as-is'. The main reason I re-built it is to allow for cross-compilation, which requires building a new GCC from scratch, THEN configuring it to allow for cross-compiling. Obvious cross-compile options might include Linux, ELF (*BSD), and PalmOS. (for the truly brave, you might even try cross-compiling for OS/X, the latest version of which is derived from the FreeBSD 5.2.1 kernel, which uses ELF executables).

The GCC compiler that comes with Interix is installed in the following directory:

/opt/gcc.3.3
You should back this up before you begin. I copied mine to a directory '/opt/gcc.3.3.backup' using the following command:
cp -r /opt/gcc.3.3 /opt/gcc.3.3.backup
Following this, you can setup up a 'symbolic link' in the '/opt' directory that points to the old compiler as follows:
mv /opt/gcc.3.3 /opt/gcc.3.3.old
ln -s /opt/gcc.3.3.old /opt/gcc.3.3
The first command renames the 'gcc.3.3' directory to 'gcc.3.3.old' (and now you realize that I really have TWO backups of the original - paranoia with respect to backups is never a bad thing). The second command creates a 'symbolic link' that points to the 'old' version of GCC. Once you have built a new 'GCC', you can delete the link and point it to the new one similar to this:
rm /opt/gcc.3.3
ln -s /opt/gcc.3.3.new /opt/gcc.3.3
This moves the symbolic link so that it points to the NEW GCC. In this way, if you experience problems, you can 'switch back and forth' as necessary to restore things back to the way they were when you first installed Interix, should the need arise. But it probably won't.

Configuration of the gcc compiler is NOT a simple thing. After spending some time reading the manual, I came up with a relatively simple script to do this for me. First, to find out how the original GCC was configured, I entered the following command:

gcc -v
The output indicates what all of the options should be. From this, I created the following script 'config.sh':
mkdir /usr/obj
mkdir /usr/obj/gcc
cd /usr/obj/gcc
/opt/gcc-3.3/configure --prefix=/opt/gcc.3.3.new --verbose --disable-shared --with-stabs --enable-nls --with-local-prefix=/opt/gcc.3.3.new --with-gnu-as --with-gnu-ld --enable-threads=posix --disable-cpp i586-pc-interix3
NOTE: the 4th command is a single line of text, containing all of the options displayed by 'gcc -v' on my system.

Following the configuration, of course, is the obgligatory 'make bootstrap' which in my case worked quite well. And then, of course, you configure all of the cross-compilers. Since I was building a cross-compiler using gcc Version 3.3, I was required to use a cross-compiler target of 'm86k-palmos-coff' rather than 'm68k-palmos' (which is what the PalmOS SDK wanted). So a little extra tweeking was in order, either with the PalmOS SDK or by creating some links 'after the fact' for backward compatibility. [I'll fire off some e-mails once I get it all working to let the appropriate people know... last I checked, ports for PalmOS SDK were broken in FreeBSD, possibly because of this.]



M4, Autoconf, Automake, and Autogen

Next in the sequence of events, for a developer, is to get Automake, Autoconf, Autogen, and their related projects up and running. My experience with these is that I had to tweek them slightly to get everything to work, and of course you must build everything in the right order. You should of course make sure that you are using the gnu version of 'make' and 'grep' prior to doing this, and make sure that the 'm4' that you build and install will be the one that is found FIRST in the path.

  1. M4 - specifically m4-1.4.1.tar.gz, web site. This one built without any problems, when extracted clean from the tarball into an appropriate directory in the /usr/local/src tree (like the others). However, if the file dates get changed for some reason (do to copying, for example), you could have trouble. The procedure is the same as outlined for 'grep' in a previous section. You first extract the tarball into a directory /usr/local/src/m4-1.4.1, and within that directory enter "./configure" "make" and "make install".
  2. Autoconf - autoconf-2.59.tar.gz, web site. This one needed a little tweeking to get it to work. Specifically, after being extracted, the following file
        /usr/local/src/autoconf-2.59/tests/autom4e
    needed to be adjusted. The specific line of code is an 'if' statement which read
        if ((MAIL=60; unset MAIL) || exit) ; then
    and should be edited to read as follows
        if ( (MAIL=60; unset MAIL) || exit) ; then
    Following this change, "./configure" "make" and "make install" as with m4, above.
    NOTE: I reported this problem, and the above change reflects the latest cvs for it
  3. Guile - guile-1.6.5.tar.gz, web site. This one also needs some tweeking, specifically the following file:
        /usr/local/src/guile-1.6.5/srfi/srfi-4.c
    on line 340, which I changed from this
        if (len > ((size_t) SIZE_MAX >> uvec_shifts[type]))
    to this
        if (len > ((size_t) SSIZE_MAX >> uvec_shifts[type]))
    and now everything builds and installs fine, using the same procedure as before. It's actually a pre-requisite for autogen so I needed it.
  4. Autogen - autogen-5.6.4.tar.gz, web site. This gave me a little trouble. Changing the 'TMP' and 'TEMP' environment variables to use the POSIX equivalent paths (/dev/fs/...etc....) rather than the windows-style path fixed the problem. You could add these 4 lines to '/etc/csh.login' to do this for you.
    setenv TEMP_ORIG  "$TEMP"
    setenv TMP_ORIG "$TMP"
    setenv TEMP "/dev/fs/"`echo $TEMP | sed s\x\\\\x/xg | sed s/://`
    setenv TMP "/dev/fs/"`echo $TMP | sed s\x\\\\x/xg | sed s/://`
    
    It essentially works by substituting a forward slash for backslashes, removing the first colon, then prepending '/dev/fs/'. It demonstrates a nice generic way to convert a windows path into its Interix equivalent.
  5. Automake - automake-1.8.4.tar.gz, web site. This built just fine without any trouble at all.
  6. Libtool - libtool-1.5.10.tar.gz, web site. If you want to create shared libraries, you'll probably need this. I was able to build and install it on Interix with no problems whatsoever.

Quite obviously newer versions of these packages can be available at any time. The ones I used were downloaded some time ago, except for 'Autogen' and 'Guile'. I had to obtain a newer version of 'Autogen' since the one I downloaded before had too many build errors, and 'Guile' was a dependency for 'Autogen'.



'man' pages on Interix

All of the *nix-based systems that I have seen include an application 'man' that displays 'manual pages'. When you install a new application, you typically install the manual pages along with it. Unfortunately, the Interix man page does not have the 'groff' utility, and so many man pages do not display properly.

There is also another problem: The directories used by Interix (by default) are the 'cat#' directories, and not 'man#' directories. So the directory tree for manual pages looks something like this:

/usr/share/man/cat1
/usr/share/man/cat1w
/usr/share/man/cat2
/usr/share/man/cat3
...
/usr/local/man/cat1
/usr/local/man/cat2
/usr/local/man/cat3
and so on. However, the GNU tools all expect the 'cat#' diretories to be 'man#' directories. Since the autotools want to install a man page to the corresponding 'man#' directories, you should rectify this problem by executing the following commands:
ln -s /usr/local/man/man1 /usr/local/man/cat1
ln -s /usr/local/man/man2 /usr/local/man/cat2
ln -s /usr/local/man/man3 /usr/local/man/cat3
and so forth. Typically only man1 and man3 will be used by things such as the GNU tools, and applications will typically only use 'man1'. Creating these symbolic links will guarantee that new applications will install their man pages in a usable location.

Additionally, you might want to add '/usr/local/man' to your "man path". To do this, you can edit '/etc/csh.local' and add (or modify) the MANPATH assignment as follows:

setenv MANPATH "/usr/local/man:$MANPATH"
Additionally you could modify the MANPATH assignment in /etc/csh.login or /etc/profile
export MANPATH="/usr/local/man:/usr/share/man:${__X11}/man:/usr/X11R5/man"
These assignments cause the 'man' application to FIRST look in the 'local' man directory, and then look in the standard man directories, when searching for man pages.



The CRLF application

I wrote an application called 'crlf' that converts <LF> to <CR><LF>, and vice versa. Since Interix conforms with the *nix standard of terminating lines with a single <LF> character, and Windows editors like 'notepad' choke on that, you may find that you need to convert between these two formats easily.

To install the 'crlf' utility, you must first download the source tarball, and save this file as

/usr/local/src/crlf-1.01.tar.gz
Then, execute the following commands
cd /usr/local/src
gunzip crlf-1.01.tar.gz
pax -r -f crlf-1.01.tar
cd crlf-1.01
./configure
make install
This will install the 'crlf' utility on your computer. For information on usage, you can type 'man crlf' (assuming you made the changes to the '/usr/local/man' directory and your 'MANPATH', as recommended in the previous section).






This Section Reserved for Future Fun Features






Simple 'vi' Commands

The hardest part about 'vi' is learning to use it. To avoid some rather frustrating experiences, I've put together a simple set of command examples.
To run 'vi'
    vi [filename]
where '[filename]' is the optional file that you want to edit.

Once in 'vi', you can navigate using the arrow, page up, and page down keys. Keys like 'home' 'end' and 'delete' may not function as you expect, so don't use them unless you can configure 'vi' ahead of time to use them properly. Instead, you can use the navigation keys documented by entering the following command:
    :viusage
The ':' begins 'command entry' mode, and 'viusage' allows you to see what commands are available to you. ':help' also works, by the way.
To exit 'vi' without saving any changes, use the following command:
    :q!
To exit 'vi' and save your changes, use the following command:
    :wq
- or -
    ZZ (no preceding ':' in this case)
(the ':w' command by itself writes the file, so you can use it to save while you work)

One of the first things you'll probably notice in 'vi' is that when you start typing, weird things happen. This is because you're not in 'insert' mode. Switching in and out of insert mode is relatively easy. While in 'insert' mode, pressing 'enter' will start a new line or insert a linefeed at the cursor. To enter 'insert' mode, press the lower case 'i'. Then you can insert keystrokes at the cursor. Arrow keys still function in this mode, as well as the backspace key (which will delete characters, but not line feeds). To exit from 'insert' mode, press the 'Esc' key once.
To delete the character under the cursor, press the lower case 'x' key.
To 'join' two lines, press the upper case 'J' key. This is the only obvious way to delete a line feed.
To get to the beginning of a line, press the '0' (zero) key.
To delete from the cursor to the end of a line, press the upper case 'D' key. You'll also need to press the upper case 'J' if you want to delete the LF also. So the sequence to delete a line would be '0DJ'
To search for something, press '/' (which enters 'command mode') followed by the text you want to search for, and . Subsequent'/' followed by searches again for the same text as before.

Other keys are documented by entering ':viusage'. Hopefully these 'hints' will get you started with 'vi' without too much trouble. You may find it to be a useful editor, or you may find it cumbersome (as I do), but at least you'll know how to use 'vi', which is a standard on UNIX and Linux systems.



Related web sites

Microsoft Interix' web site (free download)
GNU Software Download FTP site (also available via HTTP)
GCC Official Web Site



Back to S.F.T. Inc. home page
©2004 by Stewart~Frazier Tools, Inc. - all rights reserved
[ H.A.L. is to I.B.M. as V.M.S. is to W.N.T. ]
last updated: 12/08/2004