MyWebUniversity.com Home Page
 



OpenSolaris man pages main menu


Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



NAME
     gliomode,   glrawio,    glnormalio,    glttysignals,
     glabandonline,   glhandlesignal,   glpendingio  -  use
     glgetline() from an external event loop

SYNOPSIS
     cc [ flag... ] file... -ltecla [ library... ]
     #include 

     int gliomode(GetLine *gl, GlIOMode mode);


     int glrawio(GetLine *gl);


     int glnormalio(GetLine *gl);


     int glttysignals(void (*termhandler)(int), void (*susphandler)(int),
          void (*conthandler)(int), void (*sizehandler)(int));


     void glabandonline(GetLine *gl);


     void glhandlesignal(int signo, GetLine *gl, int ngl);


     GlPendingIO glpendingio(GetLine *gl);


DESCRIPTION
     The glgetline(3TECLA) function supports two different  I/O
     modes.  These are selected by calling the gliomode() func-
     tion. The mode argument of gliomode()  specifies  the  new
     I/O mode and must be one of the following.

     GLNORMALMODE    Select the normal  blocking-I/O  mode.  In
                       this  mode  glgetline()  does not return
                       until either an error occurs of  the  user
                       finishes entering a new line.


     GLSERVERMODE    Select non-blocking server  I/O  mode.  In
                       this mode, since non-blocking terminal I/O
                       is used, the entry of each new input  line
                       typically    requires    many   calls   to
                       glgetline() from an external  I/O-driven
                       event loop.





SunOS 5.11           Last change: 1 Jun 2004                    1






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



     Newly created GetLine objects start in normal I/O  mode,  so
     to  switch  to  non-blocking server mode requires an initial
     call to gliomode().

  Server I/O Mode
     In non-blocking server I/O mode, the application is required
     to  have an event loop that calls glgetline() whenever the
     terminal file descriptor  can  perform  the  type  I/O  that
     glgetline() is waiting for. To determine which type of I/O
     glgetline() is waiting  for,  the  application  calls  the
     glpendingio()  function.   The  return value is one of the
     following two enumerated values.

     GLPREAD     glgetline() is waiting to write  a  character
                  to the terminal.


     GLPWRITE    glgetline() is waiting to  read  a  character
                  from the keyboad.



     If the application is using either the select(3C) or poll(2)
     function  to  watch  for I/O on a group of file descriptors,
     then it should call the glpendingio() function before each
     call  to these functions to determine which direction of I/O
     it should tell them to watch for, and configure their  argu-
     ments  accordingly.  In  the  case of the select() function,
     this means using the FDSET() macro to add the terminal file
     descriptor  either  to  the  set  of  file descriptors to be
     watched for readability or the set to be watched for  writa-
     bility.


     As in normal I/O mode, the return value of glgetline()  is
     either a pointer to a completed input line or NUL. However,
     whereas in normal I/O mode a NUL return value always  means
     that an error occurred, in non-blocking server mode, NUL is
     also returned when glgetline() cannot read or write to the
     terminal without blocking. Thus in non-blocking server mode,
     in order to determine when a  NUL  return  value  signifies
     that  an  error occurred or not, it is necessary to call the
     glreturnstatus() function. If this  function  returns  the
     enumerated  value  GLRBLOCKED, glgetline() is waiting for
     I/O and no error has occurred.


     When glgetline() returns NUL and glreturnstatus() indi-
     cates that this is due to blocked terminal I/O, the applica-
     tion should call glgetline() again when the  type  of  I/O
     reported  by  glpendingio()  becomes possible. The prompt,



SunOS 5.11           Last change: 1 Jun 2004                    2






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



     startline and startpos arguments of glgetline() will  be
     ignored  on these calls. If you need to change the prompt of
     the line that is currently being edited, you  can  call  the
     glreplaceprompt(3TECLA)    function   between   calls   to
     glgetline().

  Giving Up The Terminal
     A complication that is unique to non-blocking server mode is
     that  it  requires  that  the  terminal  be left in raw mode
     between calls to glgetline(). If this were not  the  case,
     the  external event loop would not be able to detect indivi-
     dual key-presses, and the basic line editing implemented  by
     the terminal driver would clash with the editing provided by
     glgetline(). When the terminal needs to be used  for  pur-
     poses   other   than   entering   a   new  input  line  with
     glgetline(), it needs to be restored to a usable state. In
     particular, whenever the process is suspended or terminated,
     the terminal must be returned to a normal state. If this  is
     not done, then depending on the characteristics of the shell
     that was used to invoke the program, the user could  end  up
     with  a hung terminal. To this end, the glnormalio() func-
     tion is provided for switching  the  terminal  back  to  the
     state that it was in when raw mode was last established.


     The glnormalio() function first flushes any pending output
     to  the  terminal, then moves the cursor to the start of the
     terminal line which follows  the  end  of  the  incompletely
     entered  input  line. At this point it is safe to suspend or
     terminate the process, and it is safe for the application to
     read and write to the terminal. To resume entry of the input
     line, the application should call the glrawio() function.


     The glnormalio() function starts a  new  line,  redisplays
     the  partially  completed  input line (if any), restores the
     cursor position within  this  line  to  where  it  was  when
     glnormalio()  was  called, then switches back to raw, non-
     blocking terminal mode ready to continue entry of the  input
     line when glgetline() is next called.


     Note that in non-blocking server mode, if  glgetline()  is
     called  after a call to glnormalio(), without an interven-
     ing   call   to   glrawio(),   glgetline()   will   call
     glrawmode()  itself,  and the terminal will remain in this
     mode when glgetline() returns.

  Signal Handling
     In the previous section it was  pointed  out  that  in  non-
     blocking  server  mode,  the  terminal must be restored to a



SunOS 5.11           Last change: 1 Jun 2004                    3






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



     sane  state  whenever  a  signal  is  received  that  either
     suspends or terminates the process. In normal I/O mode, this
     is done for you by glgetline(), but in non-blocking server
     mode,  since  the terminal is left in raw mode between calls
     to glgetline(), this signal handling has to be done by the
     application.  Since  there are many signals that can suspend
     or terminate a process, as well as other  signals  that  are
     important  to  glgetline(),  such  as the SIGWINCH signal,
     which tells it when  the  terminal  size  has  changed,  the
     glttysignals()  function is provided for installing signal
     handlers for all pertinent signals.


     The glttysignals() function uses glgetline()'s  internal
     list  of  signals  to  assign  specified  signal handlers to
     groups of signals. The arguments of  this  function  are  as
     follows.

     termhandler    This is the signal handler that is  used  to
                     trap  signals  that by default terminate any
                     process that  receives  them  (for  example,
                     SIGINT or SIGTERM).


     susphandler    This is the signal handler that is  used  to
                     trap  signals  that  by  default suspend any
                     process that receives  them,  (for  example,
                     SIGTSTP or SIGTOU).


     conthandler    This is the signal handler that is  used  to
                     trap  signals  that  are usually sent when a
                     process resumes after being suspended  (usu-
                     ally  SIGCONT). Beware that there is nothing
                     to stop a user from  sending  one  of  these
                     signals at other times.


     sizehandler    This signal handler is used to trap  signals
                     that  are  sent to processes when their con-
                     trolling terminals are resized by  the  user
                     (for example, SIGWINCH).



     These arguments can all be the  same,  if  so  desired,  and
     SIGIGN  (ignore  this  signal)  or SIGDFL (use the system-
     provided default signal handler) can be specified instead of
     a function where pertinent. In particular, it is rarely use-
     ful to trap SIGCONT, so the conthandler argument will  usu-
     ally be SIGDFL or SIGIGN.



SunOS 5.11           Last change: 1 Jun 2004                    4






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



     The glttysignals() function uses  the  POSIX  sigaction(2)
     function to install these signal handlers, and it is careful
     to use the samask member of  each  sigaction  structure  to
     ensure that only one of these signals is ever delivered at a
     time. This guards against different instances of these  sig-
     nal  handlers  from simultaneously trying to write to common
     global data, such as a  shared  sigsetjmp(3C)  buffer  or  a
     signal-received  flag. The signal handlers installed by this
     function should call the glhandlesignal().


     The signo argument tells this function which  signal  it  is
     being  asked  to respond to, and the gl argument should be a
     pointer to the first element of  an  array  of  ngl  GetLine
     objects.  If your application has only one of these objects,
     pass its pointer as the gl argument and specify ngl as 1.


     Depending on the signal that is being handled, this function
     does different things.

  Process termination signals
     If the signal that was  caught  is  one  of  those  that  by
     default  terminates  any  process  that  receives  it,  then
     glhandlesignal() does the following steps.

         1.   First it blocks the delivery of  all  signals  that
              can  be  blocked (ie. SIGKIL and SIGSTOP cannot be
              blocked).

         2.   Next it calls glnormalio() for each  of  the  ngl
              GetLine objects. Note that this does nothing to any
              of the GetLine objects that are  not  currently  in
              raw mode.

         3.   Next it sets the signal handler of  the  signal  to
              its default, process-termination disposition.

         4.   Next it re-sends the process the  signal  that  was
              caught.

         5.   Finally it unblocks delivery of this signal,  which
              results in the process being terminated.

  Process suspension signals
     If the default disposition of the signal is to  suspend  the
     process, the same steps are executed as for process termina-
     tion signals, except that when the process is later resumed,
     glhandlesignal() continues, and does the following steps.

         1.   It re-blocks delivery of the signal.



SunOS 5.11           Last change: 1 Jun 2004                    5






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



         2.   It reinstates the signal handler of the  signal  to
              the  one that was displaced when its default dispo-
              sition was substituted.

         3.   For any of the GetLine objects  that  were  in  raw
              mode    when    glhandlesignal()    was   called,
              glhandlesignal()  then  calls   glrawio(),   to
              resume entry of the input lines on those terminals.

         4.   Finally, it restores the signal process mask to how
              it was when glhandlesignal() was called.


     Note that the process is suspended or terminated  using  the
     original  signal  that  was  caught,  rather  than using the
     uncatchable SIGSTOP and SIGKIL signals. This is  important,
     because  when  a  process  is  suspended  or terminated, the
     parent of the process may  wish  to  use  the  status  value
     returned  by the wait system call to figure out which signal
     was responsible. In particular, most shells use this  infor-
     mation  to  print  a  corresponding message to the terminal.
     Users would  be  rightly  confused  if  when  their  process
     received  a SIGPIPE signal, the program responded by sending
     itself a SIGKIL signal, and the shell then printed out  the
     provocative statement, "Killed!".

  Interrupting The Event Loop
     If a signal is caught and  handled  when  the  application's
     event loop is waiting in select() or poll(), these functions
     will be aborted with errno set to EINTR. When  this  happens
     the  event  loop  should call glpendingio() before calling
     select()  or  poll()  again.  It  should  then  arrange  for
     select()  or  poll()  to  wait  for  the  type  of  I/O that
     glpendingio() reports. This is necessary because any  sig-
     nal  handler  that  calls glhandlesignal() will frequently
     change the type of I/O that glgetline() is waiting for.


     If a signal arrives between the  statements  that  configure
     the  arguments  of select() or poll() and the calls to these
     functions, the signal will not be seen by  these  functions,
     which will then not be aborted. If these functions are wait-
     ing for keyboard input from the  user  when  the  signal  is
     received,  and  the  signal  handler  arranges to redraw the
     input line to accommodate a terminal resize or  the  resump-
     tion  of  the  process. This redisplay will be delayed until
     the user presses the next key. Apart from puzzling the user,
     this  clearly  is  not a serious problem. However there is a
     way, albeit complicated, to completely avoid this race  con-
     dition. The following steps illustrate this.




SunOS 5.11           Last change: 1 Jun 2004                    6






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



         1.   Block  all  of  the  signals   that   glgetline()
              catches,  by  passing  the  signal  set returned by
              gllistsignals() to sigprocmask(2).

         2.   Call glpendingio() and set up  the  arguments  of
              select() or poll() accordingly.

         3.   Call sigsetjmp(3C) with a non-zero  savemask  argu-
              ment.

         4.   Initially this sigsetjmp()  statement  will  return
              zero, indicating that control is not resuming there
              after a matching call to siglongjmp(3C).

         5.   Replace all of the handlers  of  the  signals  that
              glgetline() is configured to catch, with a signal
              handler that first records the number of the signal
              that  was  caught,  in  a file-scope variable, then
              calls siglongjmp() with a non-zero val argument, to
              return  execution  to  the above sigsetjmp() state-
              ment. Registering these signal  handlers  can  con-
              veniently  be done using the glttysignals() func-
              tion.

         6.   Set the file-scope variable that the  above  signal
              handler uses to record any signal that is caught to
              -1, so that we  can  check  whether  a  signal  was
              caught  by  seeing  if  it  contains a valid signal
              number.

         7.   Now unblock the signals that were blocked  in  step
              1.  Any  signal that was received by the process in
              between step 1 and now will now be  delivered,  and
              trigger our signal handler, as will any signal that
              is received until we block these signals again.

         8.   Now call select() or poll().

         9.   When select returns, again block the  signals  that
              were unblocked in step 7.

              If a signal is arrived any time  during  the  above
              steps,  our  signal  handler  will be triggered and
              cause control to return to the  sigsetjmp()  state-
              ment,  where  this  time,  sigsetjmp()  will return
              non-zero, indicating that a signal was caught. When
              this  happens  we  simply  skip  the above block of
              statements, and continue with the following  state-
              ments,  which are executed regardless of whether or
              not a signal is caught. Note that when  sigsetjmp()
              returns, regardless of why it returned, the process



SunOS 5.11           Last change: 1 Jun 2004                    7






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



              signal mask is returned to how  it  was  when  sig-
              setjmp()  was called. Thus the following statements
              are  always  executed  with  all  of  our   signals
              blocked.

         10.  Reinstate the signal handlers that  were  displaced
              in step 5.

         11.  Check wether a signal was caught, by  checking  the
              file-scope variable that the signal handler records
              signal numbers in.

         12.  If a signal was caught, send  this  signal  to  the
              application  again  and unblock only this signal so
              that it invokes the signal handler which  was  just
              reinstated in step 10.

         13.  Unblock all of the signals  that  were  blocked  in
              step 7.

  Signals Caught By glgetline()
     Since the application is expected to handle signals in  non-
     blocking  server  mode,  glgetline()  does  not attempt to
     duplicate this when it is being called. If one of  the  sig-
     nals  that it is configured to catch is sent to the applica-
     tion while  glgetline()  is  being  called,  glgetline()
     reinstates  the  caller's  signal handlers, then immediately
     before returning, re-sends the signal to the process to  let
     the  application's  signal handler handle it. If the process
     is not terminated  by  this  signal,  glgetline()  returns
     NUL, and a following call to glreturnstatus() returns the
     enumerated value GLRSIGNAL.

  Aborting Line Input
     Often, rather than letting it terminate the process,  appli-
     cations  respond  to  the  SIGINT  user-interrupt  signal by
     aborting the current input line. This can be accomplished in
     non-blocking     server-I/O     mode    by    not    calling
     glhandlesignal() when this signal is caught, but  by  cal-
     ling  instead  the glabandonline() function. This function
     arranges that when glgetline() is next  called,  it  first
     flushes  any  pending  output to the terminal, discardes the
     current input line, outputs a new prompt on the  next  line,
     and  finally starts accepting input of a new input line from
     the user.

  Signal Safe Functions
     Provided   that   certain   rules    are    followed,    the
     glnormalio(),    glrawio(),    glhandlesignal(),   and
     glabandonline() functions can  be  written  to  be  safely
     callable  from  signal  handlers.  Other  functions  in this



SunOS 5.11           Last change: 1 Jun 2004                    8






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)



     library should not be called from signal handlers. For  this
     to  be  true,  all signal handlers that call these functions
     must be registered in such a way that only one  instance  of
     any  one  of  them can be running at one time. The way to do
     this is to use the POSIX sigaction()  function  to  register
     all  signal  handlers,  and when doing this, use the samask
     member of the corresponding sigaction structure to  indicate
     that  all  of  the  signals  whose handlers invoke the above
     functions should be blocked when the current signal is being
     handled. This prevents two signal handlers from operating on
     a GetLine object at the same time.


     To prevent signal handlers from accessing a  GetLine  object
     while  glgetline()  or  any of its associated public func-
     tions are operating on it, all public  functions  associated
     with  glgetline(),  including  glgetline()  itself, tem-
     porarily block the delivery of signals when they are access-
     ing  GetLine objects. Beware that the only signals that they
     block are the signals that glgetline() is  currently  con-
     figured  to  catch,  so  be sure that if you call any of the
     above functions from signal handlers, that the signals  that
     these  handlers  are assigned to are configured to be caught
     by glgetline(). See gltrapsignal(3TECLA).

  Using Timeouts To Poll
     If instead of using select() or poll() to wait for I/O  your
     application  needs only to get out of glgetline() periodi-
     cally to briefly  do  something  else  before  returning  to
     accept      input     from     the     user,     use     the
     glinactivitytimeout(3TECLA)   function   in   non-blocking
     server mode to specify that a callback function that returns
     GLTOCONTINUE should be called  whenever  glgetline()  has
     been  waiting  for  I/O  for more than a specified amount of
     time. When this callback is  triggered,  glgetline()  will
     return  NUL and a following call to glreturnstatus() will
     return GLRBLOCKED.


     The glgetline() function will not return  until  the  user
     has  not  typed  a key for the specified interval, so if the
     interval is long and the user  keeps  typing,  glgetline()
     might  not return for a while. There is no guarantee that it
     will return in the time specified.

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






SunOS 5.11           Last change: 1 Jun 2004                    9






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)




           ATRIBUTE TYPE               ATRIBUTE VALUE       
    
     Interface Stability          Evolving                    
    
     MT-Level                     MT-Safe                     
    


SEE ALSO
     cplcompleteword(3TECLA),           efexpandfile(3TECLA),
     glgetline(3TECLA),                         libtecla(3LIB),
     pcalookupfile(3TECLA), attributes(5), tecla(5)









































SunOS 5.11           Last change: 1 Jun 2004                   10






Interactive Command-line Input Library Functions
                                               gliomode(3TECLA)






















































SunOS 5.11           Last change: 1 Jun 2004                   11






OpenSolaris man pages main menu

Contact us      |       About us      |       Term of use      |       Copyright © 2000-2010 MyWebUniversity.com ™