1.fp 5 CW 2.ds DT January 9, 2012 \" use troff -mm 3.nr C 3 4.nr N 2 5.SA 1 \" right justified 6.TL "311466-6713" "49059-6" \" charging case filing case 7Guidelines for writing \f5ksh-93\fP built-in commands 8.AU "David G. Korn" DGK FP 11267 8062 D-237 "(research!dgk)" 9.AF 10.TM 11267-930???-93 \" technical memo + TM numbers 11.MT 4 12.AS 2 \" abstract start for TM 13One of the features of \f5ksh93\fP, the latest version of \f5ksh\fP, 14is the ability to add built-in commands at run time. 15This feature only works on operating systems that have the ability 16to load and link code into the current process at run time. 17Some examples of the systems that have this feature 18are Linux, System V Release 4, Solaris, Sun OS, HP-UX Release 8 and above, 19AIX 3.2 and above, and Microsoft Windows systems. 20.P 21This memo describes how to write and compile programs 22that can be loaded into \f5ksh\fP at run time as built-in 23commands. 24.AE \" abstract end 25.H 1 INTRODUCTION 26A built-in command is executed without creating a separate process. 27Instead, the command is invoked as a C function by \f5ksh\fP. 28If this function has no side effects in the shell process, 29then the behavior of this built-in is identical to that of 30the equivalent stand-alone command. The primary difference 31in this case is performance. The overhead of process creation 32is eliminated. For commands of short duration, the effect 33can be dramatic. For example, on SUN OS 4.1, the time to 34run \f5wc\fP on a small file of about 1000 bytes, runs 35about 50 times faster as a built-in command. 36.P 37In addition, built-in commands may have side effects on the 38shell environment. 39This is usually done to extend the application domain for 40shell programming. For example, there is a group of X-windows extension 41built-ins that make heavy use of the shell variable namespace. 42These built-ins are added at run time and 43result in a windowing shell that can be used to write 44X-windows applications. 45.P 46While there are definite advantages to adding built-in 47commands, there are some disadvantages as well. 48Since the built-in command and \f5ksh\fP share the same 49address space, a coding error in the built-in program 50may affect the behavior of \f5ksh\fP; perhaps causing 51it to core dump or hang. 52Debugging is also more complex since your code is now 53a part of a larger entity. 54The isolation provided by a separate process 55guarantees that all resources used by the command 56will be freed when the command completes. 57Resources used by a built-in must be meticulously maintained and freed. 58Also, since the address space of \f5ksh\fP will be larger when built-in are loaded, 59it may increase the time it takes \f5ksh\fP to fork() and 60exec() non-built-in commands. 61It makes no sense to add a built-in command that takes 62a long time to run or that is run only once, since the performance 63benefits will be negligible. 64Built-ins that have side effects in the current shell 65environment have the disadvantage of increasing the 66coupling between the built-in and \f5ksh\fP, making 67the overall system less modular and more monolithic. 68.P 69Despite these drawbacks, in many cases extending 70\f5ksh\fP by adding built-in 71commands makes sense and allows reuse of the shell 72scripting ability in an application specific domain. 73This memo describes how to write \f5ksh\fP extensions. 74.H 1 "WRITING BUILT-IN COMMANDS" 75There is a development kit available for writing \f5ksh\fP 76built-ins as part of the AST (AT&T Software Technology) Toolkit. 77The development kit has three directories, 78\f5include\fP, \f5lib\fP, and \f5bin\fP. 79It is best to set the value of the environment variable 80\f5PACKAGE_ast\fP to the pathname of the directory 81containing the development kit. 82The \f5include\fP directory contains a sub-directory 83named \f5ast\fP that contains interface prototypes 84for functions that you can call from built-ins. The \f5lib\fP 85directory contains the \f5ast\fP library 86and a library named \f5cmd\fP that contains a version 87of several of the standard POSIX\*(Rf 88.RS 89.I "POSIX \- Part 2: Shell and Utilities," 90IEEE Std 1003.2-1992, ISO/IEC 9945-2:1993. 91.RF 92utilities that can be made run time built-ins. 93The \f5lib/ksh\fP directory contains shared libraries 94that implement other \f5ksh\fP built-ins. 95The \f5bin\fP directory contains build tools such as \f5nmake\fP\*(Rf. 96.RS 97Glenn Fowler, 98.IR "A Case for make" , 99Software - Practice and Experience, Vol. 20 No. S1, pp. 30-46, June 1990. 100.RF 101To add built-ins at runtime, it is necessary to build a shared library 102containing one or more built-ins that you wish to add. 103The built-ins are then added by running \f5builtin \-f\fP \fIshared_lib\fP. 104Since the procedure for building share libraries is system dependent, 105it is best to use 106\f5nmake\fP 107using the sample nmake makefile below as a prototype. 108The AST Toolkit also contains some examples of built-in libraries under 109the \f5src/cmd/kshlib\fP directory. 110.P 111There are two ways to code adding built-ins. One method is to replace 112the function \f5main\fP with a function 113\f5b_\fP\fIname\fP, where \fIname\fP is the name 114of the built-in you wish to define. 115A built-in command has a calling convention similar to 116the \f5main\fP function of a program, 117\f5int main(int argc, char *argv[])\fP. 118except that it takes a third argument of type \f5Shbltin_t*\fP which can 119be passed as \f5\s-1NULL\s+1\fP if it is not used. The definition for 120\f5Shbltin_t*\fP is in \f5<ast/shcmd.h>\fP. 121Instead of \f5exit\fP, you need to use \f5return\fP 122to terminate your command. 123The return value will become the exit status of the command. 124The \f5open\fP built-in, installed in \f5lib/ksh\fP in the AST Toolkit, uses this method. 125The \f5Shbltin_t\fP structure contains a field named \f5shp\fP which is 126a pointer the the shell data that is needed for \f5shell\fP library callbacks. 127It also contains the fields, \f5shrun\fP, \f5shtrap\fP, \f5shexit\fP, 128and \f5shbltin\fP 129that are function pointers to the \f5shell\fP library functions \f5sh_run\fP, \f5sh_trap\fP 130\f5sh_exit\fP, and \f5sh_addbuiltin\fP, respectively. These functions 131can be invoked without the need for runtime symbol lookup when the 132shell is statically linked with \f5libshell\fP. 133.P 134The alternative method is to create a function \f5lib_init\fP and 135use the \f5Shbltin_t.shbltin()\fP function to add one or more built-ins. 136The \f5lib_init\fP function will be called with two arguments. The 137first argument will be 0 when the library is loaded and the second 138argument will be of type \f5Shbltin_t*\fP. 139The \f5dbm_t\fP and \f5dss\fP shell built-ins use this method. 140.P 141No matter which way you add built-ins you should add the line 142\f5SHLIB(\fP\fIidentifier\fP\f5)\fP as the last line of one 143of the built-in source file, where \fIidentifier\fP is any C identifier. 144This line provides version information to the shell \f5builtin\fP command 145that it uses to verify compatibility between the built-in and \f5ksh\fP 146implementation versions. \f5builtin\fP fails with a diagnostic on version 147mismatch. The diagnostic helps determine whether \f5ksh\fP is out of 148date and requires an upgrade or the built-in is out of date and requires 149recompilation. 150.P 151The steps necessary to create and add a run time built-in are 152illustrated in the following simple example. 153Suppose you wish to add a built-in command named \f5hello\fP 154which requires one argument and prints the word hello followed 155by its argument. First, write the following program in the file 156\f5hello.c\fP: 157.EX 158#include <stdio.h> 159int b_hello(int argc, char *argv[], void *context) 160{ 161 if(argc != 2) 162 { 163 fprintf(stderr,"Usage: hello arg\en"); 164 return(2); 165 } 166 printf("hello %s\en",argv[1]); 167 return(0); 168} 169SHLIB(hello) 170.EE 171.P 172Next, the program needs to be compiled. 173If you are building with AT&T \f5nmake\fP use the following \f5Makefile\fP: 174.EX 175:PACKAGE: --shared ast 176hello plugin=ksh :LIBRARY: hello.c 177.EE 178and run \f5nmake install\fP to compile, link, and install the built-in shared library 179in \f5lib/ksh/\fP under \f5PACKAGE_ast\fP. 180If the built-in extension uses several \f5.c\fP files, list all of these on 181the \f5:LIBRARY:\fP line. 182.P 183Otherwise you will have to compile \f5hello.c\fP with an option 184to pick up the AST include directory 185(since the AST \f5<stdio.h>\fP is required for \f5ksh\fP compatibility) 186and options required for generating shared libraries. 187For example, on Linux use this to compile: 188.EX 189cc -fpic -I$PACKAGE_ast/include/ast -c hello.c 190.EE 191and use the appropriate link line. 192It really is best to use \f5nmake\fP because the 2 line Makefile above 193will work on all systems that have \f5ksh\fP installed. 194.P 195If you have several built-ins, it is desirable 196to build a shared library that contains them all. 197.P 198The final step is using the built-in. 199This can be done with the \f5ksh\fP command \f5builtin\fP. 200To load the shared library \f5libhello.so\fP from the current directory 201and add the built-in \f5hello\fP, invoke the command, 202.EX 203builtin -f ./libhello.so hello 204.EE 205The shared library prefix (\f5lib\fP here) and suffix (\f5.so\fP here) be omitted; 206the shell will add an appropriate suffix 207for the system that it is loading from. 208If you install the shared library in \f5lib/ksh/\fP, where \f5../lib/ksh/\fP is 209a directory on \fB$PATH\fP, the command 210.EX 211builtin -f hello hello 212.EE 213will automatically find, load and install the built-in on any system. 214Once this command has been invoked, you can invoke \f5hello\fP 215as you do any other command. 216If you are using \f5lib_init\fP method to add built-ins then no arguments 217follow the \f5\-f\fP option. 218.P 219It is often desirable to make a command \fIbuilt-in\fP 220the first time that it is referenced. The first 221time \f5hello\fP is invoked, \f5ksh\fP should load and execute it, 222whereas for subsequent invocations \f5ksh\fP should just execute the built-in. 223This can be done by creating a file named \f5hello\fP 224with the following contents: 225.EX 226function hello 227{ 228 unset -f hello 229 builtin -f hello hello 230 hello "$@" 231} 232.EE 233This file \f5hello\fP needs to be placed in a directory that is 234in your \fB\s-1FPATH\s+1\fP variable, and the built-in shared library 235should be installed in \f5lib/ksh/\fP, as described above. 236.H 1 "CODING REQUIREMENTS AND CONVENTIONS" 237As mentioned above, the entry point for built-ins must either be of 238the form \f5b_\fP\fIname\fP or else be loaded from a function named 239\f5lib_init\fP. 240Your built-ins can call functions from the standard C library, 241the \f5ast\fP library, interface functions provided by \f5ksh\fP, 242and your own functions. 243You should avoid using any global symbols beginning with 244.BR sh_ , 245.BR nv_ , 246and 247.B ed_ 248since these are used by \f5ksh\fP itself. 249\f5#define\fP constants in \f5ksh\fP interface 250files use symbols beginning with \f5SH_\fP and \f5NV_\fP, 251so avoid using names beginning with these too. 252.H 2 "Header Files" 253The development kit provides a portable interface 254to the C library and to libast. 255The header files in the development kit are compatible with 256K&R C\*(Rf, 257.RS 258Brian W. Kernighan and Dennis M. Ritchie, 259.IR "The C Programming Language" , 260Prentice Hall, 1978. 261.RF 262ANSI-C\*(Rf, 263.RS 264American National Standard for Information Systems \- Programming 265Language \- C, ANSI X3.159-1989. 266.RF 267and C++\*(Rf. 268.RS 269Bjarne Stroustroup, 270.IR "C++" , 271Addison Wesley, xxxx 272.RF 273.P 274The best thing to do is to include the header file \f5<shell.h>\fP. 275This header file causes the \f5<ast.h>\fP header, the 276\f5<error.h>\fP header and the \f5<stak.h>\fP 277header to be included as well as defining prototypes 278for functions that you can call to get shell 279services for your builtins. 280The header file \f5<ast.h>\fP 281provides prototypes for many \fBlibast\fP functions 282and all the symbol and function definitions from the 283ANSI-C headers, \f5<stddef.h>\fP, 284\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP, 285and \f5<string.h>\fP. 286It also provides all the symbols and definitions for the 287POSIX\*(Rf 288.RS 289.I "POSIX \- Part 1: System Application Program Interface," 290IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990. 291.RF 292headers \f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and 293\f5<unistd.h>\fP. 294You should include \f5<ast.h>\fP instead of one or more of 295these headers. 296The \f5<error.h>\fP header provides the interface to the error 297and option parsing routines defined below. 298The \f5<stak.h>\fP header provides the interface to the memory 299allocation routines described below. 300.P 301Programs that want to use the information in \f5<sys/stat.h>\fP 302should include the file \f5<ls.h>\fP instead. 303This provides the complete POSIX interface to \f5stat()\fP 304related functions even on non-POSIX systems. 305.P 306.H 2 "Input/Output" 307\f5ksh\fP uses \fBsfio\fP, 308the Safe/Fast I/O library\*(Rf, 309.RS 310David Korn and Kiem-Phong Vo, 311.IR "SFIO - A Safe/Fast Input/Output library," 312Proceedings of the Summer Usenix, 313pp. , 1991. 314.RF 315to perform all I/O operations. 316The \fBsfio\fP library, which is part of \fBlibast\fP, 317provides a superset of the functionality provided by the standard 318I/O library defined in ANSI-C. 319If none of the additional functionality is required, 320and if you are not familiar with \fBsfio\fP and 321you do not want to spend the time learning it, 322then you can use \f5sfio\fP via the \f5stdio\fP library 323interface. The development kit contains the header \f5<stdio.h>\fP 324which maps \f5stdio\fP calls to \f5sfio\fP calls. 325In most instances the mapping is done 326by macros or inline functions so that there is no overhead. 327The man page for the \f5sfio\fP library is in an Appendix. 328.P 329However, there are some very nice extensions and 330performance improvements in \f5sfio\fP 331and if you plan any major extensions I recommend 332that you use it natively. 333.H 2 "Error Handling" 334For error messages it is best to use the \f5ast\fP library 335function \f5errormsg()\fP rather that sending output to 336\f5stderr\fP or the equivalent \f5sfstderr\fP directly. 337Using \f5errormsg()\fP will make error message appear 338more uniform to the user. 339Furthermore, using \f5errormsg()\fP should make it easier 340to do error message translation for other locales 341in future versions of \f5ksh\fP. 342.P 343The first argument to 344\f5errormsg()\fP specifies the dictionary in which the string 345will be searched for translation. 346The second argument to \f5errormsg()\fP contains that error type 347and value. The third argument is a \fIprintf\fP style format 348and the remaining arguments are arguments to be printed 349as part of the message. A new-line is inserted at the 350end of each message and therefore, should not appear as 351part of the format string. 352The second argument should be one of the following: 353.VL .5i 354.LI \f5ERROR_exit(\fP\fIn\fP\f5)\fP: 355If \fIn\fP is not-zero, the builtin will exit value \fIn\fP after 356printing the message. 357.LI \f5ERROR_system(\fP\fIn\fP\f5)\fP: 358Exit builtin with exit value \fIn\fP after printing the message. 359The message will display the message corresponding to \f5errno\fP 360enclosed within \f5[\ ]\fP at the end of the message. 361.LI \f5ERROR_usage(\fP\fIn\fP\f5)\fP: 362Will generate a usage message and exit. If \fIn\fP is non-zero, 363the exit value will be 2. Otherwise the exit value will be 0. 364.LI \f5ERROR_debug(\fP\fIn\fP\f5)\fP: 365Will print a level \fIn\fP debugging message and will then continue. 366.LI \f5ERROR_warn(\fP\fIn\fP\f5)\fP: 367Prints a warning message. \fIn\fP is ignored. 368.H 2 "Option Parsing" 369The first thing that a built-in should do is to check 370the arguments for correctness and to print any usage 371messages on standard error. 372For consistency with the rest of \f5ksh\fP, it is best 373to use the \f5libast\fP functions \f5optget()\fP and 374\f5optusage()\fPfor this 375purpose. 376The header \f5<error.h>\fP includes prototypes for 377these functions. 378The \f5optget()\fP function is similar to the 379System V C library function \f5getopt()\fP, 380but provides some additional capabilities. 381Built-ins that use \f5optget()\fP provide a more 382consistent user interface. 383.P 384The \f5optget()\fP function is invoked as 385.EX 386int optget(char *\fIargv\fP[], const char *\fIoptstring\fP) 387.EE 388where \f5argv\fP is the argument list and \f5optstring\fP 389is a string that specifies the allowable arguments and 390additional information that is used to format \fIusage\fP 391messages. 392In fact a complete man page in \f5troff\fP or \f5html\fP 393can be generated by passing a usage string as described 394by the \f5getopts\fP command. 395Like \f5getopt()\fP, 396single letter options are represented by the letter itself, 397and options that take a string argument are followed by the \f5:\fP 398character. 399Option strings have the following special characters: 400.VL .5i 401.LI \f5:\fP 402Used after a letter option to indicate that the option 403takes an option argument. 404The variable \f5opt_info.arg\fP will point to this 405value after the given argument is encountered. 406.LI \f5#\fP 407Used after a letter option to indicate that the option 408can only take a numerical value. 409The variable \f5opt_info.num\fP will contain this 410value after the given argument is encountered. 411.LI \f5?\fP 412Used after a \f5:\fP or \f5#\fP (and after the optional \f5?\fP) 413to indicate the the 414preceding option argument is not required. 415.LI \f5[\fP...\f5]\fP 416After a \f5:\fP or \f5#\fP, the characters contained 417inside the brackets are used to identify the option 418argument when generating a \fIusage\fP message. 419.LI \fIspace\fP 420The remainder of the string will only be used when generating 421usage messages. 422.LE 423.P 424The \f5optget()\fP function returns the matching option letter if 425one of the legal option is matched. 426Otherwise, \f5optget()\fP returns 427.VL .5i 428.LI \f5':'\fP 429If there is an error. In this case the variable \f5opt_info.arg\fP 430contains the error string. 431.LI \f50\fP 432Indicates the end of options. 433The variable \f5opt_info.index\fP contains the number of arguments 434processed. 435.LI \f5'?'\fP 436A usage message has been required. 437You normally call \f5optusage()\fP to generate and display 438the usage message. 439.LE 440.P 441The following is an example of the option parsing portion 442of the \f5wc\fP utility. 443.EX 444#include <shell.h> 445while(1) switch(n=optget(argv,"xf:[file]")) 446{ 447 case 'f': 448 file = opt_info.arg; 449 break; 450 case ':': 451 error(ERROR_exit(0), opt_info.arg); 452 break; 453 case '?': 454 error(ERROR_usage(2), opt_info.arg); 455 break; 456} 457.EE 458.H 2 "Storage Management" 459It is important that any memory used by your built-in 460be returned. Otherwise, if your built-in is called frequently, 461\f5ksh\fP will eventually run out of memory. 462You should avoid using \f5malloc()\fP for memory that must 463be freed before returning from you built-in, because by default, 464\f5ksh\fP will terminate you built-in in the event of an 465interrupt and the memory will not be freed. 466.P 467The best way to to allocate variable sized storage is 468through calls to the \fBstak\fP library 469which is included in \fBlibast\fP 470and which is used extensively by \f5ksh\fP itself. 471Objects allocated with the \f5stakalloc()\fP 472function are freed when you function completes 473or aborts. 474The \fBstak\fP library provides a convenient way to 475build variable length strings and other objects dynamically. 476The man page for the \fBstak\fP library is contained 477in the Appendix. 478.P 479Before \f5ksh\fP calls each built-in command, it saves 480the current stack location and restores it after 481it returns. 482It is not necessary to save and restore the stack 483location in the \f5b_\fP entry function, 484but you may want to write functions that use this stack 485are restore it when leaving the function. 486The following coding convention will do this in 487an efficient manner: 488.EX 489\fIyourfunction\fP() 490{ 491 char *savebase; 492 int saveoffset; 493 if(saveoffset=staktell()) 494 savebase = stakfreeze(0); 495 \fR...\fP 496 if(saveoffset) 497 stakset(savebase,saveoffset); 498 else 499 stakseek(0); 500} 501.EE 502.H 1 "CALLING \f5ksh\fP SERVICES" 503Some of the more interesting applications are those that extend 504the functionality of \f5ksh\fP in application specific directions. 505A prime example of this is the X-windows extension which adds 506builtins to create and delete widgets. 507The \fBnval\fP library is used to interface with the shell 508name space. 509The \fBshell\fP library is used to access other shell services. 510.H 2 "The nval library" 511A great deal of power is derived from the ability to use 512portions of the hierarchal variable namespace provided by \f5ksh-93\fP 513and turn these names into active objects. 514.P 515The \fBnval\fP library is used to interface with shell 516variables. 517A man page for this file is provided in an Appendix. 518You need to include the header \f5<nval.h>\fP 519to access the functions defined in the \fBnval\fP library. 520All the functions provided by the \fBnval\fP library begin 521with the prefix \f5nv_\fP. 522Each shell variable is an object in an associative table 523that is referenced by name. 524The type \f5Namval_t*\fP is pointer to a shell variable. 525To operate on a shell variable, you first get a handle 526to the variable with the \f5nv_open()\fP function 527and then supply the handle returned as the first 528argument of the function that provides an operation 529on the variable. 530You must call \f5nv_close()\fP when you are finished 531using this handle so that the space can be freed once 532the value is unset. 533The two most frequent operations are to get the value of 534the variable, and to assign value to the variable. 535The \f5nv_getval()\fP returns a pointer the the 536value of the variable. 537In some cases the pointer returned is to a region that 538will be overwritten by the next \f5nv_getval()\fP call 539so that if the value isn't used immediately, it should 540be copied. 541Many variables can also generate a numeric value. 542The \f5nv_getnum()\fP function returns a numeric 543value for the given variable pointer, calling the 544arithmetic evaluator if necessary. 545.P 546The \f5nv_putval()\fP function is used to assign a new 547value to a given variable. 548The second argument to \f5putval()\fP is the value 549to be assigned 550and the third argument is a \fIflag\fP which 551is used in interpreting the second argument. 552.P 553Each shell variable can have one or more attributes. 554The \f5nv_isattr()\fP is used to test for the existence 555of one or more attributes. 556See the appendix for a complete list of attributes. 557.P 558By default, each shell variable passively stores the string you 559give with with \f5nv_putval()\fP, and returns the value 560with \f5getval()\fP. However, it is possible to turn 561any node into an active entity by assigning functions 562to it that will be called whenever \f5nv_putval()\fP 563and/or \f5nv_getval()\fP is called. 564In fact there are up to five functions that can 565associated with each variable to override the 566default actions. 567The type \f5Namfun_t\fP is used to define these functions. 568Only those that are non-\f5NULL\fP override the 569default actions. 570To override the default actions, you must allocate an 571instance of \f5Namfun_t\fP, and then assign 572the functions that you wish to override. 573The \f5putval()\fP 574function is called by the \f5nv_putval()\fP function. 575A \f5NULL\fP for the \fIvalue\fP argument 576indicates a request to unset the variable. 577The \fItype\fP argument might contain the \f5NV_INTEGER\fP 578bit so you should be prepared to do a conversion if 579necessary. 580The \f5getval()\fP 581function is called by \f5nv_getval()\fP 582value and must return a string. 583The \f5getnum()\fP 584function is called by by the arithmetic evaluator 585and must return double. 586If omitted, then it will call \f5nv_getval()\fP and 587convert the result to a number. 588.P 589The functionality of a variable can further be increased 590by adding discipline functions that 591can be associated with the variable. 592A discipline function allows a script that uses your 593variable to define functions whose name is 594\fIvarname\fP\f5.\fP\fIdiscname\fP 595where \fIvarname\fP is the name of the variable, and \fIdiscname\fP 596is the name of the discipline. 597When the user defines such a function, the \f5settrap()\fP 598function will be called with the name of the discipline and 599a pointer to the parse tree corresponding to the discipline 600function. 601The application determines when these functions are actually 602executed. 603By default, \f5ksh\fP defines \f5get\fP, 604\f5set\fP, and \f5unset\fP as discipline functions. 605.P 606In addition, it is possible to provide a data area that 607will be passed as an argument to 608each of these functions whenever any of these functions are called. 609To have private data, you need to define and allocate a structure 610that looks like 611.EX 612struct \fIyours\fP 613{ 614 Namfun_t fun; 615 \fIyour_data_fields\fP; 616}; 617.EE 618.H 2 "The shell library" 619There are several functions that are used by \f5ksh\fP itself 620that can also be called from built-in commands. 621The man page for these routines are in the Appendix. 622.P 623The \f5sh_addbuiltin()\fP function can be used to add or delete 624builtin commands. It takes the name of the built-in, the 625address of the function that implements the built-in, and 626a \f5void*\fP pointer that will be passed to this function 627as the third agument whenever it is invoked. 628If the function address is \f5NULL\fP, the specified built-in 629will be deleted. However, special built-in functions cannot 630be deleted or modified. 631.P 632The \f5sh_fmtq()\fP function takes a string and returns 633a string that is quoted as necessary so that it can 634be used as shell input. 635This function is used to implement the \f5%q\fP option 636of the shell built-in \f5printf\fP command. 637.P 638The \f5sh_parse()\fP function returns a parse tree corresponding 639to a give file stream. The tree can be executed by supplying 640it as the first argument to 641the \f5sh_trap()\fP function and giving a value of \f51\fP as the 642second argument. 643Alternatively, the \f5sh_trap()\fP function can parse and execute 644a string by passing the string as the first argument and giving \f50\fP 645as the second argument. 646.P 647The \f5sh_isoption()\fP function can be used to set to see whether one 648or more of the option settings is enabled. 649