/*
 *  processes.h
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef PROCESSES_H
#define PROCESSES_H

/* 
    SLI's basic process management capabilities
*/
#include <cstdlib>

#include "config.h"



#include <cstdio>
#include <sys/types.h>
#include <fstream>
#include <string>
#include <vector>
#include "slimodule.h"
#include "slifunction.h"
#include "name.h"

// A new SLI-Module:
class Processes: public SLIModule
{
  // The following concernes the new module: -----------------------

 public:

  static const std::string systemerror(SLIInterpreter *);  // This will be used to produce systemerror-messages

  static int fd(std::istream *s);
  static int fd(std::ostream *s);
  static int fd(std::ostream &s) {return fd(&s);}
  static int fd(std::istream &s) {return fd(&s);}

  static pid_t children_group; // the declaration of a static variable. It will
  // persist as long as the instantiation of the Processes module lives. Never
  // confuse declaration and definition of a variable, by the way...

  const Name signaldict_name; // The name of the signal dictionary

  // The Names of the signals contained in signal dictionary:
  // These are the signals defined by the POSIX standard
  const Name SIGABRT_name;
  const Name SIGALRM_name;
  const Name SIGFPE_name;
  const Name SIGHUP_name;
  const Name SIGILL_name;
  const Name SIGINT_name;
  const Name SIGKILL_name;
  const Name SIGPIPE_name;
  const Name SIGQUIT_name;
  const Name SIGSEGV_name;
  const Name SIGTERM_name;
  const Name SIGUSR1_name;
  const Name SIGUSR2_name;

  const Name SIGCHLD_name;
  const Name SIGCONT_name;
  const Name SIGSTOP_name;
  const Name SIGTSTP_name;
  const Name SIGTTIN_name;
  const Name SIGTTOU_name;


  const Name sys_errname; // The name of the variable in errordict, in which the name of a system error will be stored
  const Name sys_errno;   // The corresponding error-number

  // The Names of the system's error-numberes contained in errordict
  const Name E2BIG_name;
  const Name EACCES_name;
  const Name EAGAIN_name;
  const Name EBADF_name;
  const Name EBUSY_name;
  const Name ECHILD_name;
  const Name EDEADLK_name;
  const Name EDOM_name;
  const Name EEXIST_name;
  const Name EFAULT_name;
  const Name EFBIG_name;
  const Name EINTR_name;
  const Name EINVAL_name;
  const Name EIO_name;
  const Name EISDIR_name;
  const Name EMFILE_name;
  const Name EMLINK_name;
  const Name ENAMETOOLONG_name;
  const Name ENFILE_name;
  const Name ENODEV_name;
  const Name ENOENT_name;
  const Name ENOEXEC_name;
  const Name ENOLCK_name;
  const Name ENOMEM_name;
  const Name ENOSPC_name;
  const Name ENOSYS_name;
  const Name ENOTDIR_name;
  const Name ENOTEMPTY_name;
  const Name ENOTTY_name;
  const Name ENXIO_name;
  const Name EPERM_name;
  const Name EPIPE_name;
  const Name ERANGE_name;
  const Name EROFS_name;
  const Name ESPIPE_name;
  const Name ESRCH_name;
  const Name EXDEV_name;

  // The constructor and destructor for our module object (-if we need them-):
  Processes(void):
    signaldict_name("signaldict"),
    SIGABRT_name("SIGABRT"),
    SIGALRM_name("SIGALRM"),
    SIGFPE_name ("SIGFPE"),
    SIGHUP_name ("SIGHUP"),
    SIGILL_name ("SIGILL"),
    SIGINT_name ("SIGINT"),
    SIGKILL_name("SIGKILL"),
    SIGPIPE_name("SIGPIPE"),
    SIGQUIT_name("SIGQUIT"),
    SIGSEGV_name("SIGSEGV"),
    SIGTERM_name("SIGTERM"),
    SIGUSR1_name("SIGUSR1"),
    SIGUSR2_name("SIGUSR2"),
    
    SIGCHLD_name("SIGCHLD"),
    SIGCONT_name("SIGCONT"),
    SIGSTOP_name("SIGSTOP"),
    SIGTSTP_name("SIGTSTP"),
    SIGTTIN_name("SIGTTIN"),
    SIGTTOU_name("SIGTTOU"),
    
    
    sys_errname("sys_errname"), // The name of the variable in errordict, in which the name of a system error will be stored
    sys_errno("sys_errno"),   // The corresponding error-number
    
    // The Names of the system's error-numberes contained in errordict
    E2BIG_name("E2BIG"),
    EACCES_name("EACCES"),
    EAGAIN_name("EAGAIN"),
    EBADF_name("EBADF"),
    EBUSY_name("EBUSY"),
    ECHILD_name("ECHILD"),
    EDEADLK_name("EDEADLK"),
    EDOM_name("EDOM"),
    EEXIST_name("EEXIST"),
    EFAULT_name("EFAULT"),
    EFBIG_name("EFBIG"),
    EINTR_name("EINTR"),
    EINVAL_name("EINVAL"),
    EIO_name("EIO"),
    EISDIR_name("EISDIR"),
    EMFILE_name("EMFILE"),
    EMLINK_name("EMLINK"),
    ENAMETOOLONG_name("ENAMETOOLONG"),
    ENFILE_name("ENFILE"),
    ENODEV_name("ENODEV"),
    ENOENT_name("ENOENT"),
    ENOEXEC_name("ENOEXEC"),
    ENOLCK_name("ENOLCK"),
    ENOMEM_name("ENOMEM"),
    ENOSPC_name("ENOSPC"),
    ENOSYS_name("ENOSYS"),
    ENOTDIR_name("ENOTDIR"),
    ENOTEMPTY_name("ENOTEMPTY"),
    ENOTTY_name("ENOTTY"),
    ENXIO_name("ENXIO"),
    EPERM_name("EPERM"),
    EPIPE_name("EPIPE"),
    ERANGE_name("ERANGE"),
    EROFS_name("EROFS"),
    ESPIPE_name("ESPIPE"),
    ESRCH_name("ESRCH"),
    EXDEV_name("EXDEV")
  {} //Processes constructor 

  ~Processes(void); // clean up dynmem for static variables...

  // The Module is registered by a call to this Function:
  void init(SLIInterpreter *);

  // This function will return the name of our module:
  const std::string name(void) const;

  // This function -may- return a string of SLI-commands to be executed for initialization
  const std::string commandstring(void) const;


  // ---------------------------------------------------------------



  // The following concernes the new command(s): -------------------

 public:
  // Module contains classes defining new SLI-functions:
  class ForkFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Sysexec_aFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class WaitPIDFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class KillFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class PipeFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Dup2_is_isFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Dup2_os_osFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Dup2_is_osFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Dup2_os_isFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class AvailableFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class GetPIDFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class GetPPIDFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class GetPGRPFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class MkfifoFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class SetNonblockFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class CtermidFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Isatty_isFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };
  class Isatty_osFunction: public SLIFunction
  {
    public:
    void execute(SLIInterpreter *) const; // This is all we need.
  };

  // Module contains -one- instantiation of each new function-class:

public:
  ForkFunction forkfunction;
  Sysexec_aFunction sysexec_afunction;
  WaitPIDFunction waitPIDfunction;
  KillFunction killfunction;
  PipeFunction pipefunction;
  Dup2_is_isFunction dup2_is_isfunction;
  Dup2_os_osFunction dup2_os_osfunction;
  Dup2_is_osFunction dup2_is_osfunction;
  Dup2_os_isFunction dup2_os_isfunction;
  AvailableFunction availablefunction;
  GetPIDFunction getpidfunction;
  GetPPIDFunction getppidfunction;
  GetPGRPFunction getpgrpfunction;
  MkfifoFunction mkfifofunction;
  SetNonblockFunction setnonblockfunction;
  CtermidFunction ctermidfunction;
  Isatty_osFunction isatty_osfunction;
  Isatty_isFunction isatty_isfunction;
};


// Description of new SLI-commands:

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: fork - create a child process of SLI

Synopsis: fork -> PID

Description: Thin wrapper to the fork() system function

Parameters: In : -none-
            Out: PID(integer) : 0 (for the child)
                                the child's process ID (for the parent)

Examples: 1. fork
             (Well, just kidding...)

          2. fork 0 eq {(I'm the child!) = quit} {(I'm the parent!) =} ifelse
             Try this several times. You will notice the child message to appear
             before or after the parent message "by chance". (Even after the
             parent's SLI-prompt...)

Bugs: -

Author: R Kupper

FirstVersion: Mar 17 1999

Remarks: A full parallel process of SLI is forked.
         Parent and child will execute in parallel. There is no way to know which
         will start being executed first.
         Child inherits all open files, including stdin and stdout, from parent!
         Thus, calling fork interactively from the SLI-prompt will result in
         command-line-confusion if both processes end up without quitting.
         If fork() cannot be executed, an error is raised.

         SLI-function spoon (processes.sli) is a more convenient wrapper
          to fork!

SeeAlso: spoon, sysexec, getPID, getPPID, getPGRP, wait, waitPID
*/
   
//-----------------------------------------------------------------------------
/* Now Documented with sysexec!

Name: sysexec_a - execute a UNIX command

Synopsis: CommandArray  sysexec -> -

Description: Transfer control to a UNIX-Command.

Parameters:  In : CommandArray (array of strings):
                    An array containing the command to execute. The first element
                    is interpreted as the command, the remaining elements as it's
                    parameters.

             Out: -whatever will be will be-

Examples: -see command sysexec-

Bugs: -see command sysexec-

Author: R Kupper

FirstVersion: Mar 1999

Remarks: There is a SLI-wrapper called "sysexec" to this function.
         -see command sysexec-

SeeAlso: sysexec, fork, spoon

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: waitPID - wait or check for a child process to terminate

Synopsis: PIDin NoHangFlag waitPID -> Status NormalExitFlag PIDout
                                   -> 0

Description: The waitPID function suspends execution of the calling process
              until status information for the given child is available,
              or until delivery of a signal whose action is either to
              execute a signal-catching function or to terminate the
              process. If status information is available prior to the call
              to waitPID, it returns immediately.
				 
              The waitPID function returns the process ID of the child for
              which status is being reported.
              Zero is returned immediately, if the NoHangFlag is set
              and no status is available.

	      Alternatives: Function waitPID_i_b (undocumented) 
	      -> behaviour and synopsis are the same.

Parameters: In : PIDin(integer):      -1: Wait for any child process.
                                positive: Wait for the specific child whose
                                          process ID is equal to PIDin.
                           (           0: -not supported-) 
                           (less than -1: -not supported-) 
                              
                 NoHangFlag(boolean):
                  If true, causes waitPID function not to suspend execution
                  of the calling process if status is not immediately
                  available for any of the child processes specified by
                  PIDin. In this case, zero is returned as only result.
               
            Out: PIDout(integer):
                   The process ID of the child for which status is being
                   reported.

                 NormalExitFlag(boolean):
                   True, if status is returned for a child that terminated
                   normally, i.e. by a call to exit() or by returning from
                   main(). In that case, the exit code is reported in the Status
                   argument (see below). 
                   False, if status is returned for a child that terminated due
                   to a signal that was not caught. In that case, the number of
                   that signal is reported in the Status argument (see below).
	    
                 Status(integer):
                   If NormalExitFlag is true, this reports the child's exit code, 
                   i.e. the low-order eight bits of the status argument that the
                   child passed to exit(), or the value the child process
                   returned from main().
                   If NormalExitFlag is false, this reports the number of the
                   signal that caused the termination of the child process. Look
                   up this number in signaldict, to know what it means.
                
Examples:1. {(sleep 3) sysexec} spoon false waitPID
         2. {(ls) sysexec} spoon false waitPID
            Note the parent process' SLI-Prompt appearing AFTER execution of the
            command finished.
            This is different to the call "{(ls) sysexec} spoon" only.
         3. 23 false waitPID

Bugs: -

Author: R Kupper

FirstVersion: Apr 13 1999

Remarks: The features normally used only by the UNIX-shell-program
          (such as the WUNTRACED-option) are currently not supported,
          although values <=0 can be passed through PIDin.
         See any documentation of POSIX-function waitpid().
         Discription text is mainly taken from
          Donald A. Lewine, "POSIX programmer's guide", O'Reilly&Associates,Inc.

SeeAlso: wait, spoon, signaldict, getPGRP

*/ 

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: kill - send a signal to another process

Synopsis: PID  SIGNAL kill -> -
          PID /SIGNAL kill -> -
          
Description: The "kill" function sends a signal to a process or a group
              of processes specified by "PID". If the signal is zero,
              error checking is performed but no signal is actually sent.
              This can be used to check for a valid PID.
             SIGNAL may be given either as an integer value or as the
              literal name of the signal, as found in "signaldict".

	      Alternative: Functions kill_i_i for integer (SIGNAL), 
	      kill_i_l for literal (SIGNAL) (both undocumented) 
	      -> behaviour and synopsis are the same.

Parameters: In : PID(integer):
                   The ID of the process that shall be signalled.
                   If "PID" is greater than zero, "SIGNAL" is sent to the
                    process whose ID is "PID".
                   (If "PID" is negative, "SIGNAL" is sent to all processes
                    whose process group ID is equal to the absolute value
                    of "PID". - Process groups are usually used by the
                    shell program only.)

                 SIGNAL(integer):
                   The number of the signal to be sent.
                   Signal codes are machine-dependent values, so do not
                    rely on any given value! The valid signal codes for 
                    your machine are compiled into the "signaldict"
                    dictionary, where they can be looked up by
                    their literal names.
                   The only value you may rely on is zero:
                    If SIGNAL is zero, error checking is performed
                    but no signal is actually sent.
                    This can be used to check for a valid PID.

                  /SIGNAL(literal):
                   The literal name of the signal to be sent.
                   This name is automatically looked up in "signaldict"
                    and substituted to it's corresponding value prior
                    to a call to wait.  
                                  
            Out: -none-.

Examples: 1. 23 /SIGTERM kill %send TERM signal to Process 23

          2. %This is equivalent to 1. :
             signaldict begin
             23 SIGTERM kill
             end

          3. (xterm) 2 system %star an xterm-process
             /SIGKILL kill    %kill it again

Bugs: -

Author: R Kupper

FirstVersion: Apr 27 1999

Remarks: "kill" can be used to send ANY signal, but it's most oftenly used
          to terminate another process. Hence the name.
         Resolution of literal signal names is done by a trie defined
          in file processes.sli.
         Description taken mainly from "POSIX Programmer's Guide",
          D. Lewine, O'Reilly & Assoc. Inc.


SeeAlso: signaldict, system, sysexec, wait, waitPID, spoon, fork, getPPID, getPGRP

*/ 

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: signaldict - Dictionary containing the machine-dependent signal codes.

Synopsis: signaldict -> signaldict

Description: A SLI dictionary containing the system's valid signal codes.
             "signaldict" is used in combination with the "kill",
              "wait" or "waitPID" commands.
             Signal codes are machine-dependent values, so do not
              rely on any given value! The valid signal codes for 
              your machine are compiled into the "signaldict"
              dictionary, where they can be looked up by
              their literal names.

Examples: 1. signaldict /SIGTERM get %get the value for signal SIGTERM

          2. (xterm) 2 system %start an xterm-prcess
             signaldict begin %open signal dictionary
             SIGKILL kill     %kill process
             end              %close dictionary

          3. %This is equivalent to 2. (see description of "kill"):
             (xterm) 2 system %start an xterm-process
             /SIGKILL kill    %kill it again
             
Bugs: -

Author: R Kupper

FirstVersion: Apr 16 1999

SeeAlso: kill, wait, waitPID, system, sysexec, spoon, fork

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: pipe - Open up a pipe

Synopsis: pipe -> read_end write_end

Description:  The pipe function creates a pipe, placing a filestream
             for the read end and a filestream for the write end of
             the pipe on the stack.
              Data can be written to "write_end" and read from "read_end". 
             A read on "read_end" accesses the data written to "write_end"
             on a first-in-first-out basis.

Parameters: In : -none-

            Out: read_end(ifstream): 
                   A filestream open for reading, connected to the read-
                   end of the newly created pipe.

                 write_end(ofstream): 
                   A filestream open for writing, connected to the write-
                   end of the newly created pipe.

Examples: pipe
          (Hello Pipe) <- std::endl
          pop
          getline =

Diagnostics: If a system-error occurs, a code is stored in "sys_errno"
              (contained in errordict) to identify the error, and
              "sys_errname" is set to the error message. Then a
              "SystemError" is raised.

Bugs: -

Author: R Kupper

FirstVersion: May 02 1999

Remarks:  Description-text taken mainly from "POSIX Programmer's Guide",
         D. Lewine, O'Reilly & Assoc. Inc.

          The O_NONBLOCK and FD_CLOEXEC flags are clear on the 
         file descriptors of both streams.

          Opening a pipe in a single process is next to useless (however,
         it might be used for buffering data). The usual application
         is for inter-process-communication: A pipe is opened, and fork
         is called. The child process inherits both filestreams from
         the parent. The child will then close one of the streams (say:
         the read-end), the parent will close the other (say: the write-
         end). Data may then be transfered from the child to the parent
         process through the pipe.

          If the child is to "sysexec" a UNIX command, it may duplicate
         the pipes's write-end onto its standard "cout" stream using "dup2",
         thus directing any data written to "cout" into the pipe. It then
         calles "sysexec". The parent process is thus enabled to read
         the UNIX-command's standard output from the pipe.

          Pipes are unidirectional communication channels.
         For bidirectional communication, two separate pipes must be opened.
         The "spawn" command provides this functionality.

SeeAlso: dup2, available, spawn

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation
   
Name: available - check if data is available from an istream

Synopsis: istream available -> istream {true|false}

Description: "availabe" gives the answer to one question:
             --Is there at least one character waitng to be read
               from the istream?--
             If "available" returns true, it can be safely assumed that
             reading one character from the given istream is safe,
             i.e. it will NEITHER BLOCK nor yield EOF or an error.

	     Alternative: Functions available_is (undocumented) 
	     -> behaviour and synopsis are the same. 
                
Parameters: In:  istream: The istream to check.
            Out: true or false, indicating if data is waiting on the stream.

Examples: myfifo available { getline } if % read it data is available.

Diagnostics: If a system-error occurs, a code is stored in "sys_errno"
             (contained in errordict) to identify the error, and "sys_errname" is
             set to the error message. Then a "SystemError" is raised.
             The following system errors may be issued, according to the
             POSIX standard (errors in parantheses are not
             expected to occur in this routines' context):

             (EACCES)  Search permission is denied for a
                       directory in a files path prefix.
             (EAGAIN)  The ON_NONBLOCK flag is set for a file
                       descriptor and the process would be
                       delayed in the I/O operation.
              EBADF    Invalid file descriptor. (With the current
                       implementation, this indicates trouble
                       getting a fildescriptor from a stream. If
                       it occurs, ask the author for a proper
                       soultion!)
             (EDEADLK) A fcntl with function F_SETLKW would
                       cause a deadlock.
              EINTR    Function was interrupted by a signal.
             (EINVAL)  Invalid argument.
             (EMFILE   Too many file descriptors are in use by
                       this process.
             (ENOLCK)  No locks available.

Bugs: -

Author: R Kupper

FirstVersion: May 10 1999

Remarks: "available" will be typically used with pipes or fifos.

         There are two possible reasons why "available" may return false:
          1. There are processes writing to the pipe/fifo, but none
             of the is currently writing data to it.
              A subsequent read attempt will block until data becomes
             available. 
          2. There are no processes writing to the pipe (any longer).
              A subsequent read attempt will yield EOF.
         It is NOT possible to tell these possibilities apart! This is
         not a fault of the implementation of this function. It is generally
         impossible to do this. The only way to know is to start a read
         attempt. If it blocks, you know the answer - but you could wait
         forever. Anyway, there normally is no need to distinguish between
         these alternatives: Just NEVER try a read attempt, if "available"
         returned false. Even if temporarily no process was connected to
         the stream, it will return true as soon as the connection is re-
         established and data is waiting.

         "available" just tells you if -one- character may be read safely.
          It is left to the programmer to assure that a given amount of
         data (e.g. upto the next linefeed) may be read.

SeeAlso: pipe, mkfifo, spawn, eof, in_avail

*/ 

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: getPID - Get ID of the current process

Synopsis: getPID -> -

Description: Returns the process ID for the calling process.

Parameters: -

Examples: (I am process #) =only getPID =

Diagnostics: A call to "getPID" should never produce an error.

Bugs: -

Author: R Kupper

FirstVersion: May 26 1999

SeeAlso: getPPID, getPGRP, fork, spoon, waitPID, kill, system, spawn, shpawn

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: getPPID - Get parent ID of the current process

Synopsis: getPPID -> -

Description: Returns the process parent ID for the calling process.

Parameters: -

Examples: (I was called by process #) =only getPPID = 

Bugs: -

Author: S Schrader, taken from getPID

FirstVersion: Nov 11 2005

SeeAlso: getPID, getPGRP, fork, spoon, waitPID, kill, system, spawn, shpawn

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: getPGRP - Get process group ID of the current process

Synopsis: getPGRP -> -

Description: Returns the process group ID for the calling process.

Parameters: -

Examples: (I am member of process group #) =only getPGRP =

Diagnostics: A call to "getPGRP" should never produce an error.

Bugs: -

Author: R Kupper

FirstVersion: Apr 18 2000

SeeAlso: fork, getPID, kill

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: mkfifo - Create a FIFO special file (named pipe)

Synopsis: path mkfifo -> -

Description: The "mkfifo" command creates a new FIFO special file named
             "path". The permission bits are set to "rwx rwx rwx" (full access
             for anyone). Note that these bits may be modified by the process'
             file creation mask. (See remarks below.)

	     Alternative: Functions mkfifo_s (undocumented) 
	     -> behaviour and synopsis are the same. 

Parameters: In: path(string):
                 Path name of the FIFO to create.

Examples: (/home/kupper/my_fifo) mkfifo

Diagnostics: If a system-error occurs, a code is stored in "sys_errno"
             (contained in errordict) to identify the error, and "sys_errname" is
             set to the error message. Then a "SystemError" is raised.
             The following system errors may be issued, according to the
             POSIX standard:

              EACCES  Search permission denied for a directory in a file's path 
                      prefix.
              EEXIST  The named file already exists. 
              ENOENT  A file or directory does not exist.
              ENOSPC  No space left on disk.
              ENOTDIR A component of the specified pathname was not a directory
                      when a directory was expected.
              EROFS   Read-only file system.
              
Bugs: -

Author: R. Kupper

FirstVersion: Aug 13 1999 (Friday 13th!)

Remarks: The FIFO may be used (and has to be opened) like any regular file.

         In special cases, it might be desireable to change the FIFO's file
         permission bits. This is not supported by SLI commands.
         Use UNIX-command "chmod" to change file permissions on the newly
         created file, or use UNIX-command "umask" to set the process' file
         creation mask. (See command "system" for issuing UNIX-commands from
         SLI).

SeeAlso: pipe, mkfifo, ifstream, available, ignore, dup2

*/

//-----------------------------------------------------------------------------
/* BeginDocumentation

Name: setNONBLOCK - Switch between blocking and non-blocking I/O.

Synopsis: ifstream {true|false} setNONBLOCK -> ifstream

Description: "setNONBLOCK" sets or erases the O_NONBLOCK flag on
             an input stream. The O_NONBLOCK flag determines, if
             a read attempt will block when no data is currently
             available from the stream. By default, a newly
             created stream has the O_NONBLOCK-Flag erased,
             meaning that blocking I/O is selected. By erasing
             O_NONBLOCK, a subsequent read attempt on the stream 
             will yield EOF if no data is availabe.

	     Alternatives: Function setNONBLOCK_is_b (undocumented) 
	     -> behaviour and synopsis are the same.

Parameters: In : ifstream: The stream to change the flag on.
            Out: -

Examples: cin    false setNONBLOCK
          myfifo true  setNONBLOCK % set non-blocking I/O for my fifo.

Diagnostics: If a system-error occurs, a code is stored in "sys_errno"
             (contained in errordict) to identify the error, and "sys_errname" is
             set to the error message. Then a "SystemError" is raised.
             The following system errors may be issued, according to the
             POSIX standard (errors in parantheses are not
             expected to occur in this routines' context):

             (EACCES)  Search permission is denied for a
                       directory in a files path prefix.
             (EAGAIN)  The ON_NONBLOCK flag is set for a file
                       descriptor and the process would be
                       delayed in the I/O operation.
              EBADF    Invalid file descriptor. (With the current
                       implementation, this indicates trouble
                       getting a fildescriptor from a stream. If
                       it occurs, ask the author for a proper
                       soultion!)
             (EDEADLK) An fcntl with function F_SETLKW would
                       cause a deadlock.
              EINTR    Function was interrupted by a signal.
             (EINVAL)  Invalid argument.
             (EMFILE   Too many file descriptors are in use by
                       this process.
             (ENOLCK)  No locks available.

Bugs: -

Author: R Kupper

FirstVersion: Oct 20 1999

SeeAlso: available, ignore

*/


/*
BeginDocumentation

Name: ctermid - Return the path to the controlling terminal of the process.

Synopsis: ctermid -> (pathname)

Remarks: This is a wrapper to the POSIX kernel function ctermid().

SeeAlso: isatty
*/

#endif