<?Pub UDT _bookmark _target?><?Pub EntList bull rArr sect?><chapter id="ch3enhancepkg-11350"><title>Enhancing the Functionality of a
Package (Tasks)</title><highlights><para>This chapter describes how to create optional information files and
installation scripts for a package. While <olink targetptr="ch2buildpkg-22939" remap="internal">Chapter&nbsp;2,
Building a Package</olink> discussed the minimum requirements for making a
package, this chapter discusses additional functionality that you can build
into a package. This additional functionality is based on the criteria you
considered when planning how to design your package. For more information,
see <olink targetptr="ch1designpkg-28244" remap="internal">Considerations Before Building a
Package</olink>.</para><para>This is a list of the overview information in this chapter.</para><itemizedlist><listitem><para><olink targetptr="ch3enhancepkg-1" remap="internal">Creating Information Files
and Installation Scripts (Task Map)</olink></para>
</listitem><listitem><para><olink targetptr="ch3enhancepkg-31830" remap="internal">Creating Information
Files</olink></para>
</listitem><listitem><para><olink targetptr="ch3enhancepkg-10289" remap="internal">Creating Installation
Scripts</olink></para>
</listitem><listitem><para><olink targetptr="ch6advtech-108" remap="internal">Creating Signed Packages</olink></para>
</listitem>
</itemizedlist>
</highlights><sect1 id="ch3enhancepkg-1"><title>Creating Information Files and Installation
Scripts (Task Map)</title><para>The following task map describes the optional features you can build
into a package.</para><table frame="all" pgwide="1" id="ch3enhancepkg-tbl-44"><title>Creating Information
Files and Installation Scripts (Task Map)</title><tgroup cols="3" colsep="1" rowsep="1"><colspec colwidth="110*"/><colspec colname="col2" colwidth="167*"/><colspec colwidth="119*"/><thead><row><entry><para>Task</para>
</entry><entry><para>Description</para>
</entry><entry><para>For Instructions</para>
</entry>
</row>
</thead><tbody><row><entry><para>1. Create information files</para>
</entry><entry><para><emphasis>Define package dependencies</emphasis></para><para>A definition of package dependencies allows you to specify whether your
package is compatible with previous versions, dependent on other packages,
or whether other packages are dependent on yours.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-116" remap="internal">How to Define Package Dependencies</olink></para>
</entry>
</row><row><entry>
</entry><entry><para><emphasis>Write a copyright message</emphasis></para><para>A <filename>copyright</filename> file provides legal protection for
your software application.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-117" remap="internal">How to Write a Copyright Message</olink></para>
</entry>
</row><row><entry>
</entry><entry><para><emphasis>Reserve additional space on the target system</emphasis>.</para><para>A <filename>space</filename> file sets aside blocks on the target system,
which enables you to create files during installation that are not defined
in the <filename>pkgmap</filename> file.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-118" remap="internal">How to Reserve Additional Space
on a Target System</olink></para>
</entry>
</row><row><entry><para>2. Create installation scripts</para>
</entry><entry><para><emphasis>Obtain information from the installer</emphasis></para><para>A <filename>request</filename> script enables you to obtain information
from the person installing your package.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-119" remap="internal">How to Write a request Script</olink></para>
</entry>
</row><row><entry>
</entry><entry><para><emphasis>Gather file system data needed for installation</emphasis></para><para>A <filename>checkinstall</filename> script enables you to perform an
analysis of the target system and set up the correct environment for, or cleanly
halt, the installation.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-120" remap="internal">How to Gather File System Data</olink></para>
</entry>
</row><row><entry>
</entry><entry><para><emphasis>Write procedure scripts</emphasis></para><para>Procedure scripts enable you to provide customized installation instructions
during specific phases of the installation or removal process.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-121" remap="internal">How to Write Procedure Scripts</olink></para>
</entry>
</row><row><entry>
</entry><entry><para><emphasis>Write class action scripts</emphasis></para><para>Class action scripts enable you to specify a set of instructions to
be executed during package installation and removal on specific groups of
package objects.</para>
</entry><entry><para><olink targetptr="ch3enhancepkg-122" remap="internal">How to Write Class Action Scripts</olink></para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1><sect1 id="ch3enhancepkg-31830"><title>Creating Information Files</title><para>This section discusses optional package information files. With these
files you can define package dependencies, provide a copyright message, and
reserve additional space on a target system.</para><sect2 id="ch3enhancepkg-28289"><title>Defining Package Dependencies</title><para>You need to determine whether your package has dependencies on other
packages and if any other packages depend on yours. Package dependencies and
incompatibilities can be defined with two of the optional package information
files, <filename>compver</filename> and <filename>depend</filename>.</para><para>Delivering a <filename>compver</filename> file lets you name previous
versions of your package that are compatible with the package being installed.</para><para><indexterm><primary>package</primary><secondary>defining dependencies</secondary></indexterm><indexterm><primary><filename>compver</filename> file</primary><secondary>description</secondary></indexterm><indexterm><primary><filename>depend</filename> file</primary><secondary>description</secondary></indexterm>Delivering
a <filename>depend</filename> file lets you define three types of dependencies
associated with your package. These dependency types are as follows:</para><itemizedlist><listitem><para><indexterm><primary>prerequisite package</primary></indexterm>A <firstterm>prerequisite package</firstterm> &ndash; Your package depends on the existence
of another package</para>
</listitem><listitem><para><indexterm><primary>reverse dependency</primary></indexterm>A <firstterm>reverse dependency</firstterm> &ndash; Another package depends on the existence
of your package </para><note><para>Use the reverse dependency type only when a package that cannot
deliver a <filename>depend</filename> file relies on your package.</para>
</note>
</listitem><listitem><para><indexterm><primary>incompatible package</primary></indexterm>An <firstterm>incompatible package</firstterm> &ndash; Your package is incompatible with
the named package</para>
</listitem>
</itemizedlist><para><indexterm><primary><filename>request</filename> script</primary><secondary>dependency checking</secondary></indexterm><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>dependency checking</secondary></indexterm>The <filename>depend</filename> file resolves only very basic
dependencies. If your package depends upon a specific file, its contents,
or its behavior, the <filename>depend</filename> file does not supply adequate
precision. In this case, a <filename>request</filename> script or the <filename>checkinstall</filename> script should be used for detailed dependency checking. The <filename>checkinstall</filename> script is also the only script capable of cleanly
halting the package installation process.</para><note><para>Be certain that your <filename>depend</filename> and <filename>compver</filename> files have entries in the <filename>prototype</filename> file.
The file type should be <literal>i</literal> (for package information file).</para>
</note><para>Refer to the <olink targetdoc="refman4" targetptr="depend-4" remap="external"><citerefentry><refentrytitle>depend</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> and <olink targetdoc="refman4" targetptr="compver-4" remap="external"><citerefentry><refentrytitle>compver</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> man pages for more information. </para>
</sect2><task id="ch3enhancepkg-116"><title>How to Define Package Dependencies</title><procedure><step id="ch3enhancepkg-step-6"><para><indexterm><primary>package dependencies</primary><secondary>how to define</secondary></indexterm><indexterm><primary><filename>compver</filename> file</primary><secondary>how to write</secondary></indexterm><indexterm><primary><filename>depend</filename> file</primary><secondary>how to write</secondary></indexterm>Make the directory that contains your information files the current
working directory.</para>
</step><step id="ch3enhancepkg-step-7"><para>If previous versions of your package
exist and you need to specify that your new package is compatible with them,
create a file named <filename>compver</filename> with your favorite text editor.</para><para>List the versions with which your package is compatible. Use this format:</para><screen><replaceable>string string . . .</replaceable></screen><para>The value of <replaceable>string</replaceable> is identical to the value
assigned to the <envar>VERSION</envar> parameter in the <filename>pkginfo</filename> file,
for each compatible package.</para>
</step><step id="ch3enhancepkg-step-112"><para>Save your changes and quit the editor.</para>
</step><step id="ch3enhancepkg-step-8"><para>If your package depends on the existence
of other packages, other packages depend on the existence of your package,
or your package is incompatible with another package, create a file named <filename>depend</filename> with your favorite text editor.</para><para>Add an entry
for each dependency. Use this format:</para><screen><replaceable>type pkg-abbrev pkg-name</replaceable>
    (<replaceable>arch</replaceable>)<replaceable> version</replaceable>
    (<replaceable>arch</replaceable>)<replaceable> version . . .</replaceable></screen><variablelist><varlistentry><term><replaceable>type</replaceable></term><listitem><para>Defines the dependency type. Must be one of the following
characters: <literal>P</literal> (prerequisite package), <literal>I</literal> (incompatible
package), or <literal>R</literal> (reverse dependency).</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>pkg-abbrev</replaceable></term><listitem><para>Specifies the package abbreviation, such as <literal>SUNWcadap</literal>.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>pkg-name</replaceable></term><listitem><para>Specifies the full package name, such as <literal>Chip designers
need CAD application software to design abc chips.  Runs only on xyz hardware
and is installed in the usr partition.</literal></para>
</listitem>
</varlistentry><varlistentry><term>(<replaceable>arch</replaceable>)</term><listitem><para>Optional. Specifies the type of hardware on which the package
runs. For example, <literal>sparc</literal> or <literal>x86</literal>. If
you specify an architecture, you must use the parentheses as delimiters.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>version</replaceable></term><listitem><para>Optional. Specifies the value assigned to the <envar>VERSION</envar>	parameter
in the <filename>pkginfo</filename> file.</para>
</listitem>
</varlistentry>
</variablelist><para>For more information, see <olink targetdoc="refman4" targetptr="depend-4" remap="external"><citerefentry><refentrytitle>depend</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink>.</para>
</step><step id="ch3enhancepkg-step-45"><para>Save your changes and quit the editor.</para>
</step><step id="ch3enhancepkg-step-94"><para>Complete <emphasis>one</emphasis> of
the following tasks:</para><itemizedlist><listitem><para>If you want to create additional information files and installation
scripts, skip to the next task, <olink targetptr="ch3enhancepkg-117" remap="internal">How to
Write a Copyright Message</olink>.</para>
</listitem><listitem><para>If you have not created your <filename>prototype</filename> file,
complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How to Create a prototype
File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-62" remap="internal">Step&nbsp;7</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for each file you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-62"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><example id="ch3enhancepkg-3"><title><filename>compver</filename> File</title><para><indexterm><primary><filename>compver</filename> file</primary><secondary>example</secondary></indexterm>In this example, there are four versions of a package:
1.0, 1.1, 2.0, and the new package, 3.0. The new package is compatible with
all the three previous versions. The <filename>compver</filename> file for
the newest version might look like the following:</para><screen>release 3.0
release 2.0
version 1.1
1.0</screen><para>The entries do not have to be in sequential order. However,
they should exactly match the definition of the <envar>VERSION</envar> parameter
in each package's <filename>pkginfo</filename> file. In this example, the
package designers used different formats in the first three versions.</para>
</example><example id="ch3enhancepkg-4"><title><filename>depend</filename> File</title><para><indexterm><primary><filename>depend</filename> file</primary><secondary>example</secondary></indexterm>This example assumes that the sample package, <literal>SUNWcadap</literal>, requires that the <literal>SUNWcsr</literal> and <literal>SUNWcsu</literal> packages
already be installed on a target system. The <filename>depend</filename> file
for <literal>SUNWcadap</literal> looks like the following:</para><screen>P SUNWcsr Core Solaris, (Root)
P SUNWcsu Core Solaris, (Usr)</screen>
</example><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task><sect2 id="ch3enhancepkg-32564"><title>Writing a Copyright Message</title><para><indexterm id="ch3enhancepkg-ix23"><primary><filename>copyright</filename> file</primary><secondary>writing a</secondary></indexterm>You need to decide whether
your package should display a copyright message while it is being installed.
If so, create the <filename>copyright</filename> file. </para><note><para>You should include a <filename>copyright</filename> file to provide
legal protection for your software application. Check with the legal department
of your company for the exact wording of the message.</para>
</note><para>To deliver a copyright message, you must create a file named <filename>copyright</filename>. During installation, the message is displayed exactly as it appears
in the file (with no formatting). See the <olink targetdoc="refman4" targetptr="copyright-4" remap="external"><citerefentry><refentrytitle>copyright</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> man page for more information. </para><note><para>Be certain that your <filename>copyright</filename> file has an
entry in the <filename>prototype</filename> file. The file type should be <literal>i</literal> (for package information file). </para>
</note>
</sect2><task id="ch3enhancepkg-117"><title>How to Write a Copyright Message</title><procedure><step id="ch3enhancepkg-step-12"><para><indexterm><primary><filename>copyright</filename> file</primary><secondary>how to write</secondary></indexterm>Make the directory
that contains your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-13"><para>Create a file named <filename>copyright</filename> with
your favorite text editor.</para><para>Type the text of the copyright message
exactly as you want it to appear as your package is installed.</para>
</step><step id="ch3enhancepkg-step-46"><para>Save your changes and quit the editor.</para>
</step><step id="ch3enhancepkg-step-96"><para>Complete <emphasis>one</emphasis> of
the following tasks.</para><itemizedlist><listitem><para>If you want to create additional information files and installation
scripts, skip to the next task, <olink targetptr="ch3enhancepkg-118" remap="internal">How to
Reserve Additional Space on a Target System</olink>.</para>
</listitem><listitem><para>If you have <emphasis>not</emphasis> created your <filename>prototype</filename> file, complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How
to Create a prototype File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-61" remap="internal">Step&nbsp;5</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for the information file you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-61"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><example id="ch3enhancepkg-10"><title><filename>copyright</filename> File</title><para><indexterm><primary><filename>copyright</filename> file</primary><secondary>example</secondary></indexterm>For example, a partial copyright
message might look like the following:</para><screen>Copyright (c) 2003 <replaceable>Company Name</replaceable>
All Rights Reserved
 
This product is protected by copyright and distributed under
licenses restricting copying, distribution, and decompilation.</screen>
</example><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task><sect2 id="ch3enhancepkg-10245"><title>Reserving Additional Space on a Target
System</title><para><indexterm><primary>reserving additional space on a target system</primary></indexterm><indexterm id="ch3enhancepkg-ix24"><primary><filename>space</filename> file</primary></indexterm>You need to determine whether your package needs additional
disk space on the target system. This space is in addition to the space required
by the package objects. If so, create the <filename>space</filename> information
file. This task is different than creating empty files and directories at
installation time, as discussed in <olink targetptr="ch2buildpkg-28" remap="internal">Defining
Additional Objects to Be Created at Install Time</olink>.</para><para><indexterm><primary><command>pkgadd</command> command</primary><secondary>and disk space</secondary></indexterm><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>reserving additional space on a target system</secondary></indexterm>The <command>pkgadd</command> command ensures that there is enough
disk space to install your package based on the object definitions in the <filename>pkgmap</filename> file. However, a package may require additional disk space
beyond that needed by the objects defined in the <filename>pkgmap</filename> file.
For example, your package might create a file after installation, which may
contain a database, log files, or some other growing file that consumes disk
space. To be sure that there is space reserved for it, you should include
a <filename>space</filename> file that specifies the disk space requirements.
The <command>pkgadd</command> command checks for the additional space specified
in a <filename>space</filename> file. Refer to the <olink targetdoc="refman4" targetptr="space-4" remap="external"><citerefentry><refentrytitle>space</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> man page for more information. </para><note><para>Be certain that your <filename>space</filename> file has an entry
in the <filename>prototype</filename> file. The file type should be <literal>i</literal> (for
package information file). </para>
</note>
</sect2><task id="ch3enhancepkg-118"><title>How to Reserve Additional Space on a Target
System</title><procedure><step id="ch3enhancepkg-step-17"><para><indexterm><primary><filename>space</filename> file</primary><secondary>how to create a</secondary></indexterm>Make the directory
that contains your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-18"><para>Create a file named <filename>space</filename> with
your favorite text editor.</para><para>Specify any additional disk space requirements
needed by your package. Use this format:</para><screen><replaceable>pathname </replaceable> <replaceable>blocks </replaceable> <replaceable>inodes</replaceable></screen><variablelist><varlistentry><term><replaceable>pathname</replaceable></term><listitem><para>Specifies a directory name, which may or may not be the mount
point for a file system.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>blocks</replaceable></term><listitem><para>Specifies the number of 512-byte blocks that you want reserved.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>inodes</replaceable></term><listitem><para>Specifies the number of required inodes.</para>
</listitem>
</varlistentry>
</variablelist><para>For more information, see the <olink targetdoc="refman4" targetptr="space-4" remap="external"><citerefentry><refentrytitle>space</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> man page.</para>
</step><step id="ch3enhancepkg-step-47"><para>Save your changes and quit the editor.</para>
</step><step id="ch3enhancepkg-step-98"><para>Complete one of the following tasks.</para><itemizedlist><listitem><para>If you want to create installation scripts, skip to the next
task, <olink targetptr="ch3enhancepkg-119" remap="internal">How to Write a request Script</olink>.</para>
</listitem><listitem><para>If you have not created your <filename>prototype</filename> file,
complete the procedure in <olink targetptr="ch2buildpkg-64" remap="internal">How to Create
a prototype File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-19" remap="internal">Step&nbsp;5</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for the information file you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-19"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><example id="ch3enhancepkg-15"><title><filename>space</filename> File</title><para><indexterm><primary><filename>space</filename> file</primary><secondary>example</secondary></indexterm>This example <filename>space</filename> file specifies
that 1000 512-byte blocks and 1 inode be reserved in the <filename>/opt</filename> directory
on the target system.</para><screen>/opt   1000   1</screen>
</example><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task>
</sect1><sect1 id="ch3enhancepkg-10289"><title>Creating Installation Scripts</title><para><indexterm id="ch3enhancepkg-ix25"><primary>installation scripts</primary><secondary>creating</secondary></indexterm><indexterm><primary>installation scripts</primary><secondary>requirements for</secondary></indexterm><indexterm><primary><command>pkgadd</command> command</primary><secondary>and installation scripts</secondary></indexterm>This section discusses optional package installation
scripts. The <command>pkgadd</command> command automatically performs all
the actions necessary to install a package using the package information files
as input. You do <emphasis>not</emphasis> have to supply any package installation
scripts. However, if you want to create customized installation procedures
for your package, you can do so with installation scripts. Installation scripts: </para><itemizedlist><listitem><para>Must be executable by the Bourne shell (<command>sh</command>)</para>
</listitem><listitem><para>Must contain Bourne shell commands and text</para>
</listitem><listitem><para>Do not need to contain the <literal>#!/bin/sh</literal> shell
identifier</para>
</listitem><listitem><para>Need not be an executable file</para>
</listitem>
</itemizedlist><para>There are four types of installation scripts with which you can perform
customized actions:</para><itemizedlist><listitem><para><indexterm id="ch3enhancepkg-ix26"><primary><filename>request</filename> script</primary><secondary>creating installation scripts</secondary></indexterm><indexterm id="ch3enhancepkg-ix27"><primary>scripts</primary><see>installation scripts</see></indexterm><indexterm><primary>installation scripts</primary><secondary>types of</secondary></indexterm>The <filename>request</filename> script  </para><para>The <filename>request</filename> script solicits data from the administrator who is installing
a package for assigning or redefining environment variables.</para>
</listitem><listitem><para><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>creating installation scripts</secondary></indexterm>The <filename>checkinstall</filename> script</para><para>The <filename>checkinstall</filename> script
examines the target system for needed data, can set or modify package environment
variables, and determines whether the installation proceeds. </para><note><para>The <filename>checkinstall</filename> script is available starting
with the Solaris 2.5 and compatible releases.</para>
</note>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix28"><primary>procedure scripts</primary></indexterm>Procedure scripts  </para><para><indexterm><primary>procedure scripts</primary><secondary>predefined names of</secondary></indexterm>Procedure
scripts identify a procedure to be invoked before or after the installation
or removal of a package. The four procedure scripts are <filename>preinstall</filename>, <filename>postinstall</filename>, <filename>preremove</filename>, and <filename>postremove</filename>.</para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix30"><primary>class action script</primary><secondary>creating installation scripts</secondary></indexterm>Class action
scripts  </para><para><indexterm><primary>object classes</primary><secondary>system</secondary></indexterm>Class action scripts define an action or set of actions
that should be applied to a class of files during installation or removal.
You can define your own classes. Alternatively, you can use one of the four
standard classes (<literal>sed</literal>, <literal>awk</literal>, <literal>build</literal>,
and <literal>preserve</literal>). </para>
</listitem>
</itemizedlist><sect2 id="ch3enhancepkg-20"><title>Script Processing During Package Installation</title><para><indexterm><primary><command>pkgadd</command> command</primary><secondary>and script processing</secondary></indexterm><indexterm id="ch3enhancepkg-ix32"><primary>installation scripts</primary><secondary>processing of</secondary></indexterm>The type of scripts you use depends on when the action of the
script is needed during the installation process. As a package is installed,
the <command>pkgadd</command> command performs the following steps:</para><orderedlist><listitem><para>Executes the <filename>request</filename> script</para><para><indexterm><primary><filename>request</filename> script</primary><secondary>and script processing</secondary></indexterm>This step is the only point at which your
package can solicit input from the administrator who is installing the package. </para>
</listitem><listitem><para>Executes the <filename>checkinstall</filename> script</para><para><indexterm><primary><filename>checkinstall</filename> script</primary></indexterm>The <filename>checkinstall</filename> script gathers file system
data and can create or alter environment variable definitions to control the
subsequent installation. For more information on package environment variables,
see <olink targetptr="ch2buildpkg-13952" remap="internal">Package Environment Variables</olink>.</para>
</listitem><listitem><para><indexterm><primary><filename>preinstall</filename> script</primary></indexterm>Executes the <filename>preinstall</filename> script</para>
</listitem><listitem><para>Installs package objects, for each class to be installed</para><para><indexterm><primary>object classes</primary><secondary>installing</secondary></indexterm>Installation of these files occurs class by class, and class action
scripts are executed accordingly. The list of classes operated on and the
order in which they should be installed is initially defined with the <envar>CLASSES</envar> parameter in your <envar>pkginfo</envar> file. However, your <filename>request</filename> script or <filename>checkinstall</filename> script can change
the value of the <envar>CLASSES</envar> parameter. For more information on
how classes are processed during installation, see <olink targetptr="ch3enhancepkg-34" remap="internal">How Classes Are Processed During Package Installation</olink>.</para><orderedlist><listitem><para>Creates symbolic links, devices, named pipes, and required
directories</para>
</listitem><listitem><para>Installs the regular files (file types <literal>e</literal>, <literal>v</literal>, <literal>f</literal>), based on their class</para><para><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>script processing during package installation</secondary></indexterm>The class action script
is passed only regular files to install. All other package objects are created
automatically from information in the <filename>pkgmap</filename> file.</para>
</listitem><listitem><para>Creates all hard links</para>
</listitem>
</orderedlist>
</listitem><listitem><para><indexterm><primary><filename>postinstall</filename> script</primary><secondary>sript processing during package installation</secondary></indexterm>Executes
the <filename>postinstall</filename> script</para>
</listitem>
</orderedlist>
</sect2><sect2 id="ch3enhancepkg-21"><title>Script Processing During Package Removal</title><para><indexterm><primary><command>pkgrm</command> command</primary><secondary>and script processing</secondary></indexterm>When a package is being removed,
the <command>pkgrm</command> command performs these steps: </para><orderedlist><listitem><para><indexterm><primary><filename>preremove</filename> script</primary></indexterm>Executes the <filename>preremove</filename> script</para>
</listitem><listitem><para>Removes the package objects, for each class</para><para><indexterm><primary>object classes</primary><secondary>removing</secondary></indexterm><indexterm><primary>class action script</primary></indexterm>Removal also occurs class
by class. Removal scripts are processed in the reverse order of installation,
based on the sequence defined in the <envar>CLASSES</envar> parameter. For
more information on how classes are processed during installation, see <olink targetptr="ch3enhancepkg-34" remap="internal">How Classes Are Processed During Package Installation</olink>.</para><orderedlist><listitem><para>Removes hard links</para>
</listitem><listitem><para>Removes regular files</para>
</listitem><listitem><para>Removes symbolic links, devices, and named pipes</para>
</listitem>
</orderedlist>
</listitem><listitem><para><indexterm><primary><filename>postremove</filename> script</primary></indexterm>Executes the <filename>postremove</filename> script </para>
</listitem>
</orderedlist><para><indexterm><primary><filename>request</filename> script</primary><secondary>and package removal</secondary></indexterm>The <filename>request</filename> script
is not processed at the time of package removal. However, the script's output
is retained in the installed package and made available to removal scripts.
The <filename>request</filename> script's output is a list of environment
variables.</para>
</sect2><sect2 id="ch3enhancepkg-22"><title>Package Environment Variables Available
to Scripts</title><para><indexterm><primary>installation environment variables</primary><secondary>to determine Solaris version</secondary></indexterm><indexterm><primary>OS version environment variables</primary></indexterm><indexterm><primary><filename>request</filename> script</primary><secondary>and environment variables</secondary></indexterm><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>and environment variables</secondary></indexterm><indexterm id="ch3enhancepkg-ix34"><primary>installation environment variables</primary></indexterm><indexterm id="ch3enhancepkg-ix35"><primary>installation scripts</primary><secondary>and environment variables</secondary></indexterm>The following
groups of environment variables are available to all installation scripts.
Some of the environment variables can be modified by a <filename>request</filename> script
or a <filename>checkinstall</filename> script. </para><itemizedlist><listitem><para>The <filename>request</filename> script or the <filename>checkinstall</filename> script can set or modify any of the standard parameters in the <filename>pkginfo</filename> file, except for the required parameters. The standard
installation parameters are described in detail in the <olink targetdoc="refman4" targetptr="pkginfo-4" remap="external"><citerefentry><refentrytitle>pkginfo</refentrytitle><manvolnum>4</manvolnum></citerefentry></olink> man page.</para><note><para>The <envar>BASEDIR</envar> parameter can only be modified starting
with the Solaris 2.5 release and compatible releases.</para>
</note>
</listitem><listitem><para>You can define your own installation environment variables
by assigning values to them in the <filename>pkginfo</filename> file. Such
environment variables must be alphanumeric with initial capital letters. Any
of these environment variables can be changed by a <filename>request</filename> script
or a <filename>checkinstall</filename> script.</para>
</listitem><listitem><para>Both a <filename>request</filename> script and a <filename>checkinstall</filename> script can define new environment variables by assigning values
to them and putting them in the installation environment. </para>
</listitem><listitem><para>The following table lists environment variables that are available
to all installation scripts through the environment. None of these environment
variables can be modified by a script. </para><informaltable remap="CH3ENHANCEPKG-14210" frame="topbot" pgwide="1"><tgroup cols="2" colsep="0" rowsep="0"><colspec colname="column1" colwidth="117*"/><colspec colname="column2" colwidth="279*"/><thead><row rowsep="1"><entry><para>Environment Variable</para>
</entry><entry><para>Description</para>
</entry>
</row>
</thead><tbody><row><entry><para><envar>CLIENT_BASEDIR</envar>	</para>
</entry><entry><para>The base directory with respect to the target system. While <envar>BASEDIR</envar> is
the variable to use if you are referring to a specific package object from
the install system (most likely a server), <envar>CLIENT_BASEDIR</envar> is
the path to include in files placed on the client system. <envar>CLIENT_BASEDIR</envar> exists
if <envar>BASEDIR</envar> exists and is identical to <envar>BASEDIR</envar> if
there is no <envar>PKG_INSTALL_ROOT</envar>.</para>
</entry>
</row><row><entry><para><envar>INST_DATADIR</envar>	</para>
</entry><entry><para>The directory where the package now being read is located. If the package
is being read from a tape, this variable will be the location of a temporary
directory where the package has been transferred into directory format. In
other words, assuming there is no extension to the package name (for example, <literal>SUNWstuff.d</literal>), the <filename>request</filename> script for the current
package would be found at <literal>$INST_DATADIR/$PKG/install</literal>.</para>
</entry>
</row><row><entry><para><envar>PATH</envar>	</para>
</entry><entry><para>The search list used by <command>sh</command> to find commands on script
invocation. <envar>PATH</envar> is usually set to <literal>/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin</literal>.</para>
</entry>
</row><row><entry><para><envar>PKGINST</envar></para>
</entry><entry><para>The instance identifier of the package being installed.   If another
instance of the package is not already installed, the value is the package
abbreviation (for example, <literal>SUNWcadap</literal>). Otherwise, the value
is the package abbreviation followed by a suffix, such as <literal>SUNWcadap.4</literal>.</para>
</entry>
</row><row><entry><para><envar>PKGSAV</envar></para>
</entry><entry><para>The directory where files can be saved for use by removal scripts or
where previously saved files can be found. Available only in the Solaris 2.5
release and compatible releases.</para>
</entry>
</row><row><entry><para><filename>PKG_CLIENT_OS</filename></para>
</entry><entry><para>The operating system of the client where the package is being installed.
The value of this variable is <literal>Solaris</literal>.</para>
</entry>
</row><row><entry><para><filename>PKG_CLIENT_VERSION</filename></para>
</entry><entry><para>The Solaris version in <literal>x.y</literal> format.</para>
</entry>
</row><row><entry><para><filename>PKG_CLIENT_REVISION</filename></para>
</entry><entry><para>The Solaris build revision.</para>
</entry>
</row><row><entry><para><envar>PKG_INSTALL_ROOT</envar></para>
</entry><entry><para>The root file system on the target system where the package is being
installed. This variable exists only if the <command>pkgadd</command> and <command>pkgrm</command> commands were invoked with the <option>R</option> option.
This conditional existence facilitates its use in procedure scripts in the
form <literal>${PKG_INSTALL_ROOT}/</literal><replaceable>somepath</replaceable>.</para>
</entry>
</row><row><entry><para><envar>PKG_NO_UNIFIED</envar></para>
</entry><entry><para>An environment variable that gets set if the <command>pkgadd</command> and <command>pkgrm</command> commands were invoked with the <option>M</option> and <option>R</option> options.
This environment variable is passed to any package installation script or
package command that is part of the package environment.</para>
</entry>
</row><row><entry><para><envar>UPDATE</envar></para>
</entry><entry><para>This environment variable does not exist under most installation environments.
If this variable does exist (with the value <literal>yes</literal>), it means
one of two things. Either a package with the same name, version, and architecture
is already installed on the system. Or this package is overwriting an installed
package of the same name at the direction of the administrator. In these events,
the original base directory is always used.</para>
</entry>
</row><row><entry>
</entry><entry>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</listitem>
</itemizedlist>
</sect2><sect2 id="ch3enhancepkg-23"><title>Obtaining Package Information for a Script</title><para><indexterm><primary>installation scripts</primary><secondary>obtaining package information</secondary></indexterm>Two commands can be used from scripts
to solicit information about a package: </para><itemizedlist><listitem><para><indexterm><primary><command>pkginfo</command> command</primary><secondary>obtaining package information</secondary></indexterm>The <command>pkginfo</command> command returns information about software packages, such as the
instance identifier and package name. </para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix37"><primary><command>pkgparam</command> command</primary></indexterm>The <command>pkgparam</command> command returns values
for requested environment variables. </para><para>See the <olink targetdoc="refman1" targetptr="pkginfo-1" remap="external"><citerefentry><refentrytitle>pkginfo</refentrytitle><manvolnum>1</manvolnum></citerefentry></olink> man page, the <olink targetdoc="refman1" targetptr="pkgparam-1" remap="external"><citerefentry><refentrytitle>pkgparam</refentrytitle><manvolnum>1</manvolnum></citerefentry></olink> man page, and <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4, Verifying and Transferring
a Package</olink> for more information. </para>
</listitem>
</itemizedlist>
</sect2><sect2 id="ch3enhancepkg-24"><title>Exit Codes for Scripts</title><para><indexterm id="ch3enhancepkg-ix38"><primary>installation scripts</primary><secondary>exit codes</secondary></indexterm><indexterm><primary>exit codes for scripts</primary></indexterm>Each script must exit with one of the exit
codes shown in the following table.</para><table frame="topbot" id="ch3enhancepkg-54572"><title>Installation Script
Exit Codes</title><tgroup cols="2" colsep="0" rowsep="0"><colspec colname="column1" colwidth="44*"/><colspec colname="column2" colwidth="352*"/><thead><row rowsep="1"><entry><para>Code</para>
</entry><entry><para>Meaning</para>
</entry>
</row>
</thead><tbody><row><entry><para>0</para>
</entry><entry><para>Successful completion of script. </para>
</entry>
</row><row><entry><para>1</para>
</entry><entry><para>Fatal error. Installation process is terminated at this point. </para>
</entry>
</row><row><entry><para>2 </para>
</entry><entry><para>Warning or possible error condition. Installation continues. A warning
message is displayed at the time of completion. </para>
</entry>
</row><row><entry><para>3 </para>
</entry><entry><para>The <command>pkgadd</command> command is cleanly halted. Only the <filename>checkinstall</filename> script returns this code.</para>
</entry>
</row><row><entry><para>10 </para>
</entry><entry><para>System should be rebooted when installation of all selected packages
is completed. (This value should be added to one of the single-digit exit
codes.) </para>
</entry>
</row><row><entry><para>20 </para>
</entry><entry><para>System should be rebooted immediately upon completing installation of
the current package. (This value should be added to one of the single-digit
exit codes.) </para>
</entry>
</row>
</tbody>
</tgroup>
</table><para>See <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case
Studies of Package Creation</olink> for examples of exit codes that are returned
by installation scripts.</para><note><para>All installation scripts delivered with your package should have
an entry in the <filename>prototype</filename> file. The file type should
be <literal>i</literal> (for package installation script). </para>
</note>
</sect2><sect2 id="ch3enhancepkg-21209"><title>Writing a <filename>request</filename> Script</title><para><indexterm><primary><filename>request</filename> script</primary><secondary>writing a</secondary></indexterm>The <filename>request</filename> script
is the only way your package can interact directly with the administrator
who is installing it. This script can be used, for example, to ask the administrator
if optional pieces of a package should be installed.</para><para>The output of a <filename>request</filename> script must be a list of
environment variables and their values. This list can include any of the parameters
that you created in the <filename>pkginfo</filename> file, and the <envar>CLASSES</envar> and <envar>BASEDIR</envar> parameters. The list can also introduce
environment variables that have not been defined elsewhere. However, the <filename>pkginfo</filename> file should always provide default values when practical.
For more information on package environment variables, see <olink targetptr="ch2buildpkg-13952" remap="internal">Package Environment Variables</olink>.</para><para><indexterm><primary><command>pkgadd</command> command</primary><secondary>and <filename>request</filename> scripts</secondary></indexterm>When your <filename>request</filename> script
assigns values to an environment variable, it must then make those values
available to the <command>pkgadd</command> command and other package scripts. </para><sect3 id="ch3enhancepkg-45"><title><filename>request</filename> Script Behaviors</title><itemizedlist><listitem><para><indexterm><primary><filename>request</filename> script</primary><secondary>behaviors</secondary></indexterm>The <filename>request</filename> script
cannot modify any files. This script only interacts with administrators who
are installing the package and creates a list of environment variable assignments
based upon that interaction. The <filename>request</filename> script runs
as the non privileged user <literal>install</literal> if that user exists.
Otherwise, the script is executed as <literal>root</literal>.</para>
</listitem><listitem><para>The <command>pkgadd</command> command calls the <filename>request</filename> script with one argument that names the script's response file.
The response file stores the administrator's responses.</para>
</listitem><listitem><para>The <filename>request</filename> script is not executed during
package removal. However, the environment variables assigned by the script
are saved and are available during package removal.</para>
</listitem>
</itemizedlist>
</sect3><sect3 id="ch3enhancepkg-25"><title>Design Rules for <filename>request</filename> Scripts</title><itemizedlist><listitem><para><indexterm id="ch3enhancepkg-ix39"><primary><filename>request</filename> script</primary><secondary>design rules</secondary></indexterm>There can be only
one <filename>request</filename> script per package. The script must be named <filename>request</filename>. </para>
</listitem><listitem><para>The environment variable assignments should be added to the
installation environment for use by the <command>pkgadd</command> command
and other packaging scripts by writing them to the response file (known to
the script as <literal>$1</literal>).</para>
</listitem><listitem><para>System environment variables and standard installation environment
variables, except for the <envar>CLASSES</envar> and <envar>BASEDIR</envar> parameters,
cannot be modified by a <filename>request</filename> script. Any of the other
environment variables that you created can be changed. </para><note><para>A <filename>request</filename> script can only modify the <envar>BASEDIR</envar> parameter starting with the Solaris 2.5 and compatible releases.</para>
</note>
</listitem><listitem><para>Every environment variable that the <filename>request</filename> script
may manipulate should be assigned a default value in the <filename>pkginfo</filename> file.</para>
</listitem><listitem><para>The format of the output list should be <replaceable>PARAM=value</replaceable>.
For example: </para><screen>CLASSES=none class1</screen>
</listitem><listitem><para>The administrator's terminal is defined as standard input
to the <filename>request</filename> script. </para>
</listitem><listitem><para>Do not perform any special analysis of the target system in
a <filename>request</filename> script. It is risky to test the system for
the presence of certain binaries or behaviors, and to set environment variables
based upon that analysis. There is no guarantee that the <filename>request</filename> script
will actually be executed at install time. The administrator who is installing
the package may provide a response file that will insert the environment variables
without ever calling the <filename>request</filename> script. If the <filename>request</filename> script is also evaluating the target file system, that evaluation
may not happen. An analysis of the target system for special treatment is
best left to the <filename>checkinstall</filename> script.</para>
</listitem>
</itemizedlist><note><para><indexterm><primary><command>pkgask</command> command</primary></indexterm><indexterm><primary><command>pkgask</command> command</primary></indexterm>If the administrators who will be installing your package might
use the <trademark>JumpStart</trademark> product, then the installation of
your package must not be interactive. Either you should not provide a <filename>request</filename> script with your package, or you need to communicate to the administrators
that they should use the <command>pkgask</command> command prior to installation.
The <command>pkgask</command> command stores their responses to the <filename>request</filename> script. For more information on the <command>pkgask</command> command,
see the <olink targetdoc="refman1m" targetptr="pkgask-1m" remap="external"><citerefentry><refentrytitle>pkgask</refentrytitle><manvolnum>1M</manvolnum></citerefentry></olink> man
page.</para>
</note>
</sect3>
</sect2><task id="ch3enhancepkg-119"><title>How to Write a <filename>request</filename> Script</title><procedure><step id="ch3enhancepkg-step-49"><para><indexterm><primary><filename>request</filename> script</primary><secondary>how to write a</secondary></indexterm>Make the directory
that contains your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-50"><para>Create a file named <filename>request</filename> with
your favorite text editor.</para>
</step><step id="ch3enhancepkg-step-89"><para>Save your changes and quit the editor
when you are done.</para>
</step><step id="ch3enhancepkg-step-99"><para>Complete one of the following tasks.</para><itemizedlist><listitem><para>If you want to create additional installation scripts, skip
to the next task, <olink targetptr="ch3enhancepkg-120" remap="internal">How to Gather File
System Data</olink>.</para>
</listitem><listitem><para>If you have not created your <filename>prototype</filename> file,
complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How to Create a prototype
File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-52" remap="internal">Step&nbsp;5</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for the installation script you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-52"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><example id="ch3enhancepkg-56"><title>Writing a <filename>request</filename> Script</title><para><indexterm><primary><filename>request</filename> script</primary><secondary>example</secondary></indexterm>When a <filename>request</filename> script
assigns values to environment variables, it must make those values available
to the <command>pkgadd</command> command. This example shows a <filename>request</filename> script
segment that performs this task for the four environment variables: <envar>CLASSES</envar>, <envar>NCMPBIN</envar>, <envar>EMACS</envar>, and <envar>NCMPMAN</envar>.
Assume that these variables were defined in an interactive session with the
administrator earlier in the script.</para><screen># make environment variables available to installation
# service and any other packaging script we might have
 
cat &gt;$1 &lt;&lt;!
CLASSES=$CLASSES
NCMPBIN=$NCMPBIN
EMACS=$EMACS
NCMPMAN=$NCMPMAN
!</screen>
</example><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task><sect2 id="ch3enhancepkg-21872"><title>Gathering File System Data With the <filename>checkinstall</filename> Script</title><para><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>writing a</secondary></indexterm>The <filename>checkinstall</filename> script
is executed shortly after the optional <filename>request</filename> script.
The <filename>checkinstall</filename> script runs as the user <literal>install</literal>,
if such a user exists, or as the user <literal>nobody</literal>. The <filename>checkinstall</filename> script does not have the authority to change file system data.
However, based on the information the script gathers, it can create or modify
environment variables in order to control the course of the resulting installation.
The script is also capable of cleanly halting the installation process.</para><para>The <filename>checkinstall</filename> script is intended to perform
basic checks on a file system that would not be normal for the <command>pkgadd</command> command.
For example, this script can be used to check ahead to determine if any files
from the current package are going to overwrite existing files, or manage
general software dependencies. The <filename>depend</filename> file only manages
package-level dependencies.</para><para>Unlike the <filename>request</filename> script, the <filename>checkinstall</filename> script
is executed whether or not a response file is provided. The script's presence
does not brand the package as interactive. The <filename>checkinstall</filename> script
can be used in situations where a <filename>request</filename> script is forbidden
or administrative interaction is not practical.</para><note><para>The <filename>checkinstall</filename> script is available starting
with the Solaris 2.5 and compatible releases.</para>
</note><sect3 id="ch3enhancepkg-91"><title><filename>checkinstall</filename> Script
Behaviors</title><itemizedlist><listitem><para><indexterm><primary><filename>request</filename> script</primary><secondary>behaviors</secondary></indexterm>The <filename>checkinstall</filename> script
cannot modify any files. This script only analyzes the state of the system
and creates a list of environment variable assignments based upon that interaction.
To enforce this restriction, the <filename>checkinstall</filename> script
is executed as the non privileged user <literal>install</literal> if that
user exists. Otherwise, this script is executed as the non privileged user <literal>nobody</literal>. The <filename>checkinstall</filename> script does not have
superuser authority.</para>
</listitem><listitem><para>The <command>pkgadd</command> command calls the <filename>checkinstall</filename> script with one argument that names the script's response file.
The script's response file is the file that stores the administrator's responses.</para>
</listitem><listitem><para>The <filename>checkinstall</filename> script is not executed
during package removal. However, the environment variables assigned by the
script are saved and are available during package removal.</para>
</listitem>
</itemizedlist>
</sect3><sect3 id="ch3enhancepkg-92"><title>Design Rules for <filename>checkinstall</filename> Scripts</title><itemizedlist><listitem><para><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>design rules</secondary></indexterm>There can be only one <filename>checkinstall</filename> script per package. The script must be named <filename>checkinstall</filename>. </para>
</listitem><listitem><para>The environment variable assignments should be added to the
installation environment for use by the <command>pkgadd</command> command
and other packaging scripts by writing them to the response file (known to
the script as <literal>$1</literal>).</para>
</listitem><listitem><para>System environment variables and standard installation environment
variables, except for the <envar>CLASSES</envar> and <envar>BASEDIR</envar> parameters,
cannot be modified by a <filename>checkinstall</filename> script. Any of the
other environment variables that you created can be changed. </para>
</listitem><listitem><para>Every environment variable that the <filename>checkinstall</filename> script
may manipulate should be assigned a default value in the <filename>pkginfo</filename> file.</para>
</listitem><listitem><para>The format of the output list should be <replaceable>PARAM=value</replaceable>.
For example: </para><screen>CLASSES=none class1</screen>
</listitem><listitem><para>Administrator interaction is not permitted during execution
of a <filename>checkinstall</filename> script. All administrator interaction
is restricted to the <filename>request</filename> script.</para>
</listitem>
</itemizedlist>
</sect3>
</sect2><task id="ch3enhancepkg-120"><title>How to Gather File System Data</title><procedure><step id="ch3enhancepkg-step-69"><para><indexterm><primary><filename>checkinstall</filename> script</primary><secondary>how to write a</secondary></indexterm>Make
the directory that contains your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-70"><para>Create a file named <filename>checkinstall</filename> with your favorite text editor.</para>
</step><step id="ch3enhancepkg-step-90"><para>Save your changes and quit the editor
when you are done.</para>
</step><step id="ch3enhancepkg-step-100"><para>Complete one of the following tasks.</para><itemizedlist><listitem><para>If you want to create additional installation scripts, skip
to the next task, <olink targetptr="ch3enhancepkg-121" remap="internal">How to Write Procedure
Scripts</olink>.</para>
</listitem><listitem><para>If you have not created your <filename>prototype</filename> file,
complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How to Create a prototype
File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-72" remap="internal">Step&nbsp;5</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for the installation script you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-72"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><example id="ch3enhancepkg-93"><title>Writing a <filename>checkinstall</filename> Script</title><para><indexterm><primary><filename>request</filename> script</primary><secondary>example</secondary></indexterm>This example <filename>checkinstall</filename> script
checks to see if database software needed by the <literal>SUNWcadap</literal> package
is installed.</para><screen># checkinstall script for SUNWcadap
#
# This confirms the existence of the required specU database
 
# First find which database package has been installed.
pkginfo -q SUNWspcdA	# try the older one
 
if [ $? -ne 0 ]; then
   pkginfo -q SUNWspcdB	# now the latest
 
	  if [ $? -ne 0 ]; then	# oops
		    echo "No database package can be found. Please install the"
		    echo "SpecU database package and try this installation again."
		    exit 3		# Suspend
	  else
		    DBBASE="`pkgparam SUNWsbcdB BASEDIR`/db"	# new DB software
	  fi
else
	  DBBASE="`pkgparam SUNWspcdA BASEDIR`/db"	# old DB software
fi
 
# Now look for the database file we will need for this installation
if [ $DBBASE/specUlatte ]; then
	  exit 0		# all OK
else
	  echo "No database file can be found. Please create the database"
	  echo "using your installed specU software and try this"
	  echo "installation again."
	  exit 3		# Suspend
fi
 </screen>
</example><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task><sect2 id="ch3enhancepkg-14637"><title>Writing Procedure Scripts</title><para><indexterm><primary>procedure scripts</primary><secondary>writing</secondary></indexterm>The procedure scripts provide a set of instructions to be performed
at particular points in package installation or removal. The four procedure
scripts must be named one of the predefined names, depending on when the instructions
are to be executed. The scripts are executed without arguments.</para><itemizedlist><listitem><para><indexterm><primary>procedure scripts</primary><secondary>predefined names of</secondary></indexterm><indexterm id="ch3enhancepkg-ix43"><primary><filename>preinstall</filename> script</primary></indexterm>The <filename>preinstall</filename> script
 </para><para>Runs before class installation begins. No files should be installed
by this script.</para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix45"><primary><filename>postinstall</filename> script</primary><secondary>procedure scripts</secondary></indexterm>The <filename>postinstall</filename> script  </para><para>Runs after all volumes have been
installed.</para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix47"><primary><filename>preremove</filename> script</primary></indexterm>The <filename>preremove</filename> script  </para><para>Runs
before class removal begins. No files should be removed by this script.</para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix49"><primary><filename>postremove</filename> script</primary></indexterm>The <filename>postremove</filename> script  </para><para>Runs
after all classes have been removed.</para>
</listitem>
</itemizedlist><sect3 id="ch3enhancepkg-46"><title>Procedure Script Behaviors</title><para><indexterm id="ch3enhancepkg-ix51"><primary>procedure scripts</primary><secondary>behaviors</secondary></indexterm>Procedure scripts are executed
as <literal>uid=root</literal> and <literal>gid=other</literal>. </para>
</sect3><sect3 id="ch3enhancepkg-28"><title>Design Rules for Procedure Scripts</title><itemizedlist><listitem><para><indexterm><primary>procedure scripts</primary><secondary>design rules</secondary></indexterm>Each script should be able to be executed more
than once because it is executed once for each volume in a package. This means
that executing a script any number of times with the same input produces the
same results as executing the script only once. </para>
</listitem><listitem><para><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>procedure script design rules</secondary></indexterm><indexterm><primary><command>installf</command> command</primary></indexterm><indexterm><primary><filename>postinstall</filename> script</primary><secondary>installing package objects</secondary></indexterm><indexterm><primary><filename>postremove</filename> script</primary><secondary>removing package objects</secondary></indexterm>Each
procedure script that installs a package object not in the <filename>pkgmap</filename> file
must use the <command>installf</command> command  to notify the package database
that it is adding or modifying a path name. After all additions or modifications
are complete, this command should be invoked with the <option>f</option> option.
Only the <filename>postinstall</filename> and <filename>postremove</filename> scripts
may install package objects in this way. See the <olink targetdoc="refman1m" targetptr="installf-1m" remap="external"><citerefentry><refentrytitle>installf</refentrytitle><manvolnum>1M</manvolnum></citerefentry></olink> man page and <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case Studies of Package
Creation</olink> for more information.</para>
</listitem><listitem><para>Administrator interaction is not permitted during execution
of a procedure script. All administrator interaction is restricted to the <filename>request</filename> script.</para>
</listitem><listitem><para><indexterm><primary><command>removef</command> command</primary></indexterm>Each procedure script that removes files not installed from the <filename>pkgmap</filename> file must use the <command>removef</command> command to
notify the package database that it is removing a path name. After removal
is complete, this command should be invoked with the <option>f</option> option.
See  the <olink targetdoc="refman1m" targetptr="removef-1m" remap="external"><citerefentry><refentrytitle>removef</refentrytitle><manvolnum>1M</manvolnum></citerefentry></olink> man
page and <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case Studies
of Package Creation</olink> for details and examples.</para><note><para>The <command>installf</command> and <command>removef</command> commands
must be used because procedure scripts are not automatically associated with
any path names listed in the <filename>pkgmap</filename> file. </para>
</note>
</listitem>
</itemizedlist>
</sect3>
</sect2><task id="ch3enhancepkg-121"><title>How to Write Procedure Scripts</title><procedure><step id="ch3enhancepkg-step-48"><para><indexterm><primary>procedure scripts</primary><secondary>how to write</secondary></indexterm>Make the directory that contains
your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-53"><para>Create one or more procedure scripts
with your favorite text editor.</para><para>A procedure script must be named
one of the predefined names: <filename>preinstall</filename>, <filename>postinstall</filename>, <filename>preremove</filename>, or <filename>postremove</filename>.</para>
</step><step id="ch3enhancepkg-step-54"><para>Save your changes and quit the editor.</para>
</step><step id="ch3enhancepkg-step-101"><para>Complete one of the following tasks.</para><itemizedlist><listitem><para>If you want to create class action scripts, skip to the next
task, <olink targetptr="ch3enhancepkg-122" remap="internal">How to Write Class Action Scripts</olink>.</para>
</listitem><listitem><para>If you have not created your <filename>prototype</filename> file,
complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How to Create a prototype
File by Using the pkgproto Command</olink>. Skip to <olink targetptr="ch3enhancepkg-step-55" remap="internal">Step&nbsp;5</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for each installation script you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-55"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><taskrelated role="see-also"><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains these tasks and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated>
</task><sect2 id="ch3enhancepkg-37319"><title>Writing Class Action Scripts</title><sect3 id="ch3enhancepkg-31"><title>Defining Object Classes</title><para><indexterm id="ch3enhancepkg-ix53"><primary>object classes</primary></indexterm><indexterm id="ch3enhancepkg-ix54"><primary>package</primary><secondary>object</secondary><tertiary>classes</tertiary></indexterm><indexterm><primary>package</primary><secondary>object</secondary><tertiary>classes</tertiary><seealso>object classes</seealso></indexterm>Object classes allow a series
of actions to be performed on a group of package objects at installation or
removal. You assign objects to a class in the <filename>prototype</filename> file.
All package objects must be given a class, although the class of <literal>none</literal> is
used by default for objects that require no special action. </para><para>The installation parameter <envar>CLASSES</envar>, defined in the <filename>pkginfo</filename> file, is a list of classes to be installed (including the <literal>none</literal> class). </para><note><para><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>defining object classes</secondary></indexterm>Objects defined
in the <filename>pkgmap</filename> file that belong to a class not listed
in this parameter in the <filename>pkginfo</filename> file will <emphasis>not</emphasis> be
installed. </para>
</note><para>The <envar>CLASSES</envar> list determines the order of installation.
Class <literal>none</literal> is always installed first, if present, and removed
last. Since directories are the fundamental support structure for all other
file system objects, they should all be assigned to the <literal>none</literal> class.
Exceptions can be made, but as a general rule, the <literal>none</literal> class
is safest. This strategy ensures that the directories are created before the
objects they will contain. In addition, no attempt is made to delete a directory
before it has been emptied.</para>
</sect3><sect3 id="ch3enhancepkg-34"><title>How Classes Are Processed During Package
Installation</title><para><indexterm id="ch3enhancepkg-ix59"><primary>installing classes</primary></indexterm><indexterm id="ch3enhancepkg-ix60"><primary>object classes</primary><secondary>installing</secondary></indexterm><indexterm id="ch3enhancepkg-ix61"><primary>classes</primary><see>object classes</see></indexterm>The following
describes the system actions that occur when a class is installed. The actions
are repeated once for each volume of a package, as that volume is being installed. </para><orderedlist><listitem><para><indexterm><primary><command>pkgadd</command> command</primary><secondary>and class installation</secondary></indexterm><indexterm id="ch3enhancepkg-ix62"><primary><command>pkgadd</command> command</primary></indexterm>The <command>pkgadd</command> command creates a path name list. </para><para>The <command>pkgadd</command> command creates a list of path names upon
which the action script operates. Each line of this list contains source and
destination path names, separated by a space. The source path name indicates
where the object to be installed resides on the installation volume. The destination
path name indicates the location on the target system where the object should
be installed. The contents of the list are restricted by the following criteria: </para><itemizedlist><listitem><para>The list contains only path names that belong to the associated
class. </para>
</listitem><listitem><para><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>class processing during installation</secondary></indexterm>If
the attempt to create the package object fails, then directories, named pipes,
character devices, block devices, and symbolic links are included in the list
with the source path name set to <filename>/dev/null</filename>. Normally,
these items are automatically created by the <command>pkgadd</command> command
(if not already in existence) and given proper attributes (mode, owner, group)
as defined in the <filename>pkgmap</filename> file.</para>
</listitem><listitem><para>Linked files where the file type is <literal>l</literal> are
not included in the list under any circumstances. Hard links in the given
class are created in item 4. </para>
</listitem>
</itemizedlist>
</listitem><listitem><para>If no class action script is provided for installation of
a particular class, the path names in the generated list are copied from the
volume to the appropriate target location.</para>
</listitem><listitem><para>A class action script is executed if one exists. </para><para>The
class action script is invoked with standard input that contains the list
generated in item 1. If this volume is the last volume of the package, or
no more objects exist in this class, the script is executed with the single
argument of <literal>ENDOFCLASS</literal>.</para><note><para>Even if no regular files of this class exist in the package, the
class action script is called at least once with an empty list and the <literal>ENDOFCLASS</literal> argument.</para>
</note>
</listitem><listitem><para>The <command>pkgadd</command> command performs a content and
attribute audit, and creates hard links. </para><para>After successfully executing
items 2 or 3, the <command>pkgadd</command> command audits both content and
attribute information for the list of path names. The <command>pkgadd</command> command
creates the links associated with the class automatically. Detected attribute
inconsistencies are corrected for all path names in the generated list.</para>
</listitem>
</orderedlist>
</sect3><sect3 id="ch3enhancepkg-35"><title>How Classes Are Processed During Package
Removal</title><para><indexterm><primary><command>installf</command> command</primary></indexterm><indexterm id="ch3enhancepkg-ix63"><primary>removing classes</primary></indexterm><indexterm id="ch3enhancepkg-ix64"><primary>object classes</primary><secondary>removing</secondary></indexterm><indexterm id="ch3enhancepkg-ix66"><primary><command>pkgrm</command> command</primary><secondary>and class removal</secondary></indexterm>Objects are removed class by class. Classes that exist for a package
but are not listed in the <envar>CLASSES</envar> parameter are removed first
(for example, an object installed with the <command>installf</command> command).
 Classes listed in the <envar>CLASSES</envar> parameter are removed in reverse
order. The <literal>none</literal> class is always removed last. The following
describes the system actions that occur when a class is removed: </para><orderedlist><listitem><para>The <command>pkgrm</command> command creates a path name list. </para><para>The <command>pkgrm</command> command creates a list of installed path
names that belong to the indicated class. Path names referenced by another
package are excluded from the list unless their file type is <literal>e</literal>.
A file type of <literal>e</literal> means the file should be edited upon installation
or removal. </para><para>If the package being removed had modified any files
of type <literal>e</literal> during installation, it should remove just the
lines it added. Do not delete a non-empty editable file. Remove the lines
that the package added.</para>
</listitem><listitem><para>If no class action script exists, the path names are deleted. </para><para>If your package has no removal class action script for the class, all
the path names in the list generated by the <command>pkgrm</command> command
are deleted. </para><note><para>Files with a file type of <literal>e</literal> (editable) are
not assigned to a class and an associated class action script. These files
are removed at this point, even if the path name is shared with other packages. </para>
</note>
</listitem><listitem><para>If a class action script exists, the script is executed. </para><para>The <command>pkgrm</command> command invokes the class action script
with standard input for the script that contains the list generated in item
1. </para>
</listitem><listitem><para>The <command>pkgrm</command> command performs an audit. </para><para>After successfully executing the class action script, the <command>pkgrm</command> command
removes references to the path names from the package database unless a path
name is referenced by another package. </para>
</listitem>
</orderedlist>
</sect3><sect3 id="ch3enhancepkg-32"><title>The Class Action Script</title><para><indexterm id="ch3enhancepkg-ix55"><primary>class action script</primary></indexterm>The class action script defines a set of actions to be executed
during installation or removal of a package. The actions are performed on
a group of path names based on their class definition. See <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case Studies of Package
Creation</olink> for examples of class action scripts. </para><para>The name of a class action script is based on the class on which it
should operate and whether those operations should occur during package installation
or package removal. The two name formats are shown in the following table: </para><informaltable frame="topbot"><tgroup cols="2" colsep="0" rowsep="1"><colspec colname="column1" colwidth="152*"/><colspec colname="column2" colwidth="304*"/><thead><row><entry><para>Name Format</para>
</entry><entry><para>Description</para>
</entry>
</row>
</thead><tbody><row rowsep="0"><entry><para><literal>i.</literal><replaceable>class</replaceable> </para>
</entry><entry><para>Operates on path names in the indicated class during package installation</para>
</entry>
</row><row><entry><para> <literal>r.</literal><replaceable>class</replaceable></para>
</entry><entry><para>Operates on path names in the indicated class during package removal </para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable><para><indexterm><primary>class action script</primary><secondary>naming conventions</secondary></indexterm>For example, the name of the installation script for
a class named <literal>manpage</literal> would be <literal>i.manpage</literal>.
The removal script would be named <literal>r.manpage</literal>.</para><note><para>This file name format is not used for files that belong to the <literal>sed</literal>, <literal>awk</literal>, or <literal>build</literal> system
classes. For more information on these special classes, see <olink targetptr="ch3enhancepkg-36" remap="internal">The Special System Classes</olink>.</para>
</note>
</sect3><sect3 id="ch3enhancepkg-73"><title>Class Action Script Behaviors</title><itemizedlist><listitem><para><indexterm id="ch3enhancepkg-ix57"><primary>class action script</primary><secondary>behaviors</secondary></indexterm>Class action scripts are executed
as <literal>uid=root</literal> and <literal>gid=other</literal>. </para>
</listitem><listitem><para>A script is executed for all files in the given class on the
current volume. </para>
</listitem><listitem><para><indexterm><primary><filename>pkgmap</filename> file</primary><secondary>class action script behaviors</secondary></indexterm>The <command>pkgadd</command> and <command>pkgrm</command> commands create a list of all objects
listed in the <filename>pkgmap</filename> file that belong to the class. As
a result, a class action script can act only upon path names defined in the <filename>pkgmap</filename> that belong to a particular class. </para>
</listitem><listitem><para>When a class action script is executed for the last time (that
is, no more files belong to that class), the class action script is executed
once with the keyword argument <literal>ENDOFCLASS</literal>.</para>
</listitem><listitem><para>Administrator interaction is not permitted during execution
of a class action script.</para>
</listitem>
</itemizedlist>
</sect3><sect3 id="ch3enhancepkg-33"><title>Design Rules for Class Action Scripts</title><itemizedlist><listitem><para><indexterm><primary>class action script</primary><secondary>design rules</secondary></indexterm>If a package spans more than one volume, the
class action script is executed once for each volume that contains at least
one file that belongs to a class. Consequently, each script must be able to
be executed more than once. This means that executing a script any number
of times with the same input must produce the same results as executing the
script only once. </para>
</listitem><listitem><para>When a file is part of a class that has a class action script,
the script must install the file. The <command>pkgadd</command> command does
not install files for which a class action script exists, although it does
verify the installation.</para>
</listitem><listitem><para>A class action script should never add, remove, or modify
a path name or system attribute that does not appear in the list generated
by the <command>pkgadd</command> command. For more information on this list,
see item 1 in <olink targetptr="ch3enhancepkg-34" remap="internal">How Classes Are Processed
During Package Installation</olink>.</para>
</listitem><listitem><para>When your script sees the <literal>ENDOFCLASS</literal> argument,
put post-processing actions such as clean up into your script.</para>
</listitem><listitem><para>All administrator interaction is restricted to the <filename>request</filename> script. Do not try to obtain information from the administrator
by using a class action script.</para>
</listitem>
</itemizedlist>
</sect3><sect3 id="ch3enhancepkg-36"><title>The Special System Classes</title><para><indexterm id="ch3enhancepkg-ix67"><primary>object classes</primary><secondary>system</secondary></indexterm><indexterm id="ch3enhancepkg-ix68"><primary>system object classes</primary></indexterm>The system provides four
special classes:</para><itemizedlist><listitem><para><indexterm id="ch3enhancepkg-ix71"><primary>object classes</primary><secondary>system</secondary><tertiary><literal>sed</literal></tertiary></indexterm>The <literal>sed</literal> class</para><para>Provides a method
for using <command>sed</command> instructions to edit files upon package installation
and removal</para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix72"><primary><literal>awk</literal> class</primary></indexterm><indexterm id="ch3enhancepkg-ix73"><primary>object classes</primary><secondary>system</secondary><tertiary><literal>awk</literal></tertiary></indexterm>The <literal>awk</literal> class  </para><para>Provides a method
for using <command>awk</command> instructions to edit files upon package installation
and removal </para>
</listitem><listitem><para><indexterm id="ch3enhancepkg-ix74"><primary><literal>build</literal> class</primary></indexterm><indexterm id="ch3enhancepkg-ix75"><primary>object classes</primary><secondary>system</secondary><tertiary><literal>build</literal></tertiary></indexterm>The <literal>build</literal> class  </para><para>Provides a method
to dynamically construct or modify a file by using Bourne shell commands</para>
</listitem><listitem><para>The <literal>preserve</literal> class</para><para>Provides
a method to preserve files that should not be overwritten by future package
installations</para>
</listitem>
</itemizedlist><para>If several files in a package require special processing that can be
fully defined through <command>sed</command>, <command>awk</command>, or <command>sh</command> commands, installation is faster by using the system classes
rather than multiple classes and their corresponding class action scripts.</para><sect4 id="ch3enhancepkg-37"><title>The <literal>sed</literal> Class Script</title><para><indexterm id="ch3enhancepkg-ix76"><primary><literal>sed</literal> class</primary><secondary>script</secondary></indexterm>The <literal>sed</literal> class
provides a method to modify an existing object on the target system. The <literal>sed</literal> class action script executes automatically at installation if
a file that belongs to class <literal>sed</literal> exists. The name of the <literal>sed</literal> class action script should be the same as the name of the file
on which the instructions are executed.</para><para>A <literal>sed</literal> class action script delivers <command>sed</command> instructions
in the following format:</para><para>Two commands indicate when instructions should be executed. The <command>sed</command> instructions that follow the <command>!install</command> command
are executed during package installation. The <command>sed</command> instructions
that follow the <command>!remove</command> command are executed during package
removal. The order in which these commands are used in the file does not matter. </para><para>For more information on <command>sed</command> instructions, see the <olink targetdoc="refman1" targetptr="sed-1" remap="external"><citerefentry><refentrytitle>sed</refentrytitle><manvolnum>1</manvolnum></citerefentry></olink> man page. For examples of <literal>sed</literal> class action scripts, see <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case Studies of Package
Creation</olink>.</para>
</sect4><sect4 id="ch3enhancepkg-38"><title>The <literal>awk</literal> Class Script</title><para><indexterm id="ch3enhancepkg-ix79"><primary><literal>awk</literal> class</primary><secondary>script</secondary></indexterm>The <literal>awk</literal> class
provides a method to modify an existing object on the target system. Modifications
are delivered as <command>awk</command> instructions in an <literal>awk</literal> class
action script. </para><para>The <literal>awk</literal> class action script is executed automatically
at installation if a file that belongs to class <literal>awk</literal> exists.
Such a file contains instructions for the <literal>awk</literal> class script
in the following format:</para><para>Two commands indicate when instructions should be executed. The <command>awk</command> instructions that follow the <command>!install</command> command
are executed during package installation. The instructions that follow the <command>!remove</command> command are executed during package removal. These commands
may be used in any order. </para><para>The name of the <literal>awk</literal> class action script should be
the same as the name of the file on which the instructions are executed. </para><para>The file to be modified is used as input to the <command>awk</command> command
and the output of the script ultimately replaces the original object. Environment
variables may not be passed to the <command>awk</command> command with this
syntax. </para><para>For more information on <command>awk</command> instructions, see the <olink targetdoc="refman1" targetptr="awk-1" remap="external"><citerefentry><refentrytitle>awk</refentrytitle><manvolnum>1</manvolnum></citerefentry></olink> man page. </para>
</sect4><sect4 id="ch3enhancepkg-39"><title>The <literal>build</literal> Class Script</title><para><indexterm id="ch3enhancepkg-ix82"><primary><literal>build</literal> class</primary><secondary>script</secondary></indexterm>The <literal>build</literal> class
creates or modifies a package object file by executing Bourne shell instructions.
These instructions are delivered as the package object. The instructions run
automatically at installation if the package object belongs to the <literal>build</literal> class.   </para><para>The name of the <literal>build</literal> class action script should
be the same as the name of the file on which the instructions are executed.
The name must also be executable by the <command>sh</command> command. The
script's output becomes the new version of the file as it is built or modified.
If the script produces no output, the file is not created or modified. Therefore,
the script can modify or create the file itself.</para><para>For example, if a package delivers a default file, <literal>/etc/randomtable</literal>, and if the file does not already exist on the target system, the <literal>prototype</literal> file entry might be as follows:</para><screen>e build /etc/randomtable ? ? ?</screen><para>The package object, <literal>/etc/randomtable</literal>, might look
like the following:</para><screen width="100">!install
# randomtable builder
if [ -f $PKG_INSTALL_ROOT/etc/randomtable ]; then
		echo "/etc/randomtable is already in place.";
	    else
		echo "# /etc/randomtable" &gt; $PKG_INSTALL_ROOT/etc/randomtable
		echo "1121554	# first random number" &gt;&gt; $PKG_INSTALL_ROOT/etc/randomtable
fi
 
!remove
# randomtable deconstructor
if [ -f $PKG_INSTALL_ROOT/etc/randomtable ]; then
		# the file can be removed if it's unchanged
		if [ egrep "first random number" $PKG_INSTALL_ROOT/etc/randomtable ]; then
			rm $PKG_INSTALL_ROOT/etc/randomtable;
		fi
fi
 </screen><para>See <olink targetptr="ch5pkgcasestudies-80583" remap="internal">Chapter&nbsp;5, Case
Studies of Package Creation</olink> for another example using the <literal>build</literal> class.</para>
</sect4><sect4 id="ch3enhancepkg-114"><title>The <literal>preserve</literal> Class
Script</title><para>The <literal>preserve</literal> class preserves a package object file
by determining whether or not an existing file should be overwritten when
the package is installed. Two possible scenarios when using a <literal>preserve</literal> class
script are:</para><itemizedlist><listitem><para>If the file to be installed does not already exist in the
target directory, the file will be installed normally.</para>
</listitem><listitem><para>If the file to be installed exists in the target directory,
a message describing that the file exists is displayed, and the file is not
installed.</para>
</listitem>
</itemizedlist><para>Both scenario outcomes are considered successful by the <literal>preserve</literal> script.
A failure occurs only in the second scenario when the file is unable to be
copied to the target directory.</para><para>Starting with the Solaris 7 release, the <filename>i.preserve</filename> script
and a copy of this script, <filename>i.CONFIG.prsv</filename>, can be found
in the <filename>/usr/sadm/install/scripts</filename> directory with the other
class action scripts. </para><para>Modify the script to include the filename or filenames you would like
to preserve.</para>
</sect4>
</sect3>
</sect2><task id="ch3enhancepkg-122"><title>How to Write Class Action Scripts</title><procedure><step id="ch3enhancepkg-step-87"><para><indexterm><primary>class action script</primary><secondary>how to write a</secondary></indexterm>Make the directory that contains
your information files the current working directory.</para>
</step><step id="ch3enhancepkg-step-88"><para>Assign the package objects in the <filename>prototype</filename> file the desired class names.</para><para>For example,
assigning objects to an <literal>application</literal> and <literal>manpage</literal> class
would look like the following:</para><screen>f manpage /usr/share/man/manl/myappl.1l
f application /usr/bin/myappl</screen>
</step><step id="ch3enhancepkg-step-76"><para>Modify the <envar>CLASSES</envar> parameter
in the <filename>pkginfo</filename> file to contain the class names you want
to use in your package. </para><para>For example, entries for the <literal>application</literal> and <literal>manpage</literal> classes would look like the following:</para><screen>CLASSES=manpage application none</screen><note><para>The <literal>none</literal> class is always installed first and
removed last, regardless of where it appears in the definition of the <envar>CLASSES</envar> parameter.</para>
</note>
</step><step id="ch3enhancepkg-step-60"><para>If you are a creating a class action
script for a file that belongs to the <literal>sed</literal>, <literal>awk</literal>,
or <literal>build</literal> class, make the directory that contains the package
object your current working directory.</para>
</step><step id="ch3enhancepkg-step-77"><para>Create the class action scripts or
package objects (for files that belong to the <literal>sed</literal>, <literal>awk</literal>, or <literal>build</literal> class). </para><para>For example,
an installation script for a class named <literal>application</literal> would
be named <literal>i.application</literal> and a removal script would be named <literal>r.application</literal>.</para><para>Remember, when a file is part of a class
that has a class action script, the script must install the file. The <command>pkgadd</command> command does not install files for which a class action script
exists, although it does verify the installation. And, if you define a class
but do not deliver a class action script, the only action taken for that class
is to copy components from the installation medium to the target system (the
default <command>pkgadd</command> behavior).</para>
</step><step id="ch3enhancepkg-step-104"><para>Complete <emphasis>one</emphasis> of
the following tasks.</para><itemizedlist><listitem><para>If you have <emphasis>not</emphasis> created your <filename>prototype</filename> file, complete the procedure <olink targetptr="ch2buildpkg-64" remap="internal">How
to Create a prototype File by Using the pkgproto Command</olink>, and skip
to <olink targetptr="ch3enhancepkg-step-80" remap="internal">Step&nbsp;7</olink>.</para>
</listitem><listitem><para>If you have already created your <filename>prototype</filename> file,
edit it and add an entry for each installation script you just created.</para>
</listitem>
</itemizedlist>
</step><step id="ch3enhancepkg-step-80"><para>Build your package.</para><para>See <olink targetptr="ch2buildpkg-66" remap="internal">How to Build a Package</olink>, if needed.</para>
</step>
</procedure><taskrelated-custom><title>Where to Go Next</title><para>After you build the package, install it to confirm that it installs
correctly and verify its integrity. <olink targetptr="ch4verifypkg-18395" remap="internal">Chapter&nbsp;4,
Verifying and Transferring a Package</olink> explains how to do this and provides
step-by-step instructions on how to transfer your verified package to a distribution
medium.</para>
</taskrelated-custom>
</task>
</sect1><sect1 id="ch6advtech-108"><title>Creating Signed Packages</title><para><indexterm><primary>signed packages</primary><secondary>overview for creating</secondary></indexterm>The process of creating signed packages involves
a number of steps and requires some comprehension of new concepts and terminology.
This section provides information about signed packages, its terminology,
and information about certificate management. This section also provides step-by-step
procedures about how to create a signed package.</para><sect2 id="ch6advtech-97"><title>Signed Packages</title><indexterm><primary>signed package</primary><secondary>definition</secondary>
</indexterm><para>A signed package is a normal stream-format package that has a digital
signature (PEM-encoded PKCS7 digital signature which is defined below) that
verifies the following:</para><itemizedlist><listitem><para>The package came from the entity who signed it</para>
</listitem><listitem><para>The entity indeed signed it</para>
</listitem><listitem><para>The package has not been modified since the entity signed
it</para>
</listitem><listitem><para>The entity who signed it is a trusted entity</para>
</listitem>
</itemizedlist><para>A signed package is identical to an unsigned package, except for the
signature. A signed package is binary-compatible with an unsigned package.
Therefore, a signed package can be used with older versions of the packaging
tools.  However, the signature is ignored in this case.</para><para>The signed packaging technology introduces some new terminology and
abbreviations, which are described in the following table.</para><informaltable frame="all"><tgroup cols="2" colsep="1" rowsep="1"><colspec colname="colspec0" colwidth="35.60*"/><colspec colname="colspec1" colwidth="64.40*"/><thead><row><entry><para>Term</para>
</entry><entry><para>Definition</para>
</entry>
</row>
</thead><tbody><row><entry><para>ASN.1</para>
</entry><entry><para><indexterm><primary>public key</primary><secondary>ASN.1</secondary></indexterm>Abstract Syntax Notation 1 - A way of expressing abstract objects.
For example, ASN.1 defines a public key certificate, all of the objects that
make up the certificate, and the order in which the objects are collected.
However, ASN.1 does not specify how the objects are serialized for storage
or transmission.</para>
</entry>
</row><row><entry><para>X.509</para>
</entry><entry><para><indexterm><primary>public key</primary><secondary>X.509</secondary></indexterm>ITU-T Recommendation X.509 - Specifies the widely-adopted X.509
public key certificate syntax.</para>
</entry>
</row><row><entry><para>DER</para>
</entry><entry><para>Distinguished Encoding Rules - A binary representation of an ASN.1 object
and defines how an ASN.1 object is serialized for storage or transmission
in computing environments.</para>
</entry>
</row><row><entry><para>PEM</para>
</entry><entry><para><indexterm><primary>private key</primary><secondary>PEM</secondary></indexterm>Privacy Enhanced Message - A way to encode a file (in DER or another
binary format) using base 64 encoding and some optional headers. PEM was initially
used for encoding MIME-type email messages. PEM is also used extensively for
encoding certificates and private keys into a file that exists on a file system
or in an email message.</para>
</entry>
</row><row><entry><para>PKCS7</para>
</entry><entry><para>Public Key Cryptography Standard #7 - This standard describes a general
syntax for data that may have cryptography applied to it, such as digital
signatures and digital envelopes. A signed package contains an embedded PKCS7
signature. This signature contains at a minimum the encrypted digest of the
package, along with the signer's X.509 public key certificate. The signed
package can also contain chain certificates. Chain certificates can be used
when forming a chain of trust from the signer's certificate to a locally-stored
trusted certificate.</para>
</entry>
</row><row><entry><para>PKCS12</para>
</entry><entry><para>Public Key Cryptography Standard #12 - This standard describes a syntax
for storing cryptographic objects on disk. The package keystore is maintained
in this format.</para>
</entry>
</row><row><entry><para>Package keystore</para>
</entry><entry><para>A repository of certificates and keys that can be queried by the package
tools.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2><sect2 id="ch6advtech-109"><title>Certificate Management</title><para><indexterm><primary>certificates</primary><secondary>managing</secondary></indexterm> <indexterm><primary>trusted certificate</primary><secondary>definition</secondary></indexterm> <indexterm><primary>certificates</primary><secondary>trusted</secondary></indexterm> <indexterm><primary>public key</primary><secondary>in trusted certificates</secondary></indexterm>Before creating a signed package,
you must have a package keystore. This package keystore contains certificates
in the form of objects. Two types of objects exist in a package keystore:</para><variablelist><varlistentry><term>Trusted certificate</term><listitem><para>A trusted certificate contains a single public key certificate
that belongs to another entity. The trusted certificate is named as such because
the keystore owner trusts that the public key in the certificate indeed belongs
to the identity indicated by the &ldquo;subject&rdquo; (owner) of the certificate.
The issuer of the certificate vouches for this trust by signing the certificate.</para><para><indexterm><primary>user key</primary></indexterm> <indexterm><primary>private key</primary><secondary>user key</secondary></indexterm> <indexterm><primary>public key</primary><secondary>user key</secondary></indexterm>Trusted certificates
are used when verifying signatures and when initiating a connection to a secure
(SSL) server.</para>
</listitem>
</varlistentry><varlistentry><term>User key</term><listitem><para>A user key holds sensitive cryptographic key information.
This information is stored in a protected format to prevent unauthorized access.
A user key consists of both the user's private key and the public key certificate
that corresponds to the private key.</para><para>User keys are used when creating a signed package.</para>
</listitem>
</varlistentry>
</variablelist><para>By default, the package keystore is stored in the <literal>/var/sadm/security</literal> directory. Individual users can also have their own keystore stored
by default in the <literal>$HOME/.pkg/security</literal> directory.</para><para>On disk, a package keystore can be in two formats: a multiple-file format
and a single-file format. A multiple-file format stores its objects in multiple
files. Each type of object is stored in a separate file. All of these files
must be encrypted using the same passphrase. A single-file keystore stores
all of its objects in a single file on the file system.</para><para><indexterm><primary><command>pkgadm</command> command</primary><secondary>managing certificates</secondary></indexterm>The primary utility used to manage the
certificates and the package keystore is the <command>pkgadm</command> command.
The following subsections describe the more common tasks used for managing
the package keystore.</para><sect3 id="ch3enhancepkg-115"><title>Adding Trusted Certificates to the Package
Keystore</title><indexterm><primary>Trusted certificate</primary><secondary>and adding to the package keystore</secondary>
</indexterm><indexterm><primary>Trusted certificatee</primary><secondary>and adding to the package keystore</secondary>
</indexterm><para><indexterm><primary>package keystore</primary><secondary>adding trusted certificates to</secondary></indexterm><indexterm><primary>certificates</primary><secondary>trusted</secondary></indexterm><indexterm><primary>trusted certificate</primary><secondary>adding to the package keystore</secondary></indexterm><indexterm><primary><command>pkgadm</command> command</primary><secondary>adding trusted certificates to package keystore</secondary></indexterm>A trusted certificate
can be added to the package keystore using the<command> pkgadm</command> command.
The certificate can be in PEM or DER format. For example:</para><screen>$ pkgadm addcert -t /tmp/mytrustedcert.pem</screen><para>In this example, the PEM format certificate called <literal>mytrustedcert.pem</literal> is added to the package keystore.</para>
</sect3><sect3 id="ch6advtech-104"><title>Adding a User Certificate and Private Key
to the Package Keystore</title><para><indexterm><primary>package keystore</primary><secondary>adding user certificates and private keys to</secondary></indexterm><indexterm><primary>certificates</primary><secondary>user</secondary></indexterm><indexterm><primary><command>pkgadm</command> command</primary><secondary>adding user certificate and private key to package keystore</secondary></indexterm><indexterm><primary>private key</primary><secondary>adding to package keystore</secondary></indexterm>The <command>pkgadm</command> command does not generate user certificates or private keys.
User certificates and private keys are normally obtained from a Certificate
Authority, such as Verisign. Or, they are generated locally as a self-signed
certificate. Once the key and certificate are obtained, they can be imported
into the package keystore using the <command>pkgadm</command> command. For
example:</para><screen>pkgadm addcert -n myname -e /tmp/myprivkey.pem /tmp/mypubcert.pem</screen><para>In this example, the following options are used:</para><informaltable frame="none"><tgroup cols="2" colsep="0" rowsep="0"><colspec colwidth="50*"/><colspec colwidth="50*"/><tbody><row><entry><para><option>n</option>  <replaceable>myname</replaceable></para>
</entry><entry><para>Identifies the entity (<replaceable>myname</replaceable>) in the package
keystore on which you wish to operate. The <replaceable>myname</replaceable> entity
becomes the alias under which the objects are stored.</para>
</entry>
</row><row><entry><para><option>e</option> <literal>/tmp/</literal><replaceable>myprivkey.pem</replaceable></para>
</entry><entry><para>Specifies the file that contains the private key. In this case, the
file is <replaceable>myprivkey.pem</replaceable>, which is located in the <literal>/tmp</literal> directory.</para>
</entry>
</row><row><entry><para><literal>/tmp/</literal><replaceable>mypubcert.pem</replaceable></para>
</entry><entry><para>Specifies the PEM format certificate file called <replaceable>mypubcert.pem</replaceable>.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect3><sect3 id="ch6advtech-105"><title>Verifying the Contents in the Package Keystore</title><indexterm><primary>package keystore</primary><secondary>verifying the contents</secondary>
</indexterm><para><indexterm><primary>package keystore</primary><secondary>verifying contents of</secondary></indexterm><indexterm><primary><command>pkgadm</command> command</primary><secondary>verifying package keystore contents</secondary></indexterm>The <command>pkgadm</command> command is also used to view the contents of the package
keystore. For example:</para><screen>$ pkgadm listcert</screen><para>This command displays the trusted certificates and private keys in the
package keystore.</para>
</sect3><sect3 id="ch6advtech-106"><title>Deleting Trusted Certificates and Private
Keys From the Package Keystore</title><indexterm><primary>trusted certificate</primary><secondary>deleting from the package keystore</secondary>
</indexterm><indexterm><primary>certificates</primary><secondary>trusted</secondary>
</indexterm><para><indexterm><primary>trusted certificate</primary><secondary>deleting from the package keystore</secondary></indexterm><indexterm><primary>package keystore</primary><secondary>deleting trusted certificates and private keys from</secondary></indexterm><indexterm><primary><command>pkgadm</command> command</primary><secondary>deleting trusted certificates and private keys</secondary></indexterm><indexterm><primary>private key</primary><secondary>deleting from package keystore</secondary></indexterm>The <command>pkgadm</command> command
can be used to delete trusted certificates and private keys from the package
keystore. </para><para>When you delete user certificates, the alias of the certificate/key
pair must be specified. For example:</para><screen>$ pkgadm removecert -n myname</screen><para>The alias of the certificate is the common name of the certificate,
which can be identified using the <command>pkgadm listcert</command> command.
For example, this command deletes a trusted certificate entitled <phrase>Trusted
CA Cert 1</phrase>:</para><screen>$ pkgadm removecert -n "Trusted CA Cert 1"</screen><note><para>If you have both a trusted certificate and a user certificate
stored using the same alias, they are both deleted when you specify the <option>n</option> option.</para>
</note>
</sect3>
</sect2><sect2 id="ch6advtech-110"><title>Signed Packages Creation</title><indexterm><primary>signed package</primary><secondary>how to create</secondary>
</indexterm><para>The process of creating signed packages involves three basic steps:</para><orderedlist><listitem><para>Creating an unsigned, directory-format package.</para>
</listitem><listitem><para>Importing the signing certificate, CA certificates, and private
key into the package keystore.</para>
</listitem><listitem><para>Signing the package from Step 1 with the certificates from
Step 2.</para>
</listitem>
</orderedlist><note><para>The packaging tools do not create certificates. These certificates
must be obtained from a Certificate Authority, such as Verisign or Thawte.</para>
</note><para>Each step for creating signed packages is described in the following
procedures.</para>
</sect2><task id="ch3enhancepkg-123"><title>How to Create an Unsigned, Directory-Format
Package</title><tasksummary><para>The procedure for creating an unsigned, directory-format package is
the same as the procedure for creating a normal package, as previously described
in this manual. The following procedure describes the process of creating
this unsigned, directory-format package. If you need more information, refer
to the previous sections about building packages.</para>
</tasksummary><procedure><step><para><indexterm><primary><filename>pkginfo</filename> file</primary><secondary>creating a signed package, used in</secondary></indexterm> <indexterm><primary><command>pkginfo</command> command</primary><secondary>creating an unsigned package</secondary></indexterm>Create the <literal>pkginfo</literal> file.</para><para>The <literal>pkginfo</literal> file should have the following
basic content:</para><screen>PKG=SUNWfoo
BASEDIR=/
NAME=My Test Package
ARCH=sparc
VERSION=1.0.0
CATEGORY=application</screen>
</step><step id="ch6advtech-step-112"><para><indexterm><primary><filename>prototype</filename> file</primary><secondary>creating a signed package, used in</secondary></indexterm>Create
the <literal>prototype</literal> file.</para><para>The <literal>prototye</literal> file
should have the following basic content:</para><screen><userinput>$cat prototype</userinput>
i pkginfo
d none usr 0755 root sys
d none usr/bin 0755 root bin
f none usr/bin/myapp=/tmp/myroot/usr/bin/myapp 0644 root bin</screen>
</step><step id="ch6advtech-step-113"><para>List the contents of the object source
directory. </para><para>For example:</para><screen><userinput>$ ls -lR /tmp/myroot</userinput></screen><para><indexterm><primary><command>pkgmk</command> command</primary><secondary>creating an unsigned package</secondary><tertiary>in creating signed packages</tertiary></indexterm>The output would appear similar to the following:</para><screen>/tmp/myroot:
total 16
drwxr-xr-x   3 abc      other        177 Jun  2 16:19 usr

/tmp/myroot/usr:
total 16
drwxr-xr-x   2 abc      other        179 Jun  2 16:19 bin

/tmp/myroot/usr/bin:
total 16
-rw-------   1 abc      other       1024 Jun  2 16:19 myapp</screen>
</step><step id="ch6advtech-step-114"><para>Create the unsigned package.</para><screen><userinput>pkgmk -d `pwd`</userinput></screen><para>The output would appear similar to the following:</para><screen>## Building pkgmap from package prototype file.
## Processing pkginfo file.
WARNING: parameter &lt;PSTAMP&gt; set to "syrinx20030605115507"
WARNING: parameter &lt;CLASSES&gt; set to "none"
## Attempting to volumize 3 entries in pkgmap.
part  1 -- 84 blocks, 7 entries
## Packaging one part.
/tmp/SUNWfoo/pkgmap
/tmp/SUNWfoo/pkginfo
/tmp/SUNWfoo/reloc/usr/bin/myapp
## Validating control scripts.
## Packaging complete.</screen><para>The package now exists in the current directory.</para>
</step>
</procedure>
</task><task id="ch3enhancepkg-124"><title>How to Import the Certificates Into the
Package Keystore</title><tasksummary><para><indexterm><primary>package keystore</primary><secondary>importing a certificate into</secondary></indexterm><indexterm><primary>certificates</primary><secondary>importing into package keystore</secondary></indexterm><indexterm><primary>private key</primary><secondary>importing into package keystore</secondary></indexterm>The certificate and private key to be imported must exist as a
PEM- or DER-encoded X.509 certificate and private key. In addition, any intermediate
or &ldquo;chain&rdquo; certificates linking your signing certificate to the
Certificate Authority certificate must be imported into the package keystore
before a package can be signed.</para><note><para><indexterm><primary><command>pkgadm</command> command</primary><secondary>importing certificates into package keystore</secondary></indexterm>Each
Certificate Authority can issue certificates in various formats. To extract
the certificates and private key out of the PKCS12 file and into a PEM-encoded
X.509 file (suitable for importing into the package keystore), use a freeware
conversion utility such as OpenSSL.</para>
</note><para>If your private key is encrypted (which should usually be the case),
you are prompted for the passphrase. Also, you are prompted for a password
to protect the resulting package keystore. You can optionally not supply any
password, but doing so results in an unencrypted package keystore.</para><para>The following procedure describes how to import the certificates using
the <command>pkgadm</command> command once the certificate is in the proper
format. </para>
</tasksummary><procedure><step><para>Import all the Certificate Authority certificates found in your
PEM- or DER-encoded X.509 certificate file.</para><para>For example, to import
all the Certificate Authority certificates found in the file <literal>ca.pem</literal>,
you would type the following:</para><screen><userinput>$ pkgadm addcert -k ~/mykeystore -ty ca.pem</userinput></screen><para>The output would appear similar to the following:</para><screen>Trusting certificate &lt;VeriSign Class 1 CA Individual \
Subscriber-Persona Not Validated&gt;
Trusting certificate &lt;/C=US/O=VeriSign, Inc./OU=Class 1 Public \
Primary Certification Authority
Type a Keystore protection Password.
Press ENTER for no protection password (not recommended): 
For Verification: Type a Keystore protection Password.
Press ENTER for no protection password (not recommended): 
Certificate(s) from &lt;ca.pem&gt; are now trusted</screen><para>In order to import your signing key into the package keystore, you must
supply an alias that is used later when signing the package. This alias can
also be used if you want to delete the key from the package keystore. </para><para>For example, to import your signing key from the file <literal>sign.pem</literal>,
you would type the following:</para><screen><userinput>$ pkgadm addcert -k ~/mykeystore -n mycert sign.pem</userinput></screen><para>The output would appear similar to the following:</para><screen>Enter PEM passphrase:
Enter Keystore Password: 
Successfully added Certificate &lt;sign.pem&gt; with alias &lt;mycert&gt;</screen>
</step><step id="ch6advtech-step-116"><para>Verify that the certificates are in the
package keystore.</para><para>For example, to view the certificates in the
keystore created in the previous step, you would type the following:</para><screen><userinput>$ pkgadm listcert -k ~/mykeystore</userinput></screen>
</step>
</procedure>
</task><task id="ch3enhancepkg-125"><title>How to Sign the Package</title><tasksummary><para><indexterm><primary>pkgtrans command</primary></indexterm>Once the certificates
are imported into the package keystore, you can now sign the package. The
actual signing of the package is done using the <command>pkgtrans</command> command.</para>
</tasksummary><procedure remap="single-step"><step><para>Sign the package using the <command>pkgtrans</command> command.
Supply the location of the unsigned package and the alias of the key to sign
the package.</para><para>For example, using the examples from the previous
procedures, you would type the following to create a signed package called <literal>SUNWfoo.signed</literal>:</para><screen><userinput>$ pkgtrans -g -k ~/mykeystore -n mycert . ./SUNWfoo.signed SUNWfoo</userinput></screen><para>The output of this command would appear similar to the following:</para><screen>Retrieving signing certificates from keystore &lt;/home/user/mykeystore&gt;
Enter keystore password:
Generating digital signature for signer &lt;Test User&gt;
Transferring &lt;SUNWfoot&gt; package instance</screen><para>The signed package is created in the file <literal>SUNWfoo.signed</literal> and
is in the package-stream format. This signed package is suitable for copying
to a web site and being installed using the <command>pkgadd</command> command
and a URL.</para>
</step>
</procedure>
</task>
</sect1>
</chapter><?Pub *0000115768 0?>