saf(1M)




NAME

     saf - Service Access Facility


DESCRIPTION

     The  SAF generalizes the procedures for service   access  so
     that login access on the local system  and network access to
     local services are  managed in similar ways.
      Under the   SAF,  systems  may  access  services  using   a
     variety  of  port monitors, including ttymon,  the listener,
     and port monitors written  expressly for a  user's  applica-
     tion.   The  manner  in  which  a  port monitor observes and
     manages access ports is specific to the  port   monitor  and
     not to any component of the  SAF. Users may therefore extend
     their systems by  developing and installing their  own  port
     monitors.  One of the important features of the  SAF is that
     it can be extended in this way by users.

     Relative to the   SAF,  a  service  is  a  process  that  is
     started.   There are no restrictions on the functions a ser-
     vice may provide. The  SAF consists of  a  controlling  pro-
     cess, the  service access controller (SAC), and two adminis-
     trative levels corresponding  to two levels in the  support-
     ing  directory  structure.   The top administrative level is
     concerned with  port monitor administration, the lower level
     with  service  administration. The  SAC is documented in the
     sac(1M) man page. The administrative levels  and  associated
     utilities are documented in the  System Administration Guide
     - Volume II. The requirements for writing port monitors  and
     the  functions  a port monitor must perform to run under the
     SAF and the  SAC are documented here.

  Port Monitors
     A port monitor is a process that is responsible  for   moni-
     toring a set of homogeneous, incoming ports on a machine.  A
     port monitor's major purpose is to detect incoming   service
     requests and to dispatch them appropriately.

     A port is an externally seen access point on  a  system.   A
     port  may  be  an  address  on  a  network (TSAP or PSAP), a
     hardwired terminal line, an incoming phone line,  etc.   The
     definition  of  what constitutes a port is strictly a  func-
     tion of the port monitor itself.

     A port monitor performs certain basic  functions.   Some  of
     these  are  required  to  conform to the  SAF; others may be
     specified by the requirements and  design of the port  moni-
     tor itself.  Port monitors have two main functions: managing
     ports and monitoring ports for indications of activity.

     Port Management
           The first function of a port monitor is  to  manage  a
           port.  The actual details of how a port is managed are
           defined by the person who defines the port monitor.  A
           port  monitor  is  not restricted to handling a single
           port;  it may handle multiple ports simultaneously.

           Some examples of port management are  setting the line
           speed  on  incoming  phone  connections,   binding  an
           appropriate network address, reinitializing  the  port
           when the service terminates, outputting a prompt, etc.

     Activity Monitoring
           The second function of a port monitor  is  to  monitor
           the  port  or  ports  for  which it is responsible for
           indications of activity.  Two types of activity may be
           detected.

           The first is an indication  to  the  port  monitor  to
           take  some port monitor-specific action.  Pressing the
           break key to indicate that the line  speed  should  be
           cycled  is an example of a port monitor activity.  Not
           all port monitors need to  recognize  and  respond  to
           the  same indications.  The indication used to attract
           the attention of the  port monitor is defined  by  the
           person who defines the port monitor.

           The second is an incoming  service  request.   When  a
           service  request  is received, a port monitor  must be
           able to determine which service  is  being   requested
           from the port on which the request is received.
            The same service may be available on  more  than  one
           port.

  Other Port Monitor Functions
     This section briefly describes other port monitor functions.

     Restricting Access to the System
           A port monitor must be able to restrict access to  the
           system without disturbing services that are still run-
           ning.  In order to do this, a port monitor must  main-
           tain  two  internal states: enabled and disabled.  The
           port monitor starts in the  state  indicated  by   the
           ISTATE  environment variable provided by the  sac. See
           sac(1M) for details. Enabling or disabling a port mon-
           itor  affects all  ports for which the port monitor is
           responsible.
            If a port monitor is responsible for a  single  port,
           only that port will be affected.  If a port monitor is
           responsible for multiple ports,  the entire collection
           of  ports  will  be affected.  Enabling or disabling a
           port monitor is a dynamic  operation:  it  causes  the
           port  monitor  to   change  its  internal  state.  The
           effect does not persist across new invocations of  the
           port  monitor.   Enabling  or  disabling an individual
           port, however,  is a static  operation:  it  causes  a
           change  to an administrative file.  The effect of this
           change will persist across  new   invocations  of  the
           port monitor.

     Creating utmpx Entries
           Port monitors  are  responsible  for  creating   utmpx
           entries  with  the type field set to  USER_PROCESS for
           services they start. If this action has  been   speci-
           fied,  by  using  the -fu option in the  pmadm command
           line that added the service,  these  utmpx entries may
           in  turn be modified by the service.  When the service
           terminates,  the   utmpx  entry   must   be   set   to
           DEAD_PROCESS.

     Port Monitor Process IDs and Lock Files
           When a port monitor starts, it writes its  process  id
           into  a  file named  _pid in the current directory and
           places an advisory lock on the file.

     Changing the Service Environment: Running
           doconfig(3NSL) Before invoking the service  designated
           in  the  port  monitor administrative file,  _pmtab, a
           port monitor must arrange for the per-service   confi-
           guration  script to be run, if one exists, by  calling
           the library  function   doconfig(3NSL).   Because  the
           per-service configuration script may  specify the exe-
           cution of restricted commands, as  well as  for  other
           security reasons, port monitors  are invoked with root
           permissions.  The details of how services are  invoked
           are  specified by the person who defines the port mon-
           itor.

     Terminating a Port Monitor
           A port monitor must  terminate  itself  gracefully  on
           receipt   of  the  signal   SIGTERM.  The  termination
           sequence is the following:

           1. The port monitor  enters  the  stopping  state;  no
              further service requests are accepted.

           2. Any attempt to re-enable the port monitor  will  be
              ignored.

           3. The port monitor yields control of  all  ports  for
              which it is responsible.  It must be possible for a
              new instantiation of the  port   monitor  to  start
              correctly  while  a previous instantiation is stop-
              ping.

           4. The  advisory  lock  on  the  process  id  file  is
              released.  Once this lock is released, the contents
              of the process  id file are  undefined  and  a  new
              invocation of the port monitor may be started.

  SAF Files
     This section briefly covers the files used by the  SAF.

     The Port Monitor Administrative File
           A port monitor's current directory contains an  admin-
           istrative  file named  _pmtab; _pmtab is maintained by
           the   pmadm  command  in  conjunction  with   a   port
           monitor-specific administrative command.

           The port monitor administrative command for a   listen
           port monitor is  nlsadmin(1M); the port monitor admin-
           istrative command for ttymon is  ttyadm(1M). Any  port
           monitor  written  by  a  user must be provided with an
           administrative command specific to that  port  monitor
           to  perform similar functions.

     Per-Service Configuration Files
           A port monitor's current directory also  contains  the
           per-service configuration scripts, if they exist.  The
           names  of  the   per-service   configuration   scripts
           correspond to the service tags in the  _pmtab file.

     Private Port Monitor Files
           A port monitor may create private files in the  direc-
           tory /var/saf/tag,  where  tag is the name of the port
           monitor.  Examples of private files are log  files  or
           temporary files.

  The SAC/Port Monitor Interface
     The  SAC creates two environment  variables  for  each  port
     monitor it starts:PMTAG and ISTATE.

     This variable is set to a unique port  monitor  tag  by  the
     SAC.  The  port  monitor uses this tag to identify itself in
     response to  sac messages.
      ISTATE is used to indicate to the  port  monitor  what  its
     initial   internal  state  should  be.   ISTATE  is  set  to
     "enabled" or "disabled" to indicate that the   port  monitor
     is to start in the enabled or  disabled state respectively.

     The  SAC performs a periodic sanity poll of the  port  moni-
     tors.   The   SAC  communicates  with  port monitors through
     FIFOs.  A port monitor should open _pmpipe, in the   current
     directory,  to  receive messages from the  SAC and  ../_sac-
     pipe to send return messages to the  SAC.

  Message Formats

     This section describes the messages that may be   sent  from
     the   SAC to a port monitor (sac messages),  and from a port
     monitor to the  SAC (port monitor messages).  These messages
     are sent through FIFOs and are in the  form of C structures.

     sac Messages
           The format of messages from the  SAC is defined by the
           structure sacmsg:

           struct sacmsg
           {
                int sc_size; /* size of optional data portion */
                char sc_type; /* type of message */
           };

     The  SAC may send four types of messages to  port  monitors.
     The  type  of  message  is indicated by setting the  sc_type
     field of the  sacmsg structure to one of the following:

     SC_STATUS
           status request

     SC_ENABLE
           enable message

     SC_DISABLE
           disable message

     SC_READDB
           message indicating that the port monitor's _pmtab file
           should be read

     The sc_size field indicates the size of  the  optional  data
     part  of  the message.  See "Message Classes."  For Solaris,
     sc_size should always be set to  0.   A  port  monitor  must
     respond to every message sent by the  sac.

  Port Monitor Messages
     The format of messages from a port monitor to  the   SAC  is
     defined by the structure pmmsg:

     struct pmmsg {
          char pm_type;                /* type of message */
          unchar_t pm_state;           /* current state of port monitor */
          char pm_maxclass;            /* maximum message class this port
                                           monitor understands */
          char pm_tag[PMTAGSIZE + 1];  /* port monitor's tag */
          int pm_size;                 /* size of optional data portion */

     };

     Port monitors may send two types of messages  to  the   SAC.
     The  type  of  message  is indicated by setting the  pm_type
     field of the pmmsg structure to one of the following:

     PM_STATUS
           state information

     PM_UNKNOWN
           negative acknowledgment

     For both types of messages, the  pm_tag field is set  to the
     port  monitor's  tag  and  the  pm_state field is set to the
     port monitor's current state.  Valid states are:

     PM_STARTING
           starting

     PM_ENABLED
           enabled

     PM_DISABLED
           disabled

     PM_STOPPING
           stopping

     The current state reflects any changes caused  by  the  last
     message  from  the   SAC.  The  status message is the normal
     return message.  The negative acknowledgment should be  sent
     only   when the message received is not understood.  pm_size
     indicates the size of the optional data part of the message.
     pm_maxclass  is  used  to specify a message class.  Both are
     discussed under "Message Classes."  In Solaris,  always  set
     pm_maxclass to 1 and  sc_size to 0.  Port monitors may never
     initiate messages; they may
      only respond to messages that they receive.

  Message Classes
     The concept of message class has been included to   accommo-
     date possible  SAF extensions.  The messages described above
     are all class 1 messages.  None of these messages contains a
     variable  data  portion;   all pertinent information is con-
     tained in the message header.  If new messages are added  to
     the  protocol,  they will  be defined as new message classes
     (for example, class 2).  The first message the  SAC sends to
     a  port monitor will  always be a class 1 message. Since all
     port monitors,  by definition, understand class 1  messages,
     the first
      message the  SAC sends is guaranteed to be understood.   In

     its  response  to  the   SAC,  the  port  monitor  sets  the
     pm_maxclass field to the maximum message  class  number  for
     that  port  monitor.   The   SAC will not send messages to a
     port monitor from a  class with a  larger  number  than  the
     value of
      pm_maxclass. Requests that require  messages  of  a  higher
     class  than the  port monitor can understand will fail.  For
     Solaris, always set  pm_maxclass to 1.

     For any given port monitor, messages of  class   pm_maxclass
     and   messages   of  all  classes  with  values  lower  than
     pm_maxclass are valid.  Thus, if the  pm_maxclass  field  is
     set  to 3, the port monitor understands  messages of classes
     1, 2, and 3.  Port monitors may not generate messages;  they
     may  only  respond  to  messages.  A port monitor's response
     must be of the  same  class  as  the   originating  message.
     Since  only  the   SAC  can generate messages, this protocol
     will function even if the port monitor is capable of dealing
      with messages of a higher class than the  SAC can generate.
     pm_size  (an  element  of  the pmmsg structure) and  sc_size
     (an element of the sacmsg structure)  indicate the  size  of
     the  optional  data part of the message.  The format of this
     part  of  the  message  is  undefined.   Its  definition  is
     inherent  in  the  type of message.  For Solaris, always set
     both  sc_size and  pm_size to 0.

  Administrative Interface
     This section discusses the port monitor administrative files
     available under the SAC.

  The SAC Administrative File _sactab
     The service access controller's  administrative  file   con-
     tains  information about all the port monitors for which the
     SAC is responsible.  This file exists on the delivered  sys-
     tem.   Initially,  it  is  empty except for a single comment
     line that  contains the version number  of  the   SAC.  Port
     monitors  are  added  to the system by making entries in the
     SAC's administrative file.  These  entries  should  be  made
     using  the  administrative  command   sacadm(1M)  with a  -a
     option.  sacadm(1M) is also used to remove entries from  the
     SAC's  administrative file.  Each entry in the  SAC's admin-
     istrative file  contains the following information.

     PMTAG A unique tag that identifies a particular  port  moni-
           tor.  The system administrator is responsible for nam-
           ing a port monitor.  This tag is then used by the  SAC
           to  identify  the port  monitor for all administrative
           purposes.  PMTAG may consist of up to 14  alphanumeric
           characters.

     PMTYPE
           The type of the port  monitor.   In  addition  to  its
           unique  tag, each port monitor  has a type designator.
           The type designator identifies a group of port   moni-
           tors  that  are  different  invocations  of  the  same
           entity.  ttymon and listen are examples of valid  port
           monitor types.  The type designator is used to facili-
           tate the  administration of  groups  of  related  port
           monitors.   Without  a  type  designator,  the  system
           administrator  has no way of knowing which port  moni-
           tor  tags  correspond   to  port  monitors of the same
           type.  PMTYPE may consist of  up  to  14  alphanumeric
           characters.

     FLGS  The flags that are currently defined are:

           d     When started, do not enable the port monitor.

           x     Do not start the port monitor.

           If no flag is specified, the default action is  taken.
           By default a port monitor is started and enabled.

     RCNT  The number of times a port  monitor  may  fail  before
           being  placed  in a failed state.  Once a port monitor
           enters the failed state, the  SAC will not try to res-
           tart  it.   If a count is not specified when the entry
           is created,  this field is set to 0.  A restart  count
           of  0  indicates  that  the port monitor  is not to be
           restarted when it fails.

     COMMAND
           A string representing the command that will start  the
           port  monitor.  The first component of the string, the
           command itself, must be a full path name.

  The Port Monitor Administrative File _pmtab
     Each  port  monitor  will  have  two  directories  for   its
     exclusive  use.   The  current  directory will contain files
     defined by the  SAF (_pmtab, _pid) and the per-service  con-
     figuration   scripts,   if   they   exist.    The  directory
     /var/saf/pmtag, where  pmtag is the tag of the port monitor,
     is  available  for   the port monitor's private files.  Each
     port  monitor  has  its  own   administrative   file.    The
     pmadm(1M)  command  should be used to add, remove, or modify
     service entries in this file.  Each time a  change  is  made
     using  pmadm(1M), the corresponding port monitor rereads its
     administrative file.  Each entry in a port monitor's  admin-
     istrative  file  defines  how  the  port  monitor  treats  a
     specific port and  what service is to  be  invoked  on  that
     port.   Some  fields  must  be present for all types of port
     monitors.  Each entry must include a service tag to identify
     the   service uniquely and an identity to be assigned to the
     service when it is started (for example, root).

     The combination of a service tag and  a   port  monitor  tag
     uniquely  define an instance of a service.  The same service
     tag may be used to identify a   service  under  a  different
     port  monitor.   The  record  must also contain port monitor
     specific  data (for example, for a ttymon port monitor, this
     will  include  the  prompt  string  which  is  meaningful to
     ttymon).  Each type of port monitor must provide  a  command
     that   takes  the  necessary  port  monitor-specific data as
     arguments and outputs these data in  a  form   suitable  for
     storage  in the file.  The  ttyadm(1M) command does this for
     ttymon and  nlsadmin(1M) does it for listen.   For  a  user-
     defined port monitor, a similar administrative  command must
     also be supplied.  Each service entry in  the  port  monitor
     administrative  file must have the following format and con-
     tain  the information listed below:

     svctag:flgs:id:reserved:reserved:reserved:pmspecific# comment

     SVCTAG is a unique tag that identifies a service.  This  tag
     is  unique only for the port monitor  through which the ser-
     vice is available.  Other port monitors may offer  the  same
     or  other   services  with the same tag.  A service requires
     both a port monitor tag and a  service tag  to  identify  it
     uniquely.  SVCTAG may consist of up to 14 alphanumeric char-
     acters.  The service entries are defined as:

     FLGS  Flags with the following  meanings  may  currently  be
           included in this field:

           x     Do not enable this port. By default the port  is
                 enabled.

           u     Create  a  utmpx  entry  for  this  service.  By
                    default  no  utmpx  entry  is created for the
                 service.

     ID    The identity under which the service is to be started.
           The  identity  has  the  form  of  a  login name as it
           appears in  /etc/passwd.

     PMSPECIFIC
           Examples of port monitor  information  are  addresses,
           the   name  of  a process to execute, or the name of a
           STREAMS  pipe to  pass  a  connection  through.   This
           information  will vary to meet the needs of each  dif-
           ferent type of port monitor.

     COMMENT
           A comment associated with the service entry. Port mon-
           itors may ignore the u flag  if creating a utmpx entry
           for the service is  not appropriate to the  manner  in
           which  the   service  is to be invoked.  Some services
           may not start properly unless utmpx  entries have been
           created for them (for example, login).  Each port mon-
           itor administrative file  must   contain  one  special
           comment of the form:

           # VERSION=value

           where value is an integer that  represents   the  port
           monitor's  version number.  The version number defines
           the format of the  port monitor  administrative  file.
           This  comment  line  is  created  automatically when a
           port monitor is added to the system.  It appears on  a
           line by itself, before the service entries.

  Monitor-Specific Administrative Command
     Previously,  two  pieces  of  information  included  in  the
     _pmtab  file  were  described:  the  port  monitor's version
     number  and the port monitor part of the service entries  in
     the port monitor's  _pmtab file.  When a new port monitor is
     added, the version  number must be known so that the  _pmtab
     file  can  be  correctly initialized.  When a new service is
     added, the port monitor part of the  _pmtab  entry  must  be
     formatted  correctly.  Each port monitor must have an admin-
     istrative  command to perform these two tasks.   The  person
     who defines the port monitor must also define such an admin-
     istrative command and its input options.  When  the  command
     is invoked with these options,  the information required for
     the  port  monitor   part  of  the  service  entry  must  be
     correctly   formatted  for  inclusion  in the port monitor's
     _pmtab file and must be written to the standard output.   To
     request the version number the command must be  invoked with
     a  -V option; when it is invoked  in  this  way,   the  port
     monitor's  current  version  number  must  be written to the
     standard output.  If the command fails for any reason during
     the   execution of either of these tasks, no data  should be
     written to standard output.

  The Port Monitor/Service Interface
     The interface between  a  port  monitor  and  a  service  is
     determined solely by the service.  Two mechanisms for invok-
     ing a service are presented here as examples.

     New Service Invocations
           The first interface is for services that are   started
           anew  with  each request.  This interface requires the
           port monitor to  first  fork(2) a child process.   The
           child  will  eventually become the designated  service
           by performing an  exec(1).  Before the   exec(1)  hap-
           pens, the port monitor may take some port
            monitor-specific action;  however,  one  action  that
           must  occur  is  the interpretation of the per-service
           configuration script, if one is present.  This is done
           by calling the library routine  doconfig(3NSL).

     Standing Service Invocations
           The second interface is for  invocations  of  services
           that  are  actively running.  To use this interface, a
           service must have one  end of a stream pipe  open  and
           be prepared to  receive connections through it.

  Port Monitor Requirements
     To implement a port monitor, several  generic   requirements
     must  be  met.   This section summarizes these requirements.
     In addition to the port monitor itself,  an   administrative
     command must be supplied.

     Initial Environment
           When a port monitor is started, it expects an  initial
           execution environment in which:

              o  It has no file descriptors open

              o  It cannot be a process group leader

              o  It  has  an  entry  in    /etc/utmpx   of   type
                 LOGIN_PROCESS

              o  An environment  variable,   ISTATE,  is  set  to
                 "enabled"  or  "disabled"  to indicate  the port
                 monitor's correct initial state

              o  An environment variable,  PMTAG, is set  to  the
                 port monitor's assigned tag

              o  The directory that contains the  port  monitor's
                 administrative files is its current directory

              o  pThe port monitor  is  able  to  create  private
                 files in the directory /var/saf/tag,  where  tag
                 is the port monitor's tag

              o  The port monitor  is  running  with  user  id  0
                 (root)

     Important Files
           Relative to its current directory, the following   key
           files exist for a port monitor.

           _config
                 The port monitor's  configuration  script.   The
                 port  monitor configuration script is run by the
                 SAC.  The  SAC is  started  by   init(1M)  as  a
                 result  of  an entry in  /etc/inittab that calls
                 sac(1M).

           _pid  The file into which the port monitor writes  its
                 process id.

           _pmtab
                 The port monitor's  administrative  file.   This
                 file  contains  information  about the ports and
                 services for which the port monitor is responsi-
                 ble.

           _pmpipe
                 The FIFO through which  the  port  monitor  will
                 receive messages from the  SAC.

           svctag
                 The per-service  configuration  script  for  the
                 service with the tag  svctag.

           ../_sacpipe
                 The FIFO through which  the  port  monitor  will
                 send messages to  sac(1M).

  Port Monitor Responsibilities
     A port monitor is responsible for performing the   following
     tasks in addition to its port monitor function:

        o  Write its process id into the file  _pid and place  an
           advisory lock on the file

        o  Terminate gracefully on receipt of the signal SIGTERM

        o  Follow the protocol for message exchange with the  SAC

     A port monitor must perform the following tasks  during ser-
     vice invocation:

        o  Create a  utmpx entry if the requested service has the
           u flag set in  _pmtab

        o  Port monitors may  ignore  this  flag  if  creating  a
           utmpx  entry  for  the  service  does  not  make sense
           because of the manner in which the service  is  to  be
           invoked.
            On the other hand, some services may not start  prop-
           erly  unless utmpx entries have been created for them.

        o  Interpret the per-service  configuration  script   for
           the  requested  service, if it exists,  by calling the
           doconfig(3NSL) library routine

  Configuration Files and Scripts
     The library routine  doconfig(3NSL), defined in   libnsl.so,
     interprets the configuration scripts contained in the  files
     /etc/saf/_sysconfig (the per-system configuration file), and
     /etc/saf/pmtag/_config   (per-port   monitor   configuration
     files); and in   /etc/saf/pmtag/svctag  (per-service  confi-
     guration files).  Its syntax is:

          #include <sac.h>
          int doconfig (int fd, char *script, long rflag);

     script is the name of the configuration  script;   fd  is  a
     file  descriptor that designates the stream  to which stream
     manipulation operations are to be applied;  rflag is a  bit-
     mask  that  indicates  the  mode  in   which script is to be
     interpreted.  rflag may take two values,  NORUN  and   NOAS-
     SIGN, which may be or'd.  If  rflag is zero, all commands in
     the configuration  script are eligible to be interpreted.
      If  rflag has the  NOASSIGN bit set, the assign command  is
     considered   illegal  and will generate an error return.  If
     rflag has the  NORUN bit set, the run and  runwait  commands
     are  considered illegal and will generate error returns.  If
     a command in the script fails, the  interpretation   of  the
     script  ceases  at  that  point  and  a positive  integer is
     returned; this number indicates which  line  in  the  script
     failed.   If  a  system  error  occurs,  a  value  of  -1 is
     returned.  If a script fails, the process whose  environment
     was  being  established should not be started.  In the exam-
     ple,  doconfig(3NSL) is used to interpret a per-service con-
     figuration script.

      ...
               if ((i = doconfig (fd, svctag, 0)) != 0){
               error ("doconfig failed on line %d of script %s",i,svctag);
          }

     The Per-System Configuration File
           The       per-system        configuration        file,
           /etc/saf/_sysconfig,  is  delivered  empty.  It may be
           used to customize the environment for all  services on
           the  system by writing a command script  in the inter-
           preted language described in this chapter  and on  the
           doconfig(3NSL)  manpage.  When the  SAC is started, it
           calls the  doconfig(3NSL) function  to  interpret  the
           per-system  configuration script.  The  SAC is started
           when the system enters multiuser mode.

     Per-Port Monitor Configuration Files
           Per-port    monitor    configuration     scripts     (
           /etc/saf/pmtag/_config)  are optional.  They allow the
           user to customize the environment for  any given  port
           monitor  and  for  the  services  that   are available
           through the ports for  which   that  port  monitor  is
           responsible.   Per-port  monitor configuration scripts
           are  written in the same language used for  per-system
           configuration  scripts.   The  per-port monitor confi-
           guration script is  interpreted when the port  monitor
           is  started.   The port monitor is started by the  SAC
           after the  SAC has itself been started  and  after  it
           has      run    its    own    configuration    script,
           /etc/saf/_sysconfig. The per-port  monitor  configura-
           tion  script  may  override   defaults provided by the
           per-system configuration script.

     Per-Service Configuration Files
           Per-service configuration files  allow  the   user  to
           customize the environment for a specific service.  For
           example, a  service  may  require  special  privileges
           that are not available to the general user.  Using the
           language described in the  doconfig(3NSL) manpage, you
           can write a script that will  grant or limit such spe-
           cial  privileges  to  a   particular  service  offered
           through  a  particular  port monitor.  The per-service
           configuration  may  override   defaults  provided   by
           higher-level  configuration scripts.  For example, the
           per-service configuration script  may specify a set of
           STREAMS modules other than the default set.

  The Configuration Language
     The language in which  configuration  scripts  are   written
     consists of a sequence of commands, each of  which is inter-
     preted separately.   The  following  reserved  keywords  are
     defined:   assign, push, pop, runwait, and  run. The comment
     character is #.  Blank lines are not significant.   No  line
     in a command script may exceed 1024 characters.

     assign variable=value
           Used to define environment variables;  variable is the
           name  of  the  environment  variable and  value is the
           value to be assigned to it.  The value  assigned  must
           be a string constant;
            no  form  of  parameter  substitution  is  available.
           value may be quoted.  The quoting rules are those used
           by the  shell  for   defining  environment  variables.
           assign  will fail if space cannot be allocated for the
           new variable or if any part of  the  specification  is
           invalid.

     push module1[, module2, module3, . . .]
           Used to push STREAMS modules onto the  stream   desig-
           nated  by  fd; module1 is the name of the first module
           to be pushed,  module2  is  the  name  of  the  second
           module to be pushed, and so on.
            The command will fail if any of  the  named   modules
           cannot  be  pushed.  If a module cannot be pushed, the
           subsequent modules  on the same command line  will  be
           ignored  and  modules   that  have already been pushed
           will be popped.

     pop [module]
           Used to pop STREAMS modules off the designated stream.
           If   pop is invoked with no arguments, the top  module
           on the stream is popped.  If  an  argument  is  given,
           modules  will be popped  one at a time until the named
           module  is at the top of the  stream.   If  the  named
           module is not on the designated stream,  the stream is
           left as it was and the command fails.  If   module  is
           the  special  keyword   ALL,  then  all modules on the
           stream will be popped.
            Only modules above the topmost driver are affected.

     runwait command
           The  runwait command runs a command and waits  for  it
           to  complete;  command is the path name of the command
           to be run.   The  command  is  run  with   /bin/sh  -c
           prepended  to  it;  shell scripts may thus be executed
           from configuration scripts.  The  runwait command will
           fail  if  command  cannot  be found or  cannot be exe-
           cuted, or if  command exits with a nonzero status.

     run command
           The  run command is identical to  runwait except  that
           it  does  not wait for command to complete; command is
           the path name of the command to be run.  run will  not
           fail unless it is unable to create a  child process to
           execute the command.  Although they are  syntactically
           indistinguishable,   some of the commands available to
           run and  runwait are  interpreter  built-in  commands.
           Interpreter  built-ins  are used when it is  necessary
           to alter the state of a process  within the context of
           that process.  The  doconfig interpreter built-in com-
           mands are similar to the  shell special commands  and,
           like  these,  they  do   not spawn another process for
           execution.  See the  sh(1) man page.  The initial  set
           of built-in commands is:  cd, ulimit, umask.

  Sample Port Monitor Code
     This example shows an example of a "null" port  monitor that
     simply responds to messages from the  SAC.

     # include <stdlib.h>
     # include <stdio.h>
     # include <unistd.h>
     # include <fcntl.h>
     # include <signal.h>
     # include <sac.h>

     char Scratch[BUFSIZ]; /* scratch buffer */
     char Tag[PMTAGSIZE + 1]; /* port monitor's tag */
     FILE *Fp; /* file pointer for log file */
     FILE *Tfp; /* file pointer for pid file */
     char State; /* portmonitor's current state*/

     main(argc, argv)
          int argc;
          char *argv[];
     {
          char *istate;
          strcpy(Tag, getenv("PMTAG"));
     /*
      * open up a log file in port monitor's private directory
      */
          sprintf(Scratch, "/var/saf/%s/log", Tag);
          Fp = fopen(Scratch, "a+");
          if (Fp == (FILE *)NULL)
               exit(1);
          log(Fp, "starting");
     /*
      * retrieve initial state (either "enabled" or "disabled") and set
      * State accordingly
      */
          istate = getenv("ISTATE");
          sprintf(Scratch, "ISTATE is %s", istate);
          log(Fp, Scratch);
          if (!strcmp(istate, "enabled"))
               State = PM_ENABLED;
          else if (!strcmp(istate, "disabled"))
               State = PM_DISABLED;
          else {
               log(Fp, "invalid initial state");
               exit(1);
          }
          sprintf(Scratch, "PMTAG is %s", Tag);
          log(Fp, Scratch);
     /*
      * set up pid file and lock it to indicate that we are active
      */
          Tfp = fopen("_pid", "w");
          if (Tfp == (FILE *)NULL) {
               log(Fp, "couldn't open pid file");
               exit(1);
          }
          if (lockf(fileno(Tfp), F_TEST, 0) < 0) {
               log(Fp, "pid file already locked");
               exit(1);
          }

          log(Fp, "locking file");
          if (lockf(fileno(Tfp), F_LOCK, 0) < 0) {
               log(Fp, "lock failed");
               exit(1);
          }
          fprintf(Tfp, "%d", getpid());
          fflush(Tfp);

     /*
      * handle poll messages from the sac ... this function never returns
      */
          handlepoll();
          pause();
          fclose(Tfp);
          fclose(Fp);
     }

     handlepoll()
     {
          int pfd; /* file descriptor for incoming pipe */
          int sfd; /* file descriptor for outgoing pipe */
          struct sacmsg sacmsg; /* incoming message */
          struct pmmsg pmmsg; /* outgoing message */
     /*
      * open pipe for incoming messages from the sac
      */
          pfd = open("_pmpipe", O_RDONLY|O_NONBLOCK);
          if (pfd < 0) {
               log(Fp, "_pmpipe open failed");
               exit(1);
          }
     /*
      * open pipe for outgoing messages to the sac
      */
          sfd = open("../_sacpipe", O_WRONLY);
          if (sfd < 0) {
               log(Fp, "_sacpipe open failed");
               exit(1);
          }
     /*
      * start to build a return message; we only support class 1 messages
      */
          strcpy(pmmsg.pm_tag, Tag);
          pmmsg.pm_size = 0;
          pmmsg.pm_maxclass = 1;
     /*
      * keep responding to messages from the sac
      */
          for (;;) {
               if (read(pfd, &sacmsg, sizeof(sacmsg)) != sizeof(sacmsg)) {
                    log(Fp, "_pmpipe read failed");
                    exit(1);
               }
     /*
      * determine the message type and respond appropriately
      */
               switch (sacmsg.sc_type) {
                    case SC_STATUS:
                         log(Fp, "Got SC_STATUS message");
                         pmmsg.pm_type = PM_STATUS;
                         pmmsg.pm_state = State;
                         break;
                    case SC_ENABLE:
                         /*note internal state change below*/
                         log(Fp, "Got SC_ENABLE message");
                         pmmsg.pm_type = PM_STATUS;
                         State = PM_ENABLED;
                         pmmsg.pm_state = State;
                         break;
                    case SC_DISABLE:
                         /*note internal state change below*/
                         log(Fp, "Got SC_DISABLE message");
                         pmmsg.pm_type = PM_STATUS;
                         State = PM_DISABLED;
                         pmmsg.pm_state = State;
                         break;
                    case SC_READDB:
                         /*
                          * if this were a fully functional port
                          * monitor it would read _pmtab here
                          * and take appropriate action
                          */
                         log(Fp, "Got SC_READDB message");
                         pmmsg.pm_type = PM_STATUS;
                         pmmsg.pm_state = State;
                         break;
                    default:
                         sprintf(Scratch, "Got unknown message <%d>",
                         sacmsg.sc_type);
                         log(Fp, Scratch);
                         pmmsg.pm_type = PM_UNKNOWN;
                         pmmsg.pm_state = State;
                         break;
               }
     /*
      * send back a response to the poll
      * indicating current state
      */
               if (write(sfd, &pmmsg, sizeof(pmmsg)) != sizeof(pmmsg))
                    log(Fp, "sanity response failed");
          }
     }
     /*
      * general logging function
      */
     log(fp, msg)
          FILE *fp;
          char *msg;
     {
          fprintf(fp, "%d; %s\n", getpid(), msg);
          fflush(fp);
     }

  The sac.h Header File
     The following example shows the sac.h header file.

     /* length in bytes of a utmpx id */
     # define IDLEN 4
     /* wild character for utmpx ids */
     # define SC_WILDC 0xff
     /* max len in bytes for port monitor tag */
     # define PMTAGSIZE 14
     /*
      * values for rflag in doconfig()
      */
     /* don't allow assign operations */
     # define NOASSIGN 0x1
     /* don't allow run or runwait operations */
     # define NORUN 0x2
     /*
      * message to SAC (header only). This header is forever fixed. The
      * size field (pm_size) defines the size of the data portion of the
      * message, which follows the header. The form of this optional data
      * portion is defined strictly by the message type (pm_type).
      */
     struct pmmsg {
          char pm_type;               /* type of message */
          unchar_t pm_state;            /* current state of pm */
          char pm_maxclass;           /* max message class this port monitor
                                              understands */
          char pm_tag[PMTAGSIZE + 1]; /* pm's tag */
          int pm_size;                /* size of opt data portion */
     };
     /*
      * pm_type values
      */
     # define PM_STATUS 1 /* status response */
     # define PM_UNKNOWN 2 /* unknown message was received */
     /*
      * pm_state values
      */

     /*
      * Class 1 responses
      */
     # define PM_STARTING 1   /* monitor in starting state */
     # define PM_ENABLED 2    /* monitor in enabled state */
     # define PM_DISABLED 3   /* monitor in disabled state */
     # define PM_STOPPING 4   /* monitor in stopping state */
     /*
      * message to port monitor
      */
     struct sacmsg {
          int sc_size;         /* size of optional data portion */
          char sc_type;        /* type of message */
     };
     /*
      * sc_type values
      * These represent commands that the SAC sends to a port monitor.
      * These commands are divided into "classes" for extensibility. Each
      * subsequent "class" is a superset of the previous "classes" plus
      * the new commands defined within that "class". The header for all
      * commands is identical; however, a command may be defined such that
      * an optional data portion may be sent in addition to the header.
      * The format of this optional data piece is self-defining based on
      * the command. The first message sent by the SAC
      * will always be a class 1 message. The port monitor response
      * indicates the maximum class that it is able to understand. Another
      * note is that port monitors should only respond to a message with
      * an equivalent class response (i.e. a class 1 command causes a
      * class 1 response).
      */
     /*
      * Class 1 commands (currently, there are only class 1 commands)
      */
     # define SC_STATUS 1    /* status request *
     # define SC_ENABLE 2    /* enable request */
     # define SC_DISABLE 3   /* disable request */
     # define SC_READDB 4    /* read pmtab request */
     /*
      * `errno' values for Saferrno, note that Saferrno is used by both
      * pmadm and sacadm and these values are shared between them
      */
     # define E_BADARGS 1   /* bad args/ill-formed cmd line */
     # define E_NOPRIV 2    /* user not priv for operation */
     # define E_SAFERR 3    /* generic SAF error */
     # define E_SYSERR 4    /* system error */
     # define E_NOEXIST 5   /* invalid specification */
     # define E_DUP 6       /* entry already exists */
     # define E_PMRUN 7     /* port monitor is running */
     # define E_PMNOTRUN 8  /* port monitor is not running */
     # define E_RECOVER 9
        /* in recovery */

  Directory Structure
     This section gives a  description  of  the   SAF  files  and
     directories.

     /etc/saf/_sysconfig
           The per-system configuration script.

     /etc/saf/_sactab
           The  SAC's administrative file.  Contains  information
           about the port monitors for which the SAC is responsi-
           ble.

     /etc/saf/pmtag
           The home directory for port monitor  pmtag.

     /etc/saf/pmtag/_config
           The per-port monitor  configuration  script  for  port
           monitor  pmtag.   /etc/saf/pmtag/_pmtab  Port  monitor
           pmtag's  administrative  file.   Contains  information
           about  the  services  for which  pmtag is responsible.
           /etc/saf/pmtag/svctag  The  file  in  which  the  per-
           service  configuration  script  for   service   svctag
           (available through port  monitor   pmtag)  is  placed.
           /etc/saf/pmtag/_pid  The  file in which a port monitor
           writes its  process id in the  current  directory  and
           places  an  advisory lock on the file. /etc/saf/ pmtag
           /_pmpipe The file in which the port  monitor  receives
           messages  from  the   SAC  and   ../_sacpipe and sends
           return messages to the  SAC. /var/saf/_log The   SAC's
           log  file.   /var/saf/pmtag  The  directory  for files
           created by port monitor  pmtag, for  example  its  log
           file.


LIST OF COMMANDS

     The following administrative commands relate to  SAF.

     sacadm(1M)
           port monitor administrative command

     pmadm(1M)
           service administration command


ATTRIBUTES

     See attributes(5) for descriptions of the  following  attri-
     butes:

     ____________________________________________________________
    |       ATTRIBUTE TYPE        |       ATTRIBUTE VALUE       |
    |_____________________________|_____________________________|
    | Availability                | SUNWcsr                     |
    |_____________________________|_____________________________|


SEE ALSO

     exec(1), sh(1), init(1M), nlsadmin(1M), pmadm(1M),  sac(1M),
     sacadm(1M),   ttyadm(1M),  fork(2),  doconfig(3NSL),  attri-
     butes(5)


Man(1) output converted with man2html