1*da2e3ebdSchin.ds DT July 9, 1993 \" use troff -mm 2*da2e3ebdSchin.nr C 3 3*da2e3ebdSchin.nr N 2 4*da2e3ebdSchin.SA 1 \" right justified 5*da2e3ebdSchin.TL "311466-6713" "49059-6" \" charging case filing case 6*da2e3ebdSchinGuidelines for writing \f5ksh-93\fP built-in commands 7*da2e3ebdSchin.AU "David G. Korn" DGK FP 11267 8062 D-237 "(research!dgk)" 8*da2e3ebdSchin.AF 9*da2e3ebdSchin.TM 11267-930???-93 \" technical memo + TM numbers 10*da2e3ebdSchin.MT 4 11*da2e3ebdSchin.AS 2 \" abstract start for TM 12*da2e3ebdSchinOne of the features of \f5ksh93\fP, the latest version of \f5ksh\fP, 13*da2e3ebdSchinis the ability to add built-in commands at run time. 14*da2e3ebdSchinThis feature only works on operating systems that have the ability 15*da2e3ebdSchinto load and link code into the current process at run time. 16*da2e3ebdSchinSome examples of the systems that have this feature 17*da2e3ebdSchinare System V Release 4, Solaris, Sun OS, HP-UX Release 8 and above, 18*da2e3ebdSchinAIX 3.2 and above, and Microsoft Windows systems. 19*da2e3ebdSchin.P 20*da2e3ebdSchinThis memo describes how to write and compile programs 21*da2e3ebdSchinto can be loaded into \f5ksh\fP at run time as built-in 22*da2e3ebdSchincommands. 23*da2e3ebdSchin.AE \" abstract end 24*da2e3ebdSchin.OK Shell "Command interpreter" Language UNIX \" keyword 25*da2e3ebdSchin.MT 1 \" memo type 26*da2e3ebdSchin.H 1 INTRODUCTION 27*da2e3ebdSchinA built-in command is executed without creating a separate process. 28*da2e3ebdSchinInstead, the command is invoked as a C function by \f5ksh\fP. 29*da2e3ebdSchinIf this function has no side effects in the shell process, 30*da2e3ebdSchinthen the behavior of this built-in is identical to that of 31*da2e3ebdSchinthe equivalent stand-alone command. The primary difference 32*da2e3ebdSchinin this case is performance. The overhead of process creation 33*da2e3ebdSchinis eliminated. For commands of short duration, the effect 34*da2e3ebdSchincan be dramatic. For example, on SUN OS 4.1, the time do 35*da2e3ebdSchinrun \f5wc\fP on a small file of about 1000 bytes, runs 36*da2e3ebdSchinabout 50 times faster as a built-in command. 37*da2e3ebdSchin.P 38*da2e3ebdSchinIn addition, built-in commands that have side effects on the 39*da2e3ebdSchinshell environment can be written. 40*da2e3ebdSchinThis is usually done to extend the application domain for 41*da2e3ebdSchinshell programming. For example, an X-windows extension 42*da2e3ebdSchinthat makes heavy use of the shell variable namespace 43*da2e3ebdSchinwas added as a group of built-ins commands that 44*da2e3ebdSchinare added at run time. 45*da2e3ebdSchinThe result is a windowing shell that can be used to write 46*da2e3ebdSchinX-windows applications. 47*da2e3ebdSchin.P 48*da2e3ebdSchinWhile there are definite advantages to adding built-in 49*da2e3ebdSchincommands, there are some disadvantages as well. 50*da2e3ebdSchinSince the built-in command and \f5ksh\fP share the same 51*da2e3ebdSchinaddress space, a coding error in the built-in program 52*da2e3ebdSchinmay affect the behavior of \f5ksh\fP; perhaps causing 53*da2e3ebdSchinit to core dump or hang. 54*da2e3ebdSchinDebugging is also more complex since your code is now 55*da2e3ebdSchina part of a larger entity. 56*da2e3ebdSchinThe isolation provided by a separate process 57*da2e3ebdSchinguarantees that all resources used by the command 58*da2e3ebdSchinwill be freed when the command completes. 59*da2e3ebdSchinAlso, since the address space of \f5ksh\fP will be larger, 60*da2e3ebdSchinthis may increase the time it takes \f5ksh\fP to fork() and 61*da2e3ebdSchinexec() a non-builtin command. 62*da2e3ebdSchinIt makes no sense to add a built-in command that takes 63*da2e3ebdSchina long time to run or that is run only once, since the performance 64*da2e3ebdSchinbenefits will be negligible. 65*da2e3ebdSchinBuilt-ins that have side effects in the current shell 66*da2e3ebdSchinenvironment have the disadvantage of increasing the 67*da2e3ebdSchincoupling between the built-in and \f5ksh\fP making 68*da2e3ebdSchinthe overall system less modular and more monolithic. 69*da2e3ebdSchin.P 70*da2e3ebdSchinDespite these drawbacks, in many cases extending 71*da2e3ebdSchin\f5ksh\fP by adding built-in 72*da2e3ebdSchincommands makes sense and allows reuse of the shell 73*da2e3ebdSchinscripting ability in an application specific domain. 74*da2e3ebdSchinThis memo describes how to write \f5ksh\fP extensions. 75*da2e3ebdSchin.H 1 "WRITING BUILT-IN COMMANDS" 76*da2e3ebdSchinThere is a development kit available for writing \f5ksh\fP 77*da2e3ebdSchinbuilt-ins. The development kit has three directories, 78*da2e3ebdSchin\f5include\fP, \f5lib\fP, and \f5bin\fP. 79*da2e3ebdSchinThe \f5include\fP directory contains a sub-directory 80*da2e3ebdSchinnamed \f5ast\fP that contains interface prototypes 81*da2e3ebdSchinfor functions that you can call from built-ins. The \f5lib\fP 82*da2e3ebdSchindirectory contains the \fBast\fP library\*F 83*da2e3ebdSchin.FS 84*da2e3ebdSchin\fBast\fP stands for Advanced Software Technology 85*da2e3ebdSchin.FE 86*da2e3ebdSchinand a library named \fBlibcmd\fP that contains a version 87*da2e3ebdSchinof several of the standard POSIX\*(Rf 88*da2e3ebdSchin.RS 89*da2e3ebdSchin.I "POSIX \- Part 2: Shell and Utilities," 90*da2e3ebdSchinIEEE Std 1003.2-1992, ISO/IEC 9945-2:1993. 91*da2e3ebdSchin.RF 92*da2e3ebdSchinutilities that can be made run time built-ins. 93*da2e3ebdSchinIt is best to set the value of the environment variable 94*da2e3ebdSchin\fB\s-1PACKAGE_\s+1ast\fP to the pathname of the directory 95*da2e3ebdSchincontaining the development kit. 96*da2e3ebdSchinUsers of \f5nmake\fP\*(Rf 97*da2e3ebdSchin.RS 98*da2e3ebdSchinGlenn Fowler, 99*da2e3ebdSchinNmake reference needed 100*da2e3ebdSchin.RF 101*da2e3ebdSchin2.3 and above will then be able to 102*da2e3ebdSchinuse the rule 103*da2e3ebdSchin.nf 104*da2e3ebdSchin.in .5i 105*da2e3ebdSchin\f5:PACKAGE: ast\fP 106*da2e3ebdSchin.in 107*da2e3ebdSchin.fi 108*da2e3ebdSchinin their makefiles and not have to specify any \f5-I\fP switches 109*da2e3ebdSchinto the compiler. 110*da2e3ebdSchin.P 111*da2e3ebdSchinA built-in command has a calling convention similar to 112*da2e3ebdSchinthe \f5main\fP function of a program, 113*da2e3ebdSchin.nf 114*da2e3ebdSchin.in .5i 115*da2e3ebdSchin\f5int main(int argc, char *argv[])\fP. 116*da2e3ebdSchin.in 117*da2e3ebdSchin.fi 118*da2e3ebdSchinHowever, instead of \f5main\fP, you must use the function name 119*da2e3ebdSchin\f5b_\fP\fIname\fP, where \fIname\fP is the name 120*da2e3ebdSchinof the built-in you wish to define. 121*da2e3ebdSchinThe built-in function takes a third 122*da2e3ebdSchin\f5void*\fP argument which you can define as \f5NULL\fP. 123*da2e3ebdSchinInstead of \f5exit\fP, you need to use \f5return\fP 124*da2e3ebdSchinto terminate your command. 125*da2e3ebdSchinThe return value, will become the exit status of the command. 126*da2e3ebdSchin.P 127*da2e3ebdSchinThe steps necessary to create and add a run time built-in are 128*da2e3ebdSchinillustrated in the following simple example. 129*da2e3ebdSchinSuppose, you wish to add a built-in command named \f5hello\fP 130*da2e3ebdSchinwhich requires one argument and prints the word hello followed 131*da2e3ebdSchinby its argument. First, write the following program in the file 132*da2e3ebdSchin\f5hello.c\fP: 133*da2e3ebdSchin.nf 134*da2e3ebdSchin.in .5i 135*da2e3ebdSchin\f5#include <stdio.h> 136*da2e3ebdSchinint b_hello(int argc, char *argv[], void *context) 137*da2e3ebdSchin{ 138*da2e3ebdSchin if(argc != 2) 139*da2e3ebdSchin { 140*da2e3ebdSchin fprintf(stderr,"Usage: hello arg\en"); 141*da2e3ebdSchin return(2); 142*da2e3ebdSchin } 143*da2e3ebdSchin printf("hello %s\en",argv[1]); 144*da2e3ebdSchin return(0); 145*da2e3ebdSchin}\fP 146*da2e3ebdSchin.in 147*da2e3ebdSchin.fi 148*da2e3ebdSchin.P 149*da2e3ebdSchinNext, the program needs to be compiled. 150*da2e3ebdSchinOn some systems it is necessary to specify a compiler 151*da2e3ebdSchinoption to produce position independent code 152*da2e3ebdSchinfor dynamic linking. 153*da2e3ebdSchinIf you do not compile with \f5nmake\fP 154*da2e3ebdSchinit is important to specify the a special include directory 155*da2e3ebdSchinwhen compiling built-ins. 156*da2e3ebdSchin.nf 157*da2e3ebdSchin.in .5i 158*da2e3ebdSchin\f5cc -pic -I$PACKAGE_ast/include -c hello.c\fP 159*da2e3ebdSchin.in 160*da2e3ebdSchin.fi 161*da2e3ebdSchinsince the special version of \f5<stdio.h>\fP 162*da2e3ebdSchinin the development kit is required. 163*da2e3ebdSchinThis command generates \f5hello.o\fP in the current 164*da2e3ebdSchindirectory. 165*da2e3ebdSchin.P 166*da2e3ebdSchinOn some systems, you cannot load \f5hello.o\fP directly, 167*da2e3ebdSchinyou must build a shared library instead. 168*da2e3ebdSchinUnfortunately, the method for generating a shared library 169*da2e3ebdSchindiffers with operating system. 170*da2e3ebdSchinHowever, if you are building with the AT\&T \f5nmake\fP 171*da2e3ebdSchinprogram you can use the \f5:LIBRARY:\fP rule to specify 172*da2e3ebdSchinthis in a system independent fashion. 173*da2e3ebdSchinIn addition, if you have several built-ins, it is desirable 174*da2e3ebdSchinto build a shared library that contains them all. 175*da2e3ebdSchin.P 176*da2e3ebdSchinThe final step is using the built-in. 177*da2e3ebdSchinThis can be done with the \f5ksh\fP command \f5builtin\fP. 178*da2e3ebdSchinTo load the shared library \f5hello.so\fP and to add 179*da2e3ebdSchinthe built-in \f5hello\fP, invoke the command, 180*da2e3ebdSchin.nf 181*da2e3ebdSchin.in .5i 182*da2e3ebdSchin\f5builtin -f hello hello\fP 183*da2e3ebdSchin.in 184*da2e3ebdSchin.fi 185*da2e3ebdSchinThe suffix for the shared library can be omitted in 186*da2e3ebdSchinwhich case the shell will add an appropriate suffix 187*da2e3ebdSchinfor the system that it is loading from. 188*da2e3ebdSchinOnce this command has been invoked, you can invoke \f5hello\fP 189*da2e3ebdSchinas you do any other command. 190*da2e3ebdSchin.P 191*da2e3ebdSchinIt is often desirable to make a command \fIbuilt-in\fP 192*da2e3ebdSchinthe first time that it is referenced. The first 193*da2e3ebdSchintime \f5hello\fP is invoked, \f5ksh\fP should load and execute it, 194*da2e3ebdSchinwhereas for subsequent invocations \f5ksh\fP should just execute the built-in. 195*da2e3ebdSchinThis can be done by creating a file named \f5hello\fP 196*da2e3ebdSchinwith the following contents: 197*da2e3ebdSchin.nf 198*da2e3ebdSchin.in .5i 199*da2e3ebdSchin\f5function hello 200*da2e3ebdSchin{ 201*da2e3ebdSchin unset -f hello 202*da2e3ebdSchin builtin -f hello hello 203*da2e3ebdSchin hello "$@" 204*da2e3ebdSchin}\fP 205*da2e3ebdSchin.in 206*da2e3ebdSchin.fi 207*da2e3ebdSchinThis file \f5hello\fP needs to be placed in a directory that is 208*da2e3ebdSchinin your \fB\s-1FPATH\s+1\fP variable. In addition, the full 209*da2e3ebdSchinpathname for \f5hello.so\fP should be used in this script 210*da2e3ebdSchinso that the run time loader will be able to find this shared library 211*da2e3ebdSchinno matter where the command \f5hello\fP is invoked. 212*da2e3ebdSchin.H 1 "CODING REQUIREMENTS AND CONVENTIONS" 213*da2e3ebdSchinAs mentioned above, the entry point for built-ins must be of 214*da2e3ebdSchinthe form \f5b_\fP\fIname\fP. 215*da2e3ebdSchinYour built-ins can call functions from the standard C library, 216*da2e3ebdSchinthe \fBast\fP library, interface functions provided by \f5ksh\fP, 217*da2e3ebdSchinand your own functions. 218*da2e3ebdSchinYou should avoid using any global symbols beginning with 219*da2e3ebdSchin.BR sh_ , 220*da2e3ebdSchin.BR nv_ , 221*da2e3ebdSchinand 222*da2e3ebdSchin.B ed_ 223*da2e3ebdSchinsince these are used by \f5ksh\fP itself. 224*da2e3ebdSchinIn addition, \f5#define\fP constants in \f5ksh\fP interface 225*da2e3ebdSchinfiles, use symbols beginning with \fBSH_\fP to that you should 226*da2e3ebdSchinavoid using names beginning with \fBSH_\fP. 227*da2e3ebdSchin.H 2 "Header Files" 228*da2e3ebdSchinThe development kit provides a portable interface 229*da2e3ebdSchinto the C library and to libast. 230*da2e3ebdSchinThe header files in the development kit are compatible with 231*da2e3ebdSchinK&R C\*(Rf, 232*da2e3ebdSchin.RS 233*da2e3ebdSchinBrian W. Kernighan and Dennis M. Ritchie, 234*da2e3ebdSchin.IR "The C Programming Language" , 235*da2e3ebdSchinPrentice Hall, 1978. 236*da2e3ebdSchin.RF 237*da2e3ebdSchinANSI-C\*(Rf, 238*da2e3ebdSchin.RS 239*da2e3ebdSchinAmerican National Standard for Information Systems \- Programming 240*da2e3ebdSchinLanguage \- C, ANSI X3.159-1989. 241*da2e3ebdSchin.RF 242*da2e3ebdSchinand C++\*(Rf. 243*da2e3ebdSchin.RS 244*da2e3ebdSchinBjarne Stroustroup, 245*da2e3ebdSchin.IR "C++" , 246*da2e3ebdSchinAddison Wesley, xxxx 247*da2e3ebdSchin.RF 248*da2e3ebdSchin.P 249*da2e3ebdSchinThe best thing to do is to include the header file \f5<shell.h>\fP. 250*da2e3ebdSchinThis header file causes the \f5<ast.h>\fP header, the 251*da2e3ebdSchin\f5<error.h>\fP header and the \f5<stak.h>\fP 252*da2e3ebdSchinheader to be included as well as defining prototypes 253*da2e3ebdSchinfor functions that you can call to get shell 254*da2e3ebdSchinservices for your builtins. 255*da2e3ebdSchinThe header file \f5<ast.h>\fP 256*da2e3ebdSchinprovides prototypes for many \fBlibast\fP functions 257*da2e3ebdSchinand all the symbol and function definitions from the 258*da2e3ebdSchinANSI-C headers, \f5<stddef.h>\fP, 259*da2e3ebdSchin\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP, 260*da2e3ebdSchinand \f5<string.h>\fP. 261*da2e3ebdSchinIt also provides all the symbols and definitions for the 262*da2e3ebdSchinPOSIX\*(Rf 263*da2e3ebdSchin.RS 264*da2e3ebdSchin.I "POSIX \- Part 1: System Application Program Interface," 265*da2e3ebdSchinIEEE Std 1003.1-1990, ISO/IEC 9945-1:1990. 266*da2e3ebdSchin.RF 267*da2e3ebdSchinheaders \f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and 268*da2e3ebdSchin\f5<unistd.h>\fP. 269*da2e3ebdSchinYou should include \f5<ast.h>\fP instead of one or more of 270*da2e3ebdSchinthese headers. 271*da2e3ebdSchinThe \f5<error.h>\fP header provides the interface to the error 272*da2e3ebdSchinand option parsing routines defined below. 273*da2e3ebdSchinThe \f5<stak.h>\fP header provides the interface to the memory 274*da2e3ebdSchinallocation routines described below. 275*da2e3ebdSchin.P 276*da2e3ebdSchinPrograms that want to use the information in \f5<sys/stat.h>\fP 277*da2e3ebdSchinshould include the file \f5<ls.h>\fP instead. 278*da2e3ebdSchinThis provides the complete POSIX interface to \f5stat()\fP 279*da2e3ebdSchinrelated functions even on non-POSIX systems. 280*da2e3ebdSchin.P 281*da2e3ebdSchin.H 2 "Input/Output" 282*da2e3ebdSchin\f5ksh\fP uses \fBsfio\fP, 283*da2e3ebdSchinthe Safe/Fast I/O library\*(Rf, 284*da2e3ebdSchin.RS 285*da2e3ebdSchinDavid Korn and Kiem-Phong Vo, 286*da2e3ebdSchin.IR "SFIO - A Safe/Fast Input/Output library," 287*da2e3ebdSchinProceedings of the Summer Usenix, 288*da2e3ebdSchinpp. , 1991. 289*da2e3ebdSchin.RF 290*da2e3ebdSchinto perform all I/O operations. 291*da2e3ebdSchinThe \fBsfio\fP library, which is part of \fBlibast\fP, 292*da2e3ebdSchinprovides a superset of the functionality provided by the standard 293*da2e3ebdSchinI/O library defined in ANSI-C. 294*da2e3ebdSchinIf none of the additional functionality is required, 295*da2e3ebdSchinand if you are not familiar with \fBsfio\fP and 296*da2e3ebdSchinyou do not want to spend the time learning it, 297*da2e3ebdSchinthen you can use \fBsfio\fP via the \fBstdio\fP library 298*da2e3ebdSchininterface. The development kit contains the header \f5<stdio.h>\fP 299*da2e3ebdSchinwhich maps \fBstdio\fP calls to \fBsfio\fP calls. 300*da2e3ebdSchinIn most instances the mapping is done 301*da2e3ebdSchinby macros or inline functions so that there is no overhead. 302*da2e3ebdSchinThe man page for the \fBsfio\fP library is in an Appendix. 303*da2e3ebdSchin.P 304*da2e3ebdSchinHowever, there are some very nice extensions and 305*da2e3ebdSchinperformance improvements in \fBsfio\fP 306*da2e3ebdSchinand if you plan any major extensions I recommend 307*da2e3ebdSchinthat you use it natively. 308*da2e3ebdSchin.H 2 "Error Handling" 309*da2e3ebdSchinFor error messages it is best to use the \fBast\fP library 310*da2e3ebdSchinfunction \f5errormsg()\fP rather that sending output to 311*da2e3ebdSchin\f5stderr\fP or the equivalent \f5sfstderr\fP directly. 312*da2e3ebdSchinUsing \f5errormsg()\fP will make error message appear 313*da2e3ebdSchinmore uniform to the user. 314*da2e3ebdSchinFurthermore, using \f5errormsg()\fP should make it easier 315*da2e3ebdSchinto do error message translation for other locales 316*da2e3ebdSchinin future versions of \f5ksh\fP. 317*da2e3ebdSchin.P 318*da2e3ebdSchinThe first argument to 319*da2e3ebdSchin\f5errormsg()\fP specifies the dictionary in which the string 320*da2e3ebdSchinwill be searched for translation. 321*da2e3ebdSchinThe second argument to \f5errormsg()\fP contains that error type 322*da2e3ebdSchinand value. The third argument is a \fIprintf\fP style format 323*da2e3ebdSchinand the remaining arguments are arguments to be printed 324*da2e3ebdSchinas part of the message. A new-line is inserted at the 325*da2e3ebdSchinend of each message and therefore, should not appear as 326*da2e3ebdSchinpart of the format string. 327*da2e3ebdSchinThe second argument should be one of the following: 328*da2e3ebdSchin.VL .5i 329*da2e3ebdSchin.LI \f5ERROR_exit(\fP\fIn\fP\f5)\fP: 330*da2e3ebdSchinIf \fIn\fP is not-zero, the builtin will exit value \fIn\fP after 331*da2e3ebdSchinprinting the message. 332*da2e3ebdSchin.LI \f5ERROR_system(\fP\fIn\fP\f5)\fP: 333*da2e3ebdSchinExit builtin with exit value \fIn\fP after printing the message. 334*da2e3ebdSchinThe message will display the message corresponding to \f5errno\fP 335*da2e3ebdSchinenclosed within \f5[\ ]\fP at the end of the message. 336*da2e3ebdSchin.LI \f5ERROR_usage(\fP\fIn\fP\f5)\fP: 337*da2e3ebdSchinWill generate a usage message and exit. If \fIn\fP is non-zero, 338*da2e3ebdSchinthe exit value will be 2. Otherwise the exit value will be 0. 339*da2e3ebdSchin.LI \f5ERROR_debug(\fP\fIn\fP\f5)\fP: 340*da2e3ebdSchinWill print a level \fIn\fP debugging message and will then continue. 341*da2e3ebdSchin.LI \f5ERROR_warn(\fP\fIn\fP\f5)\fP: 342*da2e3ebdSchinPrints a warning message. \fIn\fP is ignored. 343*da2e3ebdSchin.H 2 "Option Parsing" 344*da2e3ebdSchinThe first thing that a built-in should do is to check 345*da2e3ebdSchinthe arguments for correctness and to print any usage 346*da2e3ebdSchinmessages on standard error. 347*da2e3ebdSchinFor consistency with the rest of \f5ksh\fP, it is best 348*da2e3ebdSchinto use the \f5libast\fP functions \f5optget()\fP and 349*da2e3ebdSchin\f5optusage()\fPfor this 350*da2e3ebdSchinpurpose. 351*da2e3ebdSchinThe header \f5<error.h>\fP included prototypes for 352*da2e3ebdSchinthese functions. 353*da2e3ebdSchinThe \f5optget()\fP function is similar to the 354*da2e3ebdSchinSystem V C library function \f5getopt()\fP, 355*da2e3ebdSchinbut provides some additional capabilities. 356*da2e3ebdSchinBuilt-ins that use \f5optget()\fP provide a more 357*da2e3ebdSchinconsistent user interface. 358*da2e3ebdSchin.P 359*da2e3ebdSchinThe \f5optget()\fP function is invoked as 360*da2e3ebdSchin.nf 361*da2e3ebdSchin.in .5i 362*da2e3ebdSchin\f5int optget(char *argv[], const char *optstring)\fP 363*da2e3ebdSchin.in 364*da2e3ebdSchin.fi 365*da2e3ebdSchinwhere \f5argv\fP is the argument list and \f5optstring\fP 366*da2e3ebdSchinis a string that specifies the allowable arguments and 367*da2e3ebdSchinadditional information that is used to format \fIusage\fP 368*da2e3ebdSchinmessages. 369*da2e3ebdSchinIn fact a complete man page in \f5troff\fP or \f5html\fP 370*da2e3ebdSchincan be generated by passing a usage string as described 371*da2e3ebdSchinby the \f5getopts\fP command. 372*da2e3ebdSchinLike \f5getopt()\fP, 373*da2e3ebdSchinsingle letter options are represented by the letter itself, 374*da2e3ebdSchinand options that take a string argument are followed by the \f5:\fP 375*da2e3ebdSchincharacter. 376*da2e3ebdSchinOption strings have the following special characters: 377*da2e3ebdSchin.VL .5i 378*da2e3ebdSchin.LI \f5:\fP 379*da2e3ebdSchinUsed after a letter option to indicate that the option 380*da2e3ebdSchintakes an option argument. 381*da2e3ebdSchinThe variable \f5opt_info.arg\fP will point to this 382*da2e3ebdSchinvalue after the given argument is encountered. 383*da2e3ebdSchin.LI \f5#\fP 384*da2e3ebdSchinUsed after a letter option to indicate that the option 385*da2e3ebdSchincan only take a numerical value. 386*da2e3ebdSchinThe variable \f5opt_info.num\fP will contain this 387*da2e3ebdSchinvalue after the given argument is encountered. 388*da2e3ebdSchin.LI \f5?\fP 389*da2e3ebdSchinUsed after a \f5:\fP or \f5#\fP (and after the optional \f5?\fP) 390*da2e3ebdSchinto indicate the the 391*da2e3ebdSchinpreceding option argument is not required. 392*da2e3ebdSchin.LI \f5[\fP...\f5]\fP 393*da2e3ebdSchinAfter a \f5:\fP or \f5#\fP, the characters contained 394*da2e3ebdSchininside the brackets are used to identify the option 395*da2e3ebdSchinargument when generating a \fIusage\fP message. 396*da2e3ebdSchin.LI \fIspace\fP 397*da2e3ebdSchinThe remainder of the string will only be used when generating 398*da2e3ebdSchinusage messages. 399*da2e3ebdSchin.LE 400*da2e3ebdSchin.P 401*da2e3ebdSchinThe \f5optget()\fP function returns the matching option letter if 402*da2e3ebdSchinone of the legal option is matched. 403*da2e3ebdSchinOtherwise, \f5optget()\fP returns 404*da2e3ebdSchin.VL .5i 405*da2e3ebdSchin.LI \f5':'\fP 406*da2e3ebdSchinIf there is an error. In this case the variable \f5opt_info.arg\fP 407*da2e3ebdSchincontains the error string. 408*da2e3ebdSchin.LI \f50\fP 409*da2e3ebdSchinIndicates the end of options. 410*da2e3ebdSchinThe variable \f5opt_info.index\fP contains the number of arguments 411*da2e3ebdSchinprocessed. 412*da2e3ebdSchin.LI \f5'?'\fP 413*da2e3ebdSchinA usage message has been required. 414*da2e3ebdSchinYou normally call \f5optusage()\fP to generate and display 415*da2e3ebdSchinthe usage message. 416*da2e3ebdSchin.LE 417*da2e3ebdSchin.P 418*da2e3ebdSchinThe following is an example of the option parsing portion 419*da2e3ebdSchinof the \f5wc\fP utility. 420*da2e3ebdSchin.nf 421*da2e3ebdSchin.in +5 422*da2e3ebdSchin\f5#include <shell.h> 423*da2e3ebdSchinwhile(1) switch(n=optget(argv,"xf:[file]")) 424*da2e3ebdSchin{ 425*da2e3ebdSchin case 'f': 426*da2e3ebdSchin file = opt_info.arg; 427*da2e3ebdSchin break; 428*da2e3ebdSchin case ':': 429*da2e3ebdSchin error(ERROR_exit(0), opt_info.arg); 430*da2e3ebdSchin break; 431*da2e3ebdSchin case '?': 432*da2e3ebdSchin error(ERROR_usage(2), opt_info.arg); 433*da2e3ebdSchin break; 434*da2e3ebdSchin}\fP 435*da2e3ebdSchin.in 436*da2e3ebdSchin.fi 437*da2e3ebdSchin.H 2 "Storage Management" 438*da2e3ebdSchinIt is important that any memory used by your built-in 439*da2e3ebdSchinbe returned. Otherwise, if your built-in is called frequently, 440*da2e3ebdSchin\f5ksh\fP will eventually run out of memory. 441*da2e3ebdSchinYou should avoid using \f5malloc()\fP for memory that must 442*da2e3ebdSchinbe freed before returning from you built-in, because by default, 443*da2e3ebdSchin\f5ksh\fP will terminate you built-in in the event of an 444*da2e3ebdSchininterrupt and the memory will not be freed. 445*da2e3ebdSchin.P 446*da2e3ebdSchinThe best way to to allocate variable sized storage is 447*da2e3ebdSchinthrough calls to the \fBstak\fP library 448*da2e3ebdSchinwhich is included in \fBlibast\fP 449*da2e3ebdSchinand which is used extensively by \f5ksh\fP itself. 450*da2e3ebdSchinObjects allocated with the \f5stakalloc()\fP 451*da2e3ebdSchinfunction are freed when you function completes 452*da2e3ebdSchinor aborts. 453*da2e3ebdSchinThe \fBstak\fP library provides a convenient way to 454*da2e3ebdSchinbuild variable length strings and other objects dynamically. 455*da2e3ebdSchinThe man page for the \fBstak\fP library is contained 456*da2e3ebdSchinin the Appendix. 457*da2e3ebdSchin.P 458*da2e3ebdSchinBefore \f5ksh\fP calls each built-in command, it saves 459*da2e3ebdSchinthe current stack location and restores it after 460*da2e3ebdSchinit returns. 461*da2e3ebdSchinIt is not necessary to save and restore the stack 462*da2e3ebdSchinlocation in the \f5b_\fP entry function, 463*da2e3ebdSchinbut you may want to write functions that use this stack 464*da2e3ebdSchinare restore it when leaving the function. 465*da2e3ebdSchinThe following coding convention will do this in 466*da2e3ebdSchinan efficient manner: 467*da2e3ebdSchin.nf 468*da2e3ebdSchin.in .5i 469*da2e3ebdSchin\fIyourfunction\fP\f5() 470*da2e3ebdSchin{ 471*da2e3ebdSchin char *savebase; 472*da2e3ebdSchin int saveoffset; 473*da2e3ebdSchin if(saveoffset=staktell()) 474*da2e3ebdSchin savebase = stakfreeze(0); 475*da2e3ebdSchin \fP...\f5 476*da2e3ebdSchin if(saveoffset) 477*da2e3ebdSchin stakset(savebase,saveoffset); 478*da2e3ebdSchin else 479*da2e3ebdSchin stakseek(0); 480*da2e3ebdSchin}\fP 481*da2e3ebdSchin.in 482*da2e3ebdSchin.fi 483*da2e3ebdSchin.H 1 "CALLING \f5ksh\fP SERVICES" 484*da2e3ebdSchinSome of the more interesting applications are those that extend 485*da2e3ebdSchinthe functionality of \f5ksh\fP in application specific directions. 486*da2e3ebdSchinA prime example of this is the X-windows extension which adds 487*da2e3ebdSchinbuiltins to create and delete widgets. 488*da2e3ebdSchinThe \fBnval\fP library is used to interface with the shell 489*da2e3ebdSchinname space. 490*da2e3ebdSchinThe \fBshell\fP library is used to access other shell services. 491*da2e3ebdSchin.H 2 "The nval library" 492*da2e3ebdSchinA great deal of power is derived from the ability to use 493*da2e3ebdSchinportions of the hierarchal variable namespace provided by \f5ksh-93\fP 494*da2e3ebdSchinand turn these names into active objects. 495*da2e3ebdSchin.P 496*da2e3ebdSchinThe \fBnval\fP library is used to interface with shell 497*da2e3ebdSchinvariables. 498*da2e3ebdSchinA man page for this file is provided in an Appendix. 499*da2e3ebdSchinYou need to include the header \f5<nval.h>\fP 500*da2e3ebdSchinto access the functions defined in the \fBnval\fP library. 501*da2e3ebdSchinAll the functions provided by the \fBnval\fP library begin 502*da2e3ebdSchinwith the prefix \f5nv_\fP. 503*da2e3ebdSchinEach shell variable is an object in an associative table 504*da2e3ebdSchinthat is referenced by name. 505*da2e3ebdSchinThe type \f5Namval_t*\fP is pointer to a shell variable. 506*da2e3ebdSchinTo operate on a shell variable, you first get a handle 507*da2e3ebdSchinto the variable with the \f5nv_open()\fP function 508*da2e3ebdSchinand then supply the handle returned as the first 509*da2e3ebdSchinargument of the function that provides an operation 510*da2e3ebdSchinon the variable. 511*da2e3ebdSchinYou must call \f5nv_close()\fP when you are finished 512*da2e3ebdSchinusing this handle so that the space can be freed once 513*da2e3ebdSchinthe value is unset. 514*da2e3ebdSchinThe two most frequent operations are to get the value of 515*da2e3ebdSchinthe variable, and to assign value to the variable. 516*da2e3ebdSchinThe \f5nv_getval()\fP returns a pointer the the 517*da2e3ebdSchinvalue of the variable. 518*da2e3ebdSchinIn some cases the pointer returned is to a region that 519*da2e3ebdSchinwill be overwritten by the next \f5nv_getval()\fP call 520*da2e3ebdSchinso that if the value isn't used immediately, it should 521*da2e3ebdSchinbe copied. 522*da2e3ebdSchinMany variables can also generate a numeric value. 523*da2e3ebdSchinThe \f5nv_getnum()\fP function returns a numeric 524*da2e3ebdSchinvalue for the given variable pointer, calling the 525*da2e3ebdSchinarithmetic evaluator if necessary. 526*da2e3ebdSchin.P 527*da2e3ebdSchinThe \f5nv_putval()\fP function is used to assign a new 528*da2e3ebdSchinvalue to a given variable. 529*da2e3ebdSchinThe second argument to \f5putval()\fP is the value 530*da2e3ebdSchinto be assigned 531*da2e3ebdSchinand the third argument is a \fIflag\fP which 532*da2e3ebdSchinis used in interpreting the second argument. 533*da2e3ebdSchin.P 534*da2e3ebdSchinEach shell variable can have one or more attributes. 535*da2e3ebdSchinThe \f5nv_isattr()\fP is used to test for the existence 536*da2e3ebdSchinof one or more attributes. 537*da2e3ebdSchinSee the appendix for a complete list of attributes. 538*da2e3ebdSchin.P 539*da2e3ebdSchinBy default, each shell variable passively stores the string you 540*da2e3ebdSchingive with with \f5nv_putval()\fP, and returns the value 541*da2e3ebdSchinwith \f5getval()\fP. However, it is possible to turn 542*da2e3ebdSchinany node into an active entity by assigning functions 543*da2e3ebdSchinto it that will be called whenever \f5nv_putval()\fP 544*da2e3ebdSchinand/or \f5nv_getval()\fP is called. 545*da2e3ebdSchinIn fact there are up to five functions that can 546*da2e3ebdSchinassociated with each variable to override the 547*da2e3ebdSchindefault actions. 548*da2e3ebdSchinThe type \f5Namfun_t\fP is used to define these functions. 549*da2e3ebdSchinOnly those that are non-\f5NULL\fP override the 550*da2e3ebdSchindefault actions. 551*da2e3ebdSchinTo override the default actions, you must allocate an 552*da2e3ebdSchininstance of \f5Namfun_t\fP, and then assign 553*da2e3ebdSchinthe functions that you wish to override. 554*da2e3ebdSchinThe \f5putval()\fP 555*da2e3ebdSchinfunction is called by the \f5nv_putval()\fP function. 556*da2e3ebdSchinA \f5NULL\fP for the \fIvalue\fP argument 557*da2e3ebdSchinindicates a request to unset the variable. 558*da2e3ebdSchinThe \fItype\fP argument might contain the \f5NV_INTEGER\fP 559*da2e3ebdSchinbit so you should be prepared to do a conversion if 560*da2e3ebdSchinnecessary. 561*da2e3ebdSchinThe \f5getval()\fP 562*da2e3ebdSchinfunction is called by \f5nv_getval()\fP 563*da2e3ebdSchinvalue and must return a string. 564*da2e3ebdSchinThe \f5getnum()\fP 565*da2e3ebdSchinfunction is called by by the arithmetic evaluator 566*da2e3ebdSchinand must return double. 567*da2e3ebdSchinIf omitted, then it will call \f5nv_getval()\fP and 568*da2e3ebdSchinconvert the result to a number. 569*da2e3ebdSchin.P 570*da2e3ebdSchinThe functionality of a variable can further be increased 571*da2e3ebdSchinby adding discipline functions that 572*da2e3ebdSchincan be associated with the variable. 573*da2e3ebdSchinA discipline function allows a script that uses your 574*da2e3ebdSchinvariable to define functions whose name is 575*da2e3ebdSchin\fIvarname\fP\f5.\fP\fIdiscname\fP 576*da2e3ebdSchinwhere \fIvarname\fP is the name of the variable, and \fIdiscname\fP 577*da2e3ebdSchinis the name of the discipline. 578*da2e3ebdSchinWhen the user defines such a function, the \f5settrap()\fP 579*da2e3ebdSchinfunction will be called with the name of the discipline and 580*da2e3ebdSchina pointer to the parse tree corresponding to the discipline 581*da2e3ebdSchinfunction. 582*da2e3ebdSchinThe application determines when these functions are actually 583*da2e3ebdSchinexecuted. 584*da2e3ebdSchinBy default, \f5ksh\fP defines \f5get\fP, 585*da2e3ebdSchin\f5set\fP, and \f5unset\fP as discipline functions. 586*da2e3ebdSchin.P 587*da2e3ebdSchinIn addition, it is possible to provide a data area that 588*da2e3ebdSchinwill be passed as an argument to 589*da2e3ebdSchineach of these functions whenever any of these functions are called. 590*da2e3ebdSchinTo have private data, you need to define and allocate a structure 591*da2e3ebdSchinthat looks like 592*da2e3ebdSchin.nf 593*da2e3ebdSchin.in .5i 594*da2e3ebdSchin\f5struct \fIyours\fP 595*da2e3ebdSchin{ 596*da2e3ebdSchin Namfun_t fun; 597*da2e3ebdSchin \fIyour_data_fields\fP; 598*da2e3ebdSchin};\fP 599*da2e3ebdSchin.in 600*da2e3ebdSchin.fi 601*da2e3ebdSchin.H 2 "The shell library" 602*da2e3ebdSchinThere are several functions that are used by \f5ksh\fP itself 603*da2e3ebdSchinthat can also be called from built-in commands. 604*da2e3ebdSchinThe man page for these routines are in the Appendix. 605*da2e3ebdSchin.P 606*da2e3ebdSchinThe \f5sh_addbuiltin()\fP function can be used to add or delete 607*da2e3ebdSchinbuiltin commands. It takes the name of the built-in, the 608*da2e3ebdSchinaddress of the function that implements the built-in, and 609*da2e3ebdSchina \f5void*\fP pointer that will be passed to this function 610*da2e3ebdSchinas the third agument whenever it is invoked. 611*da2e3ebdSchinIf the function address is \f5NULL\fP, the specified built-in 612*da2e3ebdSchinwill be deleted. However, special built-in functions cannot 613*da2e3ebdSchinbe deleted or modified. 614*da2e3ebdSchin.P 615*da2e3ebdSchinThe \f5sh_fmtq()\fP function takes a string and returns 616*da2e3ebdSchina string that is quoted as necessary so that it can 617*da2e3ebdSchinbe used as shell input. 618*da2e3ebdSchinThis function is used to implement the \f5%q\fP option 619*da2e3ebdSchinof the shell built-in \f5printf\fP command. 620*da2e3ebdSchin.P 621*da2e3ebdSchinThe \f5sh_parse()\fP function returns a parse tree corresponding 622*da2e3ebdSchinto a give file stream. The tree can be executed by supplying 623*da2e3ebdSchinit as the first argument to 624*da2e3ebdSchinthe \f5sh_trap()\fP function and giving a value of \f51\fP as the 625*da2e3ebdSchinsecond argument. 626*da2e3ebdSchinAlternatively, the \f5sh_trap()\fP function can parse and execute 627*da2e3ebdSchina string by passing the string as the first argument and giving \f50\fP 628*da2e3ebdSchinas the second argument. 629*da2e3ebdSchin.P 630*da2e3ebdSchinThe \f5sh_isoption()\fP function can be used to set to see whether one 631*da2e3ebdSchinor more of the option settings is enabled. 632