  shellmod
  Introduction


  1.  What is shellmod

  Shellmod is a Linuxconf module as well as a stand-alone utility.  Its
  goal is to allow easy writing of other Linuxconf modules and stand-
  alone utilities using sh (/bin/sh, the shell interpretor).

  The benefit of writing Linuxconf modules (or simply administration
  utilities) this way are:


  o  Nice interface: Your script will work both in text and graphical
     mode, with a much better appearance than an usual shell script.
     When used as a module in Linuxconf, it will even work in HTML,
     completely transparently.

  o  Simplicity: It is possible to write useful stuff in a 10-15 lines
     shell script. It is possible to turn an non interactive existing
     10-15 lines shell script into a 15-20 lines cool interactive
     script, running     both in text, GUI mode, and even HTML mode.

  o  Used as a module, your script will be able to hook itself in
     various Linuxconf menus, making it fully integrated in the
     administration scheme.

  o  Not only the script can enhance Linuxconf menus, it can even
     participate as a co-manager in some dialogs. This means that a
     simple script can add new fields in the user account dialog for
     example.

  Normal C++ Linuxconf module can do more things obviously, but scripts
  offers a nice and efficient solution for custom installation and on
  site support. A new Linuxconf module may be develop with the
  user/friend/customer looking over your shoulder.


  2.  Principles

  In this section we will see the basic layout of a shellmod script, how
  to use it and how it communicate with Linuxconf.


  2.1.  Components of the shellmod package

  The shellmod package provides the following parts:


  o  The shellmod utility used to run shellmod script without Linuxconf.
     This utility is located in /usr/bin.

  o  The shellmod module which allows shellmod script to interact with
     Linuxconf. Note that a shellmod script can be used both ways,
     either stand-alone or embedded in Linuxconf.

  o  The shellmod-lib.sh function library. This is located in
     /usr/lib/linuxconf/lib. This contains utility functions simplifying
     shellmod scripts. This file must be sourced in all scripts.

  o  Some sample script.

  o  At some point, the package will contain some contrib scripts and a
     browser will be designed to easily find and try those contrib
     scripts. If you have written something general and useful, send it
     on the Linuxconf mailing list, for inclusion in this package.


  2.2.  How to use shellmod scripts

  A script may be used either stand-alone or within Linuxconf. It can be
  used both ways.


  2.2.1.  As a stand-alone utility

  To run a shellmod script, you either do



               shellmod path_of_the_script [ arguments ]





  Or if the script start with #!/usr/bin/shellmod, you simply run it
  like any utility. Note that in all cases, the script must be
  executable (chmod +x script).


  2.2.2.  As a Linuxconf module

  To be used this way, it must be registered in Linuxconf. This is done
  either interactively or using a special command line. The shellmod
  module register its configuration menu in the Control files and
  systems menu. You will find there a dialog to register your script.
  Just enter the path of your script and that's it. The script will be
  visible in Linuxconf at the next run.

  The script may be registered using the following command line. This is
  especially useful if you include your script in a package and would
  like to register the script in Linuxconf at package installation (RPM
  packagers might consider the trigger facility to do this).



               linuxconf --modulemain shellmod --setmod script_path





  Note that the linuxconf --modulemain construct is the normal way to
  yield control to a module own command line: shellmod is not different.

  You may unregister a script from Linuxconf by doing:



               linuxconf --modulemain shellmod --unsetmod script_path





  Note that the above syntax replicate the way normal (C++) Linuxconf
  modules may be registered and unregistered, by using the linuxconf
  --setmod and linuxconf --unsetmod command lines.


  2.3.  Layout of a shellmod script

  A shellmod script will always look like this:



               #!/usr/bin/shellmod
               . /usr/lib/linuxconf/lib/shellmod-lib.sh
               register(){
                       # Put regmenu and comanager calls here
               }
               # Put here the various functions referenced above

               main(){
                       # We define a sub-menu or a dialog
               }
               # The script always end with the dispatch function call. Always
               dispatch






  2.3.1.  The shellmod-lib.sh function library


  2.3.2.  The register function

  The register function is required if the script is used as a Linuxconf
  module. Linuxconf will call the function expecting the script to pass
  back the list of menu and dialog in which it want to register. Here is
  an example of a register function installing two sub-menu and one co-
  manager.



               # Register in the "miscellaneous service" menu
               echo regmenu main MENU_MISCSERV \"main menu of the module\"
               # Register at the end of the dnsconf menu
               echo regmenu function2 dnsconf \"Some title\"
               # Register as a co-manager in the user account dialog
               echo comanager function-prefix user






  2.3.3.  The register function for stand-alone only module

  The register function is not needed for stand-alone module. It is a
  good idea to provide a minimal one in case a user try to register this
  module in Linuxconf. The following one will make it clear the script
  is not intended to be use this way:



               register(){
                       echo error \"This shellmod script can't be use as a module\"
               }





  2.3.4.  The main function

  If the script is used stand-alone, it requires a function called main.
  The shellmod utility will blindly call this function.  It is a good
  idea to always provide one. In the register function we often register
  in a Linuxconf menu the main function. Done this way, the script
  provides a consistent interface used either stand-alone or as a
  Linuxconf module.

  The main function will generally define a menu or a dialog. Note that
  the main function is the one which will receive the script arguments.
  The arguments will often be used as default values for the dialog
  fields.  Here is a small example.



               main(){
                       echo DIALOG
                       echo newf_str path \"Document path\" $1
                       echo newf_str mail \"Email this document to\" $2
                       echo newf_str fax \"Fax this document to\" $3
                       echo edit \"Document manager\" \"Fill this form to send the document\"
                       dispatch
                       echo end
                       if [ "$CODE" = "accept" ] ; then
                               if [ "$mail" != "" ] ; then
                                       cat $path | mail $mail
                               fi
                               if [ "$fax" != "" ] ; then
                                       spoolfax $fax $path
                               fi
                       fi
               }






  2.3.5.  The dispatch function

  A module always ends with a call to the dispatch function. A shellmod
  script may be seen as a set of function waiting to be called (A
  library).  Based on context, Linuxconf (or shellmod for stand-alone
  scripts) will call the appropriate one.

  Note that the script can perform some initialization before calling
  the dispatch function. As explain later, a script may be seen as a
  small server which keeps its state between calls to its various
  functions.


  2.4.  How does it works

  A shellmod script interact with shellmod or Linuxconf by echoing
  commands on it standard output. It receives directives by simply
  reading its standard input. The dispatch function takes care of
  reading and processing (dispatching) the request it receives.  We can
  think of the script as being in sandwich between two shellmod process
  like this



               shellmod | script | shellmod


  Everything echoed by the script is grabbed by shellmod and interpreted
  as protocol commands. It is important to redirect the output of sub-
  command you are using either to the error channel (command >&2) or to
  /dev/null. Failing to do so will trigger many error messages from
  shellmod.


  3.  Protocol

  we will now present the various commands issued by the script. Those
  commands will be split by task


  3.1.  Command layout and quoting

  All command sent to shellmod are done using the echo shell command.
  They always looks like:



               echo command arg1 arg2 arg3





  Arguments are either a single or multiple words (separated with
  spaces).  To group multiple words as a single argument, quotes must be
  used.  While this is standard command line practice, there is a catch:
  Quoting will only affect the argument as seen by the echo command.
  Once process, the whole line will be received as a single stream of
  words separated by space and the quote will be gone. The quotes must
  be part of the line received by shellmod. Here is an example



               echo newf_str name \"Enter your name\" \"Tux the penguin\"





  The shellmod-lib.sh define the qecho helper function you may used to
  get a more standard shell quoting behavior. Here the same example
  rewritten with qecho.



               qecho newf_str name "Enter your name" 'Tux the penguin'





  As you see, with qecho you can mix the different shell quoting syntax.
  The qecho function insures that proper double quotes surround all
  arguments.



  3.2.  Sending multi-line parameters

  Shell scripts are not that good at handling and passing multi-line
  text. The "defval" command was created to fix that.  Here is a typical
  usage:

               echo var1 "This is the first line"
               echo var1 "This is the second line"
               echo error =var1





  This creates a popup error message with two lines. "defval" is used
  repeatedly to define the multi-line text and is referenced as an
  argument using the = sign. The argument must not be quoted. So you
  can't use the qecho helper function using a defvar parameter, because
  qecho insures quoting around all parameters.


  3.3.  Building a dialog



  3.3.1.  echo DIALOG

  A dialog always starts with this command. It requires no further
  argument.  Then you stuff it with field definitions, add optional
  buttons and then you call the edit function. Here is a sample:



               echo DIALOG
               echo newf_str var \"field title\" value
               edho edit \"Dialog title\" \"Dialog introduction\"
               dispatch
               echo end






  3.3.2.  roman }

  This pops up the dialog. The window title control using the first
  argument and the longer dialog description is controlled by the
  introduction field.

  The last argument is option and lets you control the buttons displayed
  at the bottom of the dialog. The value "0" means to display no button
  (useful to display some gauge for example).

  When the last argument is omitted, the button Accept and Cancel are
  displayed.


  3.3.3.  echo show \"title\" \"Introduction\"

  This works like edit. It pops up the dialog with the same arguments.
  But it return immediatly. This is generally used with the
  ``newf_gauge'' command.


  3.3.4.  dispatch

  This yield control to Linuxconf/shellmod and wait for results.  Field
  variable are updated and the CODE variable is set to the button value
  selected by the user: This is either "accept" or "cancel".


  3.3.5.  echo end

  This deletes the dialog. It is removed from the screen and forgotten.
  We often issue the end command right after the dispatch command. But
  more complex dialog may use the end command after a validation loop.


  3.3.6.  A complete example



       #!/usr/bin/shellmod
       . /usr/lib/linuxconf/lib/shellmod-lib.sh
       main(){
               echo DIALOG
               echo newf_str name \"User name\"
               while true
               do
                       echo edit \"User query\" \"Enter the user name\"
                       dispatch
                       if [ "$CODE" = "cancel" ] ; then
                               break
                       elif [ "$name" = "" ] ; then
                               echo error \"Please provide a name\"
                       else
                               echo notice \"Doing something with the user account\"
                               break
                       fi
               done
               echo end
       }
       dispatch







  3.4.  Building a menu

  This is handled by the DIALOG_MENU and new_menuitem commands.


  3.4.1.  echo DIALOG_MENU

  This does not require any argument.


  3.4.2.  echo new_menuitem function prompt title

  This records one menu entry. Each menu entry is associated with one
  script function (that must be defined). The prompt is generally a
  keyword. The title is the rest of the menu entry.


  3.4.3.  echo editmenu \"Menu title\" \"Introduction\"

  This pops the menu. It is followed by a call to dispatch.


  3.4.4.  dispatch

  This is where everything is done for a menu. The dispatch function
  will run until the user select the "quit" button.  The corrresponding
  function is called whenever a menu entry is selected. This is handled
  transparently by the dispatch function.

  Note that the dispatch function also exits if the user select an
  optional buttons (added with the button command).  So it is possible
  to handle a in a loop like the example dialog above.


  3.4.5.  echo end

  This deletes the menu.


  3.4.6.  A complete example



       #!/usr/bin/shellmod
       . /usr/lib/linuxconf/lib/shellmod-lib.sh
       menufunc1(){
               echo notice \"menufunc1 selected\"
       }
       menufunc2(){
               echo notice \"menufunc2 selected\"
       }
       main(){
               echo DIALOG_MENU
               echo new_menuitem menufunc1 Select \"First option\"
               echo new_menuitem menufunc2 \"\" \"Second option\"
               echo editmenu \"Main menu\" \"Pick an option\"
               dispatch
               echo end
       }
       dispatch






  3.5.  Managing a list of records


  3.5.1.  echo DIALOG_LIST

  A DIALOG_LIST is just a variation of a menu. The main difference is
  that the number of entry might be very long. In that case a filter
  dialog will popup so restrict the amount of diaplayed record. You can
  deal with very large list of item.

  DIALOG_LIST does not require any argument.


  3.5.2.  echo newf_head \"Column1 title\" \"Column2 title\" ...

  You can define the heading of the list. This is optional, but looks
  much more nicer.


  3.5.3.  echo new_menuitem \"function args\" \"Column1 value\" \"Col-
  umn2 value\" ...

  It works like DIALOG_MENU, except that we often supply more columns.
  There is another variation as the function is defined with arguments.
  Note that this may be used with DIALOG_MENU as well. We generally
  define one function per menu entry and a single function to process
  each record of the list, using the argument to differentiate the
  processing.

  Note also that you can use a mixed solution within the same
  DIALOG_MENU or DIALOG_LIST: You can use a single function to provide a
  common processing for some record and different function to manage
  exception.


  3.5.4.  echo editmenu \"List title\" \"Introduction\"

  Same as with DIALOG_MENU.


  3.5.5.  dispatch

  This behave like the DIALOG_MENU.


  3.5.6.  echo end

  This delete the list.


  3.5.7.  A complete example

  Here is a realistic example where we display a directory and let the
  user pick one file and do something with it.  We see in this example
  how easy it is to parse the output of the "ls -l" command and present
  the file name, the size and revision date in three formatted column.


       #!/usr/bin/shellmod
       . /usr/lib/linuxconf/lib/shellmod-lib.sh
       fileshow(){
               echo notice \"Processing file $1\"
       }
       main(){
               echo DIALOG_LIST
               echo newf_head \"File name\" Sise \"Revision date\"
               ls -l $1 | \
                       (
                       read total
                       while read perm count user group size month day hour name
                       do
                               echo new_menuitem \"fileshow $name\" $name $size \"$month $day $hour\"
                       done
                       )
               echo editmenu \"Current directory\" \"This show all file in the current directory\"
               dispatch
               echo end
       }
       dispatch





  3.6.  Defining fields

  All commands defining a dialog field start with the prefix newf_.  We
  have used the same name and same parameter order (when possible) as
  the C++ module API.

  The first argument is always the name of the shell variable which will
  receive the value entered by the user. You will often use the
  following construct to edit (correct the current value) of a given
  variable.



               qecho newf_str var "title" "$var"
               .
               qecho edit ...
               dispatch
               if [ "$CODE" = "accept" ] ; then
                       if [ "$var" = "..." ] ;then
                               .
                               .
                       fi
               fi






  3.7.  Command list

  Here is the list of all field definition commands:


  o  ``newf_chk''

  o  ``newf_chkm''

  o  ``newf_combo''

  o  ``newf_dbl''

  o  ``newf_enum''

  o  ``newf_gauge''

  o  ``newf_hexnum''

  o  ``newf_list''

  o  ``newf_num''

  o  ``newf_pass''

  o  ``newf_radio''

  o  ``newf_slider''

  o  ``newf_str''

  o  ``newf_title''




  3.7.1.

  echo newf_chk var \"field title\" \"Initial 0 or 1 value\" \"Suffix
  title\"

  Setup a check box field (on/off or yes/no). The variable var will be
  setup to either 0 or 1. This field has two title. One on the left of
  the check box and one on the right. This is often used like this in
  Linuxconf:

               The current feature [ ] is selected






  3.7.2.  Variation of the newf_chk syntax

  When using newf_chk, you must pass a 0 or 1 as the value. The edit
  variable will receive the result as 0 or 1. This is not so useful as
  often shell script are dealing with different type of boolean value.
  For example, a script dealing with an SQL server may find itself
  dealing with Y and N values. To avoid translating from one system to
  the other, the syntax of the initial value has been expanded.


  o  To make things easy, shellmod will accept as a selected value
     anything in 1,Y and Yes (case insensitive). Unless told
     differently, these values will be translated to 1. Anything else
     will be translated to 0.

  o  By using a special triplet format, one can specify the actual value
     and the dictionary used to interpret it. You specify the value like
     this:



                       value:on_value:off_value






  So if you application is dealing with ON/OFF values, you can specify
  the initial value like this:



                       $var:ON:OFF






  Not only ON and OFF will be accepted to interpret the value, but the
  end result will be sent to the script using one of those word.


  3.7.3.

  echo newf_chkm var \"field title\" \"Initial numeric value\"
  \"value1\" \"value2\" ...

  Setup of multiple selection field using check boxes. The boxes are
  presented horizontally. Here is an example followed with the field it
  produced in text mode:



               echo newf_chkm sel \"Which position\" 1 left center right



  This produces:



               Which position    ( ) left  (o) center ( ) right





  The variable var will take the numerical index of the selected item,
  starting at 0.


  3.7.4.

  echo newf_combo var \"field title\" \"Initial value\"

  Setup a single line + selector field. The user will be able to pick a
  value out of a pick list or enter another by hand. The variable var
  will contain the textual value either entered or selected.

  newf_combo is used with the comboitem command. You setup first the
  combo field and then you pass one by one the possible values using
  comboitem. Note that the values are followed by a descriptive text
  (optional). Here is a code sample:



               echo newf_combo port \"Which port\" ttyS1
               echo comboitem ttyS0 \"COM1 in DOS\"
               echo comboitem ttyS1 \"COM2 in DOS\"
               echo comboitem ttyS2 \"COM3 in DOS\"





  The variable $port will take the value ttyS0, ttyS1, ttyS2 or anything
  the user dares to enter. See ``newf_enum'' and ``newf_list'' for a
  variation of this input field.


  3.7.5.

  echo newf_dbl var \"field title\" \"Initial numeric value\" number-of-
  decimal

  Setup a numerical input field with decimal notation. Works like
  ``newf_num'' except that a decimal point is allowed. The number of
  decimal parameter control the number of digits allowed after the
  decimal point as well as the formatting of the field.


  3.7.6.

  echo newf_enum var \"field title\" \"Initial numeric value\"

  Setup a selector field. The user will be able to pick a value out of a
  pick list. The variable var will contain the index of the selected
  item. The user is limited to picking one item of the list.

  newf_enum is used with the enumitem command. You setup first the enum
  field and then you pass one by one the possible values using enumitem.
  Here is a code sample:

               echo newf_enum no \"Which port\" 1
               echo enumitem ttyS0 \"COM1 in DOS\"
               echo enumitem ttyS1 \"COM2 in DOS\"
               echo enumitem ttyS2 \"COM3 in DOS\"





  The variable $no will take the value 0 1 or 2. See ``newf_combo'' and
  ``newf_list'' for a variation of this input field.


  3.7.7.

  echo newf_gauge ID \"field title\" \"Initial decimal value\" \"Maximum
  value\"

  Setup a visual gauge, generally used to display the completion status
  of a process (loading, installing). The state of the gauge is changed
  by calling this command again. The first call defines the field, the
  next ones update the gauge. This widget is generally used with the
  "show" command so the script never stop in the "edit" state. Here is a
  small example



               echo DIALOG
               qecho newf_gauge ID "Status" 0 10
               qecho show "Status" ""
               i=0
               while [ "$i" != "10" ] ; do
                   i=`expr $i + 1`
                   sleep 1
                   qecho newf_gauge ID "Status" $i 10
                   qecho show "Status" ""
               done






  3.7.8.

  echo newf_hexnum var \"field title\" \"Initial hexa-decimal value\"

  Setup a numerical input field (integer). Works like ``newf_num'' but
  accept digits and hexa-decimal digits.


  3.7.9.

  echo newf_list var \"field title\" \"Initial value\"

  Setup a selector field. The user will be able to pick a value out of a
  pick list only The variable var will contain the textual value
  selected.

  newf_list is used with the listitem command. You setup first the list
  field and then you pass one by one the possible values using listitem.
  Note that the values are followed by a descriptive text (optional).
  Here is a code sample:



          echo newf_list port \"Which port\" ttyS1
          echo listitem ttyS0 \"COM1 in DOS\"
          echo listitem ttyS1 \"COM2 in DOS\"
          echo listitem ttyS2 \"COM3 in DOS\"





  The variable $port will take the value ttyS0, ttyS1 or ttyS2.  See
  ``newf_enum'' and ``newf_combo'' for a variation of this input field.


  3.7.10.

  echo newf_num var \"field title\" \"Initial numeric value\"

  Setup a numerical input field (integer). Works like newf_str but
  accept only digit.


  3.7.11.

  echo newf_pass var \"field title\" \"Initial value\"

  Setup a password field. Works like a newf_str field except the input
  is not echoed (invisible typing).


  3.7.12.

  echo newf_radio var \"field title\" numeric-value instance-value
  \"suffix title\"

  Setup a radio button field. Several radio button fields must be
  defined for each possible selection. All radio buttons sharing the
  same input variable (var above) operate together: Selecting one De-
  select the other. The var variable will get the numeric-value of the
  selected radio button field.

  Related radio buttons may be placed anywhere in a dialog. They do not
  have to be sequential or even on the same page of the notebook dialog


  3.7.13.

  echo newf_slider var \"field title\" \"Initial decimal value\" \"mini-
  mum value\" \"Maximum value\"

  This works like the newf_num, to edit a decimal value. But it is shown
  as a visual slider. The minimum and maximum value represent the left
  and right edge of the slider.



               qecho newf_slider var "Meeting hour" 15 9 16






  3.7.14.

  echo newf_str var \"field title\" \"Initial value\"

  Setup a one line text input.


  3.7.15.

  echo newf_title "Pad title" level "Left title" "Text mode title"

  This is not an input field but a way to organize a large dialog in
  section. The end result is far different in graphic mode than in text
  or HTML mode. In graphic mode, this will create a notebook dialog and
  each newf_title defines one page (one pad) of the notebook.

  The first argument, pad title, is only used in graphic mode.

  The     second argument is a number and represent the notebook level.
  This allows very complex dialogs with notebook within notebook. In
  text and HTML mode, this argument has no effect.


  o  A value of 0 add an horizontal splitter between two fields. The
     "Text mode title" is centered in that splitter.

  o  A value of 1 create the first level of notebook. A value of 2
     create a sub-notebook with the current one.

  The third argument, left title, is used only in text and HTML mode.
  It places a small title on the left of the input fields.

  The last argument, text mode title, appears centered between two input
  fields.


  3.8.  Adding buttons

  You can add optional buttons simply by using the button command. It
  requires to arguments. The first is the button ID which will be passed
  to the script using the CODE variable. The second is the label (title)
  of the button. Here is an example:



               echo DIALOG
               echo newf_str name \"User name\" $name
               echo button Add \"Add a new user\"
               echo edit "title" \"User management\"
               dispatch
               echo end
               if [ "$CODE" = "Add" ] ; then
                       # Adding a new user
               elif [ "$CODE" = "accept" ] ; then
                       # Inspecting a user record
               fi






  3.9.  Set the current input field

  The "setcurfield" opcode sets the keyboard focus on a specific field.
  You must pass the field ID as a single argument. Here is an example:




          qecho DIALOG
          qecho newf_str uid "User id"
          qecho newf_str name "Name"
          qecho newf_str phone "Name"
          qecho setcurfield name
          qecho edit "sample" "The focus is now on name"
          dispatch
          echo end






  4.  Building co-managers

  Co-managers are exciting. They allows one to add functionalities to
  Linuxconf right where it belongs, instead of adding new sub-menus.


  4.1.  Principles

  A co-manager is a component that participate in a dialog. It may add
  fields and validation. The most common case is the user account
  dialog, where several co-managers participate. The most visible one is
  the mailconf module, which insert a complete section to handle email
  aliases. Another is the pppdialin module which add a section to deal
  with PPP parameters.

  A co-manager must provide 4 functions:


  o  Adding fields to the dialog. Here the co-manager will probably add
     a new section and few fields. It is not forced to add anything.

  o  Add validation. The co-manager may do all kind of validation not
     only on its own fields. The admin is not allowed to commit any
     changes to the user account until all co-managers agree.

  o  Save the inputs. The co-manager must save the value of the fields
     it manages. User account co-managers have to preserver information
     on a per user basis.

  o  Delete information associated to the user account/information
     record when it is deleted.

  Note that the co-managers have been created with user accounts in
  mind, but the concept is more general than that. Change "user account"
  above for "record" and you get a more general picture.


  4.2.  Registering the co-manager

  Linuxconf must be notified that a co-manager exists for a given
  dialog.  Dialogs are identified by a small key. For example, the key
  for the user account dialog is "user".

  A shellmod co-manager must provide four functions, using the same
  prefix.  When registering the co-manager, you provide the function
  prefix and the dialog key. This is done with in the register function
  Here is an example:





          # Register as a co-manager in the user account dialog
          echo comanager ufct user





  The function prefix is ufct. One must create four functions according
  to this prefix:


  o  ufct-setupdia

  o  ufct-validate

  o  ufct-save

  o  ufct-deluser



  4.3.  The various functions


  4.3.1.  setupdia

  This function is called when building the dialog. You can use any
  opcode normally used to define a dialog. You do not have to define the
  dialog yourself (echo DIALOG) as it is implicitly defined.

  While you can simply add fields in the dialog, one will generally
  define a new dialog section. Unless you do that, your new field will
  be appended in the current section, which can be any section.

  You define a section with the newf_title opcode



               qecho newf_title "Mailing lists" 1 - "Mailing lists"






  4.3.2.  validate

  This function receives all field value (entered by the user). Each
  field correspond to a shell variable, so you can test their value
  directly. You must use the "retcode" opcode to tell if the validation
  was successful. Here is an example



               echo retcode 0





  Any value different from 0 is taken as a validation failure. Any error
  must be reported with the "error" opcode. You may also use the
  "setcurfield" to jump to a specific field.



          if [ "$a1" = "valid" ] ; then
                  echo retcode 0
          else
                  echo setcurfield a1
                  echo retcode -1
                  echo error \"sample.sh: Invalid value, enter the word valid\"
          fi







  4.3.3.  save

  All field's value are returned to your script as shell variable.  The
  save function must do various things with the information. It can
  either save it in a file, or perform some actions (send an email to an
  administrator about the required changes for example).

  Other shell variable also contain information related to this dialog
  (see dialog context below).


  4.3.4.  deluser

  This function name is a bit miss-leading. It means that the record
  must be deleted (in general, a user account). You must use the
  information from the dialog context (see below) to perform the
  required deletion.


  4.4.  Dialog context

  A co-manager is handling one part of a larger dialog. To properly
  manage its part, the co-manager must know other information about the
  current dialog. For example, to enhance the user account dialog, one
  must know the user account (user id) being edited as well as the
  domain (is it a virtual email domain user account ?).

  This extra infomation is passed as shell variable, so readily usable.
  The available information is dialog dependent. For user account co-
  managers, the following variables are provided:


     domain
        The virtual email domain is passed. For the main domain, this
        variable is set to /.

     is_new
        This is a flag telling you if this is a new account (name is
        empty) or not.

     name
        This is the user id.

  One way to learn the information available to your script is by
  running it in debug mode under Linuxconf. You enable this mode from
  Linuxconf user interface, in control file and system/shell module
  management/shellmod configuration.





  5.  Script process life

  Shellmod and Linuxconf will start the script whenever it is needed.
  Used as a Linuxconf module, the script is not started at Linuxconf
  startup but only when one of its menu or co-manager entries are
  selected.

  The script is start and proceed to its dispatch function, where it
  waits for request. Some request triggers the execution of one of the
  script's function. When the function done, the original dispatch
  function resume and continue to wait. Note that dispatch may be used
  recursively.

  Once started, the script sits there waiting for request until
  Linuxconf end. As such it can be seen as a small server sharing
  information collected while performing various request.

  When used as a stand-alone utility, the script will end as soon as its
  main function exits.


  6.  Module builder

  A shell module builder is available to get you started faster.  You
  access this builder from shellmod main menu or with the shellmod
  utility:



               shellmod --build





  A single dialog appears. You fill it and this create the framework for
  a new shell module. Here are the various fields


  6.1.  Path of the module

  You simply enter the full or relative path of the new shell script you
  want to create. The builder is not able to edit an existing module.


  6.2.  Insert in menu

  You must supply the menu id of the menu in which you want to insert
  the module (in Linuxconf). A module may insert in several Linuxconf
  menus, but the builder only supports one. Modifying the code later is
  easy.

  This field has a help list to pick the proper ID.


  6.3.  Menu title

  Just enter the text of the menu entry.


  6.4.  This is a user account co-manager

  By selecting this check-box, you instruct the builder to generate the
  proper co-manager function templates (setupdia,save,deluser,validate).


  Note that a module may be a co-manager and insert in menus as well.


  6.5.  Main menu entries

  You simply enter the various menu entries. For each one, the builder
  will generate a shell function template menufunc1, menufunc2. It will
  also generate the menu code in the main function. You will have to
  provide the code for the various menufunc functions.

  } Main menu entries























































