Developing Wrappers

The following sections describe some basic information about how to develop wrappers. Refer to Part 6 of this book for an introduction to shell programming.

Interpreter Choice

You typically write wrapper scripts in an interpreted language so that they can execute on the various platform configurations in the environment. If you are going to write wrappers, you must decide which interpreter to use. The Solaris Operating Environment provides three shells that make suitable interpreters for wrappers, as noted in Table 68.

Table 68. Available Shells
Shell Description
/bin/sh Bourne shell.
/bin/ksh Korn shell.
/bin/csh C shell.

NOTE

The Solaris 8 Operating Environment also includes three freeware shells: The Bourne-Again shell (bash), the TC shell (tcsh), and the Z shell (zsh).


Sun recommends that you use the Bourne shell to write wrappers. Although the C shell is popular for interactive use, the Bourne shell is more advanced as a programming language. The C shell is also less portable because there are more feature variations between UNIX platforms. The Bourne shell supports functions—which result in code that is reusable in other wrappers—and the ability to pipe into and out of control constructs. The examples in this chapter use Bourne shell syntax.

NOTE

In an environment that is so heterogeneous that even the Bourne shell is not universally available, you would have to seek yet another interpreter, possibly Perl.


As with all shell scripts, the first line in the script specifies the shell. The following example shows the first line in a Bourne shell wrapper script.

#!/bin/sh

Wrapper Directory and Naming

Create a subdirectory in the application directory, for example, /usr/apps/pkgs/application-name/dist. Within that directory, create a wrapper that has the same name as the other wrappers. For example, name each wrapper wrapper (for example, /usr/apps/pkgs/application-name/dist/wrapper). When you use the same name for each application wrapper, it simplifies administration because you do not need to remember a host of different wrapper names. You can easily create links to any wrapper.

Command Name Evaluation

One of the first things a wrapper must do is evaluate the name that was used to invoke it. The wrapper has its own name. The wrapper name is different from any of the application command names, but the wrapper must know which command name it is being asked to represent.

For example, for package footool,v2.0, the foo command is a link to the script called wrapper that is located in the /usr/apps/pkgs/footool,v2.0/dist directory. When a user types foo, the wrapper learns the name used to invoke it from the construct $0. In this case, $0 is /usr/apps/exe/foo. The /bin/basename command is used to strip the leading path, and foo is assigned to the variable cmd, as shown below.

cmd=`/bin/basename $0`

Environment Variables

Many applications require that you assign environment variables before you can execute the application. Environment variables usually are values that cannot be reliably predicted by the compiled code, such as the directory where the application is installed. Such variables must be set and exported to be available to subsequently executing processes, just as they would be from a user's dot files. The Bourne shell syntax is shown below.

export FOOHOME
FOOHOME=/usr/apps/pkgs/footool,v2.0

NOTE

You can export the environment variable either before or after you assign it a value. Once you export an environment variable, it remains exported for the remainder of the script, even if you modify it. So, you need to export an environment variable only once within a script.


Platform Evaluation

Not all applications support all combinations of hardware platforms and operating systems that may be in your environment. Therefore, you need to evaluate the user's platform to see if service can be provided.

For example, if footool,v2.0 supports only the sun4u platform, the code shown here declines service (politely) to all other platforms.

case `uname -m` in
      sun4u)
               ;;
      *)
               echo >&2 "Sorry, $cmd not available for `uname -m`
 architecture."
               exit 1
               ;;
esac

Command Path Construction

Next, you define the variable command in terms of code that yields the complete execution path to the application binary.

NOTE

The wrapper may not, in fact, execute the binary itself but instead may invoke a link that the vendor has routed through its own wrapper, as is the case with the FrameMaker product.


In the footool,v2.0 wrapper, you might write a command path definition, as shown in the following example.

command=$FOOHOME/bin.`uname -m`/$cmd

The command path definition could be more complex, or it could be as simple as that shown in the following example.

command=$FOOHOME/bin/$cmd

Exec/Argument Passing

The wrapper has now made its assignments and calculations and has determined that the service is available for this user. It is time to hand off execution to the application and get out of the way, via the exec statement. The wrapper process has navigated to the correct binary and passed on the necessary environment. It then vanishes and imposes no further burden.

The last action of the wrapper is to make sure that any arguments the user included on the original command line get through exactly as expressed, which is the purpose of the ${1+"$@"} construct at the end of the exec statement shown in the following example.

exec $command ${1+"$@"}

A Basic Wrapper

At this point, the basic wrapper looks like the example below.

#!/bin/sh
       cmd=`/bin/basename $0`
       export FOOHOME
       FOOHOME=/usr/apps/pkgs/footool,v2.0
       case `uname -m` in
             sun4u)
                     ;;
             *)
                     echo >&2 "Sorry, $cmd not available for `uname -m`
                     architecture."
                     exit 1
                     ;;
       esac
       command=$FOOHOME/bin/$cmd
       exec $command ${1+"$@"}

The wrapper example is not quite complete; it does not consider how `uname -m` gets defined. The code necessary to assess architecture varies depending on the mix of platforms in the environment. However, in a given environment, you would need to use this same code for many wrappers. You can create the code as a Bourne shell function that can be replicated in as many wrappers as necessary.

In fact, for ease of maintenance, you might choose to make this code one function among others in a library external to the wrappers themselves. The wrappers requiring this function then merely source it from the library and execute it at the appropriate point in the wrapper. In this way, you often can carry out maintenance required by the wrappers by updating the library that supports all the wrappers. See Chapter 19 for some examples of wrapper functions.

If you provide a function library, be sure to use a consistent naming convention so that the wrappers can access and source the wrapper functions. You may want to apply the version-naming convention to this directory as well. For example, you might create a directory named /usr/apps/library,v1.0.

When a function library exists, you use the functions in scripts by defining the library location and sourcing the function script at the beginning of the wrapper. Next, you would execute the function at the appropriate point in the wrapper to return the values required. Remember, our wrapper example here is intentionally basic. The bold lines in the following example show the additions made to the basic script. See “arch.sh.fctn Function” for an example of the function arch.sh.fctn.

#!/bin/sh
library=/usr/apps/pkgs/library,v1.0
							. $library/sh/arch.sh.fctn
cmd=`/bin/basename $0`
export FOOHOME
FOOHOME=/usr/apps/pkgs/footool,v2.0
case `uname -m` in
      sun4u)
          ;;
     *)
          echo >&2 "Sorry, $cmd not available for `uname -m` architecture."
          exit 1
          ;;
esac
command=$FOOHOME/bin/$cmd
exec $command ${1+"$@"}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.12.207