OS/2 port of pdksh version 5 Dec 27, 1994 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. A default build of pdksh, called ksh.exe, is included in the os2 run time package. This version was built using the emx facility and therefore requires that an emx run time package .08h 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. If you would rather build your own, obtain the sources from ftp.cs.mun.ca in the directory pub/pdksh. You will need a copy of gtar and gunzip to unload the archive and probably an hpfs partition. Now cd 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 options.h to define your particular preferences. Configure does support two options. Use /v for verbose output and /d to build a debug version with symbols (for gcc). KSH 5 versus KSH 4.9 The KSH version 5 effort is being spearheaded by Michael Rendell, who took over the effort by 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 this first version 5 port to os/2, I started with the 4.9 os/2 changes and applied them to the new version as best I could. Many bugs and limitations from that port may still be there (and there are probably some new ones). A few things did get fixed, most notably arguments to scripts are now passed in correctly. One of my goals for this version 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 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 $ substitutions can be used in the prompt. The commands 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. 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 in the bind command.) The remapping of 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. 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 os/2 commands the '/' is used to indicate an option. This should still work with pdksh as long as it is not attached directly to the command name. 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 place the assignment command in quotes or use '\;'. Note that since a ';' is not a valid filename or pathname character the '\' will be correctly interpreted as an escape character. 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. 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. PDSKH, 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 and is started interactively. It is more difficult to get an OS/2 shell to read login files although this shell will honor a loginfile called profile.ksh if located in $INIT/etc, c:/usr/etc, or your home. The trick is to fool it into thinking that you logged in. Renaming the shell to something beginning with a '-' will do the trick. Real Unix systems modify argument 0 during the login process to accomplish this. Now if you start this shell it will think that you just logged in. Too bad OS/2 doesn't support symbolic links. A future release will add a special start up option (was -0 in 4.9) to support simulated logging in. Should you mess up 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. 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 Korne 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 a 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. (Yes it can run dos commands and OS/2 command files as well.) The .ksh extension tells the shell that this is an executable shell script. The current version will also treat a file without an extension as a shell script in the style of unix. Hopefully this won't cause problems since it really aids scripts. If it does we may have to take it out. Scripts need not necessarily be a ksh shell scripts however. the standard Unix #! line at the top of the file determines the actual comand that will be used to run the script. (Perhaps in the future Michael or I will design an alias capability that permits you to define your own extensions.) The sample kshrc.ksh file that came 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. If if no editing mode is defined you can use F3 to get the previous command and the other editing commands can be used. However, to get the most from the shell you will probably want the set of Unix commands ported by the Gnu team. 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 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 to permit it to ignore case. 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. To write portable scripts use the 'uname' command from Gnu to set a variable that can be checked for specialized approaches. 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. The second goal 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. (I have provided an automatic map for shell references to /dev/null.) Some 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.) 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 setting $1, $2, etc. In OS/2 this needs to be a ';'. For now you will have to hand modify the script. 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. WORK IN PROGRESS There is still much to do to complete this project. The confiure.cmd file needs work as does the Makefile. The standard defaults work in the Makefile but many other things have not been checked. It is known to work with nmake and dmake, but gnu make has problems. The config.h file was hand built to get something to work but other options and configurations could be tried. Ksh job control emulation isn't done nor is ksh background processing (you can use the OS/2 start command). And of course there are bugs to fix and enhancements to be made. 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