OS/2 port of pdksh version 5 June, 1996 Introduction This document is intended to define the specific features and differences in the os/2 port of pdksh. For general features and descriptions of pdksh itself please refer to the standard pdksh README or the man page. In general the port has tried to maintain as many of the standard ksh features as possible. For installation details and an introduction to ksh please read the README.1st file shipped in the run time zip package for os2. A default build of pdksh, called ksh.exe, is included in the os2 run time package. This version was built using the emx environment and therefore requires that an emx run time package 0.9b or later be installed on the system. This is not normally a problem since you probably already installed it for 'ls' and other Unix commands from the file gnufutil.zip. (If you haven't install gnufutil.zip you may want to consider it.) Building KSH.EXE If you would rather build your own, you should obtain the sources from ftp.cs.mun.ca in the directory pub/pdksh. You will need a copy of tar and gunzip to unload the archive and install on an hpfs partition. Change to the source directory and run the script os2\configure.cmd. (If you prefer you can copy configure.cmd to the source directory.) This will prepare the build environment so that your version of make can be used to build the executable. Note that configure.cmd is still under construction and you may need to make changes to the Makefile and to config.h to match your specific needs. Copies of all of these files will be placed into the source directory. In addition you may want to make changes to config.h to define your particular preferences. Configure.cmd for os2 support these optional options and arguments: /h | /? | -h Print a usage message and exit. /v | -v Print verbose output during configure /d | -d build a debug version with symbols (for gcc) sh build sh rather than ksh Any configuration other that the default requires that sed be in your search path. You should always get a copy of the latest pre-built version of ksh as well since the file os2bugs may contain some last minute fixes that were too late to include in the formal release, and you may find some other updates. In addition the run time version supplies a couple of sample icons for use with ksh. At this point you can use your favorite make command to build the executable. Pdksh is known to work with nmake and dmake, gnu make requires at least version 3.7.3 and is the only one that will automatically make the man page. You can manually run mkman after starting your new copy of ksh, 'ksh mkman ksh|sh ksh.man'. (A prebuilt sh and expanded cat version of ksh.1 is included in the rt package.) There is a built in check routine that is part of the makefile. Type 'make check' to run it. This routine needs a copy of perl on your machine in order to support the test harness used to test the build. I have built the infrastructure into the port to support this checking but have not been able to get it all to run correctly yet. The problem is because of a bug in the os2 port of ksh. To check the build without using perl, run the command: 'ksh Bugs ksh'. This will use the older checking facility. You should run this if you make any changes to the source to insure that you haven't broken something crucial. Run make check on an unmodified version first so that you will know what to expect. If you want to get the perl version running please contact me for information. KSH 5 VERSUS KSH 4.9 The KSH version 5 effort is being spearheaded by Michael Rendell. Michael took over the effort from Simon J. Gerraty who maintained the version 4 code. While the version 4 code was a good implementation of ksh version 5 strives to continue the conformance to the actual posix definitions and to AT&T ksh. For my version 5 port to os/2, I originally started with the 4.9 os/2 changes and applied them to the new version. Subsequently many changes have been made so that there is little resemblance to that version. One of my goals for version 5 is to make ksh not only and interactive shell, but one that can run some limited Unix(tm) shell scripts as well. Generally the two shells behave the same. Version 5 has no logout script (This can be set up using a trap in your profile.ksh file if desired.) and the option 'hashall' has been replaced with 'trackall'. (To see all of the options use the command 'set -o'.) In addition the prompt has been changed to conform with the at&t ksh shell instead of the csh like implemetation of version 4. The '!' sign is used for the history number and $variable substitutions can be used in the prompt. The commands generally behave more consistently. For example bind now goes to standard out so it can be redirected or piped. Arrays are now implemented as are almost all AT&T ksh features plus a few more. The os/2 port provides file name completion that is not case sensitive. The startup file kshrc.ksh is still supported, but the way it works is slightly different. OS2 IMPLEMENTATION VS. UNIX The original OS/2 port was done by Kai Uwe Rommel. I have re-implemented his ideas in this os/2 version. The os/2 version of ksh has been modified to accept the standard os/2 conventions. Drive designations a:, etc., are accepted and path separators in variables have been changed to ';'. In addition either '/' or '\' can be used as a directory separator. The bind command in emacs mode has been enhanced to accept function key and alt key bindings. (To see what the alt key binding should be, use ^Q followed by the key you are interested in. Replace the ^ alpha you see with ^0, typed as two characters, in the bind command.) The cursor keys have been implemented for command history for both emacs mode and vi insert mode. Standard default stty settings are implemented for both modes as well. A os2 only print option, -f, can be used to force forward slashes in its argument. This can be used to switch a variable containing '\' to output '/' in a pipe to a unix command that doesn't like '\' as a path separator, such as sed. / vs. \ processing The remapping of certain keys can lead to some confusion for Unix and OS/2 users. The '\' key has a different meaning in Unix where it is used to escape a special meaning for the character following it or in the case of the echo (typeset) command it provides special meanings to certain characters. At the end of a line the '\' is used to escape the line feed permitting a command to extend to multiple lines. In OS/2 this key is generally the directory name separator. To provide for both functions in the OS/2 pdksh the '\' is defined to be a directory separator in any pathname specification and will keep its escape meaning when it is followed by any non-alphanumeric character. The echo command retains its special interpretation of '\' and will, for example, interpret \t as a tab when printing. This can be disconcerting when you echo the variable that you just set to c:\tmp. If you want to use echo on a variable with pathnames in it you should either use uppercase names or a '/' as a separator. Another choice is to alias echo to 'print -r' or perhaps 'echo -E'. This will disable the special interpretaions. You could even use the new 'print -f' to force any '\' to switch to '/', but this is less portable. If you have loaded the printenv command it can be used to look at variables. Unix uses '/' as a directory separator and the OS/2 implementation permits and in some cases prefers this use as well. Generally you can freely mix '/' and '\' characters in a pathname. However, 'cd \' will not complete since '\' will escape the new line command and you will get the secondary prompt. Just enter a / and the command will complete. For many standard os/2 commands the '/' is used to indicate an option and may want a '\' as a path separator. These will still work and be correctly interpreted with pdksh as long as a '/' is not attached directly to the command name. Just be sure and enter the syntax needed by the command you are trying to execute. While backslash processing is usually correct and automatic there are times when it doesn't do what you might expect. For example ls \tmp\*.exe might surprise you. In this case the '\' will be interpreted as an escape for the '*' character. You may need quotes or several backslashes to get what you want. Beginning with 5.2.4 the output of ksh favors '/' for any generated pathnames. This is intended to make script processing for unix scripts easier. Unfortunately, this may make interactive use for os2 users that prefer the '\' key a little less desirable. Should you prefer the earlier convention then you can rebuild the executable from the sources. Only one change in sh.h, DIRSEP, controls this behavior. ; vs. : processing Another conflict is the use of ':' and ';'. Unix uses ':' to separate entries in variable assignment and ';' to indicate multiple commands on the same line. OS/2 uses the ';' to separate entries in a variable. This could lead to problems when making an assignment to a variable in pdksh. You will need to escape the ';' in OS/2 to prevent the shell from interpreting it as the end of the command. Either surround the assignment command with quotes or use '\;'. Note that since a ';' is not a valid filename or pathname character the '\' will be correctly interpreted as an escape character. Since having to escape the ';' character can be a pain when changing environmental variables containing a list of paths there are some functions defined in the sample kshrc.ksh file to ease this task. There are three functions; add_path, pre_path, and del_path that can be used to append a path, prepend a path or delete a path from any environmental variable (PATH by default). If you needed to add a path to /emx/bin you might do "add_path e:\emx\bin" for example, or perhaps "add_path e:\emx\book BOOKSHELF" to add some books to the bookshelf. Note that you will need a copy of sed in your search path to use the del_path function. In OS/2 the ':' is used to separate the drive letter from the rest of the pathname. This usage had been preserved in pdksh. You can imbed the drive letter as needed in pathnames. In addition pdksh preserves the notion of separate contexts for each drive. To change drives you would use the cd command. "cd A:/" would change to the root on drive A while "cd C:." would change to whatever was current context on drive C. Some aliases are defined in the sample kshrc.ksh to permit the usual A: to automatically do a change directory to the A drive. Wildcard Processing OS/2 and pdksh have similar notions about wildcard characters '*' and '?' except that pdksh handles the expansion of these wildcard within the shell and then passes the answer as a list to the application. If the application needs to see the wildcard character then you must escape it from the shell. Note that pdksh knows about other wildcard techniques as well. Please see the man page. Background Processing Do to some limitations in the os2 fork process and other differences between os2 and unix it is not possible to support back-grounding from pdksh of commands that begin a new window. For this reason I have automatically backgrounded all such tasks when they are started. This will permit the os2 ksh to serve as a command line launch mechanism for dos, full screen, and pm applications. (Note that currently ksh can only launch an application of the same type (windowed, or fullscreen) that ksh itself is unless you use the 'start' alias. There is a 'start' alias defined in the sample kshrc.ksh file that can be used to start normal command line commands in a new window. For example you could say "start ksh" to start a copy of ksh itself in a new window. Since it is a new window it will automatically return control to the existing copy of ksh. Note that the start alias uses the os2 start command so you could supply it with any standard start option such as /FS to force a full screen copy. Please check your os2 command reference manual for further information on start. PDKSH, OS/2 and the ENVIRONMENT. The environment in OS/2 and Unix are quite different. For one thing you don't actually login to your machine in OS/2 and your initial environment is established by your CONFIG.SYS file. The Shell will use the variables that were set in CONFIG.SYS and you should really consider assigning TMPDIR and HOME for use by pdksh. It will also use ENV as a variable that names a startup file that will run each time the shell is started, even if a script is started. This start up file is located in your home directory. For compatability with 4.9 this shell will also automatically use a startup shell kshrc.ksh if it finds one in your home directory, is started interactively, and $ENV is not set. The variable OS2_SHELL should point to cmd.exe or a fully compatible version and will be used as the shell of choice for any scripts that you write that do not contain the #! or extproc information in the top line of the script. If you prefer you can set the variable EXECSHELL to a shell to be used instead of OS2_SHELL. The use of OS2_SHELL assumes that the shell requires the /c option and that the shell needs all pathnames separated with '\'. Setting EXECSHELL will disable both of these assumptions. A special feature is the support of the -l, login option. If this option is entered when starting ksh then the shell will execute a loginfile called profile.ksh if located in $INIT/etc, c:/usr/etc, or your home. If you are using this shell as your primary shell you may wish to change the settings in your os2 command shell notebook to call ksh.exe -l. I would not recommend changing the default shell in config.sys. Should you destroy your PATH variable try 'unset PATH'. A default path may get you going again. In addition pdksh for OS/2 always uses commands from current context first in the search path even if it is not explicitly set. By default c: drive is used when no variables are set. Specifically c:/usr/bin and c:/usr/etc can be used as defaults various places in ksh. If you build your own version then this can be changed. Generally all of the environmental variables described in the man page will work in OS2 so long as the tools in use understand them in the same way as Unix would. Using KSH The shell itself can be called any name you wish. Good names include pdksh.exe, ksh.exe, sh.exe. You can build two completely different shells using the options file. A full blown Korn shell can be built or a complete subset that behaves very much like a Bourne shell. The smaller version is excellent for script support. In the run time release I have provided the full shell under the name ksh.exe and the smaller version under the name sh.exe. Be careful with names like rksh.exe or you could end up with a restricted shell that can't do everything. In Unix an executable can be tagged with an attribute to make it known to the system as an executable. In OS/2 this is done with an extension. This shell knows all of the standard OS/2 extensions plus .ksh and .sh. (Yes it can run dos commands and OS/2 command files as well.) The .ksh or .sh extension tells the shell that this is an executable shell script. The current version will also treat a file without an extension as an executable in the style of Unix. Scripts need not necessarily be a ksh shell scripts however. The standard Unix #! line at the top of the file determines the actual shell that will be used to run the script. A feature in this release is that any Unix absolute pathnames will be tried and, if they fail a second try will be made by stripping the path from the #! line since Unix style paths are unlikely to match os2 usage. Your standard PATH search path will be used. Should the same filename with a different extension exist in the same directory pdksh will use the extension typed in by the user or if no extension is entered then the search order is, .ksh, .exe, no extension, .sh, .cmd, .com, .bat. This search order permits ksh scripts to be used to modify binary executable behavior while allowing the -Zexe option for emx gcc. . Note that if you explicitly type the extension yourself then any extension can be used so long as the #! processing line is at the top of the file to let pdksh know what to do. The sample kshrc.ksh file that comes with the distribution can be used as an example that shows you how to create aliases that will simulate the standard OS/2 commands. This means you can still use copy, dir, and del if you want to. Keyboard bindings supplied will still provide the command stack and suddenly you also have command line completion and alias capability. To get the most from the shell you will probably want the set of Unix commands developed by the Gnu team and ported to os2. You will most certainly need them or a similar set if you want to run any Unix scripts. A few functions are also provided in the sample kshrc.ksh file to demonstrate the power of functions and to ease common tasks. Unix file systems are case sensitive and ksh generally expects this also. This means that internal commands as well as aliases are case sensitive. You can use this to your advantage. For example you might want to run a dos shell only to find out that 'command' is captured as an internal command by ksh. Try 'COMMAND' or even 'Command' and you will get what you wanted. The file name completion and wild card expansion has been modified for os2 to permit it to ignore case. Working with Editing Modes As delivered ksh for os2 supports three different editing modes to use with the command line. By default the editing mode is the same as that used in cmd.exe in that F1, F2, and F3 can be used to edit the previous command. Left and right cursor keys can also be used to edit the command. Support for this comes directly from the emx layer. The history mechanism is supported in this mode but you will not be able to scroll trhough history from the command line. Pdksh commands exist to display and edit history and the EDITOR environmental variable can be set to specify the editor you want. Two other mutually exclusive editing modes exist as well. The sample kshrc.ksh file turns on emacs editing mode. In this mode pdksh emulates the commands and keyboard binding present in emacs. The keyboard binding is fully customizable by the user using the bind command. For os2 the default build includes support of the cursor keys to edit both current and previous commands. The sample kshrc.ksh file includes some further mapping as examples of keyboard binding. The bind -m command can be used to define special macro commands. Note that in emacs the ESC key following by a letter key is usually synonymous with holding down the ALT key and pressing a letter key. In the current os2 implementation these keys are not tied together so they could be programmed independantly although this could be confusing for the user. This may change in the future. Issuing the command 'set -o vi' turns on vi mode. This mode emulates the keyboard binding from the vi editor. In addition using the tab key for command line completion is separately programmable using the set command. For os2 the cursor keys are also set up to work from within insert mode to allow editing of both the current and previous commands without ever leaving insert mode. The Esc Shft-A sequence can be used to jump to the end of the line allowing you to append new information to the line. CTRL-X, CTRL-E and CTRL-F permit command line completion within insert mode. Thus you can use vi mode without ever having to learn traditional vi commands. SHELL SCRIPT PROGRAMMING One of my goals in porting this shell was to be able to do shell level script programming and to run Unix shell scripts with minimal modification. The first goal is easy and fully functional in this release. You can write shell scripts for this or other shells. The name of the shell you want to run the script is entered in the first line of the script itself after a '#!' sequence. If you only enter the name of the command then pdksh will use your search path to find the shell. This is the recommended approach, however absolute paths of the form /bin/ etc. will be stripped automatically if needed to permit running Unix scripts unmodified. To write portable scripts use the 'uname' command from Gnu to set a variable that can be checked for specialized approaches. As a special case absoulte paths using '\' will not be stripped and an error will be generated if the command is not found at the exact path specified. It is even possible to use ksh as a scripting language when your main shell is a standard OS/2 shell. To do this you would write your ksh script as usual except that the first line in the script should read 'extproc ksh'. The script should be named with a '.cmd' extension so that the OS/2 shell can find it. When the cmd.exe finds this line in the file it will call ksh to process the script for you. A script that is written this way can also be called directly from ksh. As a matter of fact you could use this technique entirely for script creation and name all your scripts with the .cmd extension. Pdksh will honor 'extproc' exactly like the standard Unix '#!' processing. Unlike Unix #! processing the OS2 cmd processing of an extproc header line only passes the file name to the spawned process instead of the full pathname. This is a bug in os2 IMHO since if you explicitely want a certain path for the command you cannot guarantee it. The workaround was to put the path in the extproc line and then shift the extra filename off the argument list. For example my whatis.cmd file used to start like this. extproc ksh c:/usr/bin/whatis.cmd shift You can still do this, but ksh will also search the path to find a copy of the command, so this is no longer required. Of course, the copy that ksh finds might not be the one you wanted but at least you can copy your cmd files around without having to modify them. A side effect of this change is that typing: "ksh whatis" will now search your path as well which does change the standard behavior of ksh which some might construe as a feature! The second goal of running Unix scripts with little or no modification is much more difficult to achieve. Unix makes many assumptions about how the system is set up which makes fully portable scripts difficult to accomplish without the knowledge of the script internals. Many script assume the presense of /dev/null and /tmp. (The emx layer provides an automatic map for shell references to /dev/null and /dev/tty as of the 0.9a version and pdksh also maps /dev/null to nul for the cases where emx doesn't see it unless a /dev/null is present.) Some scripts assume /bin and certain commands within /bin (usually cp and sh). Until I can figure out how to make this more transparent you can simply make these directories on the drive that you intend to run the script on. (Of course, you could also modify the script.) Some scripts reset the PATH variable near the beginning of the script. While you could copy a whole set of commands it is probably easier to modify the script or use tvfs (more about tvfs later.) Another standard "trick" in Bourne shell script programming is to modify IFS to include a colon and then use the set command to parse a variable by setting $1, $2, etc. In OS/2 this would need to be a ';'. For now you will have to hand modify the script. The latest release of ksh for os2 now supports multiple open files using standard pdksh syntax. Note that error checking may not be as complete as standard pdksh for some of this usage. Of course Unix scripts expect the presence of Unix commands. You will need to install a set of Unix utilities, Unix text processing commands, and probably sed and a version of awk. I have created a c:/usr directory on my system for Unix stuff. I have /usr/bin, /usr/man, /usr/etc, /usr/home, and /usr/local. You could establish even more, or perhaps less, Unix conformance. You will also need a ps command. I use procs.exe which I renamed to ps.exe. Kill is a ksh builtin. RUNNING UNIX GNU CONFIGURE SCRIPTS. A lot of people would like to use pdksh to permit them to run the gnu automatic configure scripts. I am pleased to report that this is possible using pdksh. However, I can't guarantee that the results will match the true configuration for os2 since this is dependant on the way the individual configure scripts are written. To set up to run configure scripts you will need to have a copy of pdksh called sh.exe somewhere in your path and, of course, you should be running within a pdksh shell. One of the very early things done by most configure scripts is to figure out the compiler. This will fail since it depends on setting the IFS (see the above discussion). To workaround this problem simply set CC to the compiler you want to use prior to running the script. For example to use gcc: 'export CC=gcc'. Most configure scripts couldn't figure out the names of os2 compilers anyway. Now you should be able to simply type 'configure' and watch it work. At some point the configure script will build a config.status script to perform the final step. If this is not run using 'sh -c config.status' or some such it will fail since .status is not an os2 legal executable suffix. You can run it manually however by typing 'ksh config.status'. If you have problems you should inspect the config.status script and fix it as required. Using ksh -x config.status will echo the lines as they are executed which should aid in debug. Many configure scripts actually build and execute programs to test for certain features. In OS2 using emx, the final link step must have the .exe extension tied to the executable name or the linker will not link correctly. You will need to modify the configure script to insure the correct executable name. Once this is built it can be renamed to a name without an extension if ksh is being used to run it. A line similar to the following may work for you if you are using 2.0: ac_link='${CC-cc} -o conftest.exe $CFLAGS $CPPFLAGS $LDFLAGS \ conftest.$ac_ext $LIBS && mv conftest.exe conftest' This trick takes advantage of ksh's ability to run a command without an extension. Even with these changes you may still find that configure does not correctly identify some os2 features. I would recommend that the config.cache file be edited as required or the resulting config.h file. Another trick is to use the -Zexe option to gcc. This builds a zero length file without an extension and the real executable with the extension .exe. Makefiles and some configure scripts may be fooled by this behavior. TVFS An IBM employee written program called tvfs, toronto virtual file system, can be downloaded from most os2 ftp sites and from IBM ftp sites. This program permits you to simulate a Unix like file system that can span physical drives and even network drives. Using tvfs you cd once into the drive letter designated as the tvfs drive and from then on you can reference all of your drives and directories by only using Unix style pathnames if you wish. Even a limited form of symbolic links can be set up on this drive. This can be a great aid in running Unix scripts and makefiles as well as configure scripts. WORK IN PROGRESS There is still much to do and this project will probably never be complete. The configure.cmd file needs work as does the Makefile. Please let me know if you get this to compile using a C compiler other than gcc. The standard defaults work in the Makefile but many other things are not implemented. And of course there are bugs to fix and enhancements to be made. Check the file os2bugs in the run time release for the latest information on bugs. Please let me know if you like this port, have found a porting bug, have fixed a bug, or have coded a spiffy enhancement. Michael Rendell should be consulted for general pdksh items and is now actually maintaining and enhancing all of the code. Please check the standard README for more information and also the file os2bugs for current known problems and limitations. I can be reached at daled@cadence.com. Note that this is a home brew project and is in no way related to my employment. Dale DePriest