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