
/* system.q: Q's system module
   $Id: system.q,v 1.8 2008/02/23 10:12:59 agraef Exp $ */

/* This file is part of the Q programming system.

   The Q programming system 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, or (at your option) any
   later version.

   The Q programming system 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 this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* NOTE: Not all operations are implemented on all systems. The UNIX-specific
   operations are marked with `(U)'. Only a portable subset of the UNIX system
   interface is provided, which encompasses the most essential operations
   found on many recent UNIX (and other POSIX) systems, as described by the
   ANSI C and POSIX standards, as well as the Single UNIX Specification
   (SUS). These operations are also available on Linux and OSX systems.
   Please also note that at this time some of the low-level operations (most
   notably, ioctl) are not yet implemented. */

/****************************************************************************/

/* Manifest constants. These vary from system to system; only the most common
   values are provided as global variables here. Flag values can be combined
   using bitwise logical operations as usual. Flag values which are
   unavailable on the host system will be set to zero, other undefined values
   to -1 (or () in some cases). Thus undefined values will generally have no
   effect or cause the corresponding operations to fail. */

public var const
  // _spawn modes
  P_WAIT, P_NOWAIT, P_OVERLAY, P_DETACH,

  // file access modes
  O_RDONLY, O_WRONLY, O_RDWR,
  // access mode bitmask
  O_ACCMODE,

  // file descriptor flags
  FD_CLOEXEC,

  // status flags
  O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_NDELAY, O_NOCTTY,
  O_BINARY,

  // file type bitmask
  S_IFMT,
  // file types
  S_IFBLK, S_IFCHR, S_IFIFO, S_IFREG, S_IFDIR, S_IFLNK, S_IFSOCK,

  // permission flags
  S_ISUID, S_ISGID, S_ISVTX,
  S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR,
  S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP,
  S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH,

  // fcntl command codes
  F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK, F_SETLKW,

  // lock types
  F_RDLCK, F_WRLCK, F_UNLCK,

  // modes for access operation
  F_OK, R_OK, W_OK, X_OK,

  // wait options
  WNOHANG, WUNTRACED,

  // time units used by the clock and times routines
  CLOCKS_PER_SEC, CLK_TCK,

  /* termios constants ******************************************************/

  // tcsetattr options
  TCSANOW, TCSADRAIN, TCSAFLUSH,

  // tcflush options
  TCIFLUSH, TCIOFLUSH, TCOFLUSH,

  // tcflow options
  TCIOFF, TCION, TCOOFF, TCOON,

  // input modes
  BRKINT, ICRNL, IGNBRK, IGNCR, IGNPAR, INLCR, INPCK, ISTRIP, IUCLC,
  IXANY, IXOFF, IXON, PARMRK,

  // output modes
  OPOST, OLCUC, ONLCR, OCRNL, ONOCR, ONLRET, OFILL,
  NLDLY, NL0, NL1,
  CRDLY, CR0, CR1, CR2, CR3,
  TABDLY, TAB0, TAB1, TAB2, TAB3,
  BSDLY, BS0, BS1,
  VTDLY, VT0, VT1,
  FFDLY, FF0, FF1,

  // control modes
  CSIZE, CS5, CS6, CS7, CS8,
  CSTOPB, CREAD, PARENB, PARODD, HUPCL, CLOCAL,

  // local modes
  ECHO, ECHOE, ECHOK, ECHONL, ICANON, IEXTEN, ISIG,
  NOFLSH, TOSTOP, XCASE,

  // baud rates
  B0, B50, B75, B110, B134, B150, B200, B300, B600,
  B1200, B1800, B2400, B4800, B9600, B19200, B38400,

  // symbolic control character indices
  VEOF, VEOL, VERASE, VINTR, VKILL, VMIN,
  VQUIT, VSTART, VSTOP, VSUSP, VTIME,

  /* socket-related constants ***********************************************/

  // address families
  AF_LOCAL, AF_UNIX, AF_FILE, AF_INET, AF_INET6,

  // socket types
  SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET,

  // shutdown options (HOW argument)
  SHUT_RD, SHUT_WR, SHUT_RDWR,

  // send/recv flag values
  MSG_EOR, MSG_OOB, MSG_PEEK, MSG_WAITALL,

  // socket option level (getsockopt/setsockopt)
  SOL_SOCKET,

  // socket level options
  SO_ACCEPTCONN, SO_BROADCAST, SO_DEBUG, SO_DONTROUTE,
  SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE,
  SO_RCVBUF, SO_RCVLOWAT, SO_RCVTIMEO, SO_REUSEADDR,
  SO_SNDBUF, SO_SNDLOWAT, SO_SNDTIMEO, SO_TYPE,

  // important IP protocol numbers
  IPPROTO_IP, IPPROTO_ICMP, IPPROTO_TCP, IPPROTO_UDP,

  /* highres timers *********************************************************/

  CLOCK_REALTIME, CLOCK_MONOTONIC,
  CLOCK_PROCESS_CPUTIME, CLOCK_THREAD_CPUTIME,

  /* locale-related constants ***********************************************/

  // locale categories
  LC_ALL, LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME,

  // nl_langinfo items
  CODESET,
     
  D_T_FMT, D_FMT, T_FMT, T_FMT_AMPM,
     
  AM_STR, PM_STR,
     
  DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7,
     
  ABDAY_1, ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7,
     
  MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11,
  MON_12,
     
  ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9,
  ABMON_10, ABMON_11, ABMON_12,
     
  ERA, ERA_D_T_FMT, ERA_D_FMT, ERA_T_FMT,
     
  ALT_DIGITS, RADIXCHAR, THOUSEP,
     
  YESEXPR, NOEXPR,
     
  CRNCYSTR;

// retrieve system parameters

private extern sys_vars;
def (P_WAIT, P_NOWAIT, P_OVERLAY, P_DETACH,

     O_RDONLY, O_WRONLY, O_RDWR, O_ACCMODE,
     FD_CLOEXEC,
     O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_NDELAY, O_NOCTTY,
     O_BINARY,

     S_IFMT, S_IFBLK, S_IFCHR, S_IFIFO, S_IFREG, S_IFDIR, S_IFLNK, S_IFSOCK,

     F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK, F_SETLKW,
     F_RDLCK, F_WRLCK, F_UNLCK,
     F_OK, R_OK, W_OK, X_OK,

     WNOHANG, WUNTRACED,

     CLOCKS_PER_SEC, CLK_TCK,

     TCSANOW, TCSADRAIN, TCSAFLUSH,

     TCIFLUSH, TCIOFLUSH, TCOFLUSH,

     TCIOFF, TCION, TCOOFF, TCOON,

     BRKINT, ICRNL, IGNBRK, IGNCR, IGNPAR, INLCR, INPCK, ISTRIP, IUCLC,
     IXANY, IXOFF, IXON, PARMRK,

     OPOST, OLCUC, ONLCR, OCRNL, ONOCR, ONLRET, OFILL,
     NLDLY, NL0, NL1,
     CRDLY, CR0, CR1, CR2, CR3,
     TABDLY, TAB0, TAB1, TAB2, TAB3,
     BSDLY, BS0, BS1,
     VTDLY, VT0, VT1,
     FFDLY, FF0, FF1,

     CSIZE, CS5, CS6, CS7, CS8,
     CSTOPB, CREAD, PARENB, PARODD, HUPCL, CLOCAL,

     ECHO, ECHOE, ECHOK, ECHONL, ICANON, IEXTEN, ISIG,
     NOFLSH, TOSTOP, XCASE,

     B0, B50, B75, B110, B134, B150, B200, B300, B600,
     B1200, B1800, B2400, B4800, B9600, B19200, B38400,

     VEOF, VEOL, VERASE, VINTR, VKILL, VMIN,
     VQUIT, VSTART, VSTOP, VSUSP, VTIME,

     AF_LOCAL, AF_INET, AF_INET6,

     SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET,

     SHUT_RD, SHUT_WR, SHUT_RDWR,

     MSG_EOR, MSG_OOB, MSG_PEEK, MSG_WAITALL,

     SOL_SOCKET,

     SO_ACCEPTCONN, SO_BROADCAST, SO_DEBUG, SO_DONTROUTE,
     SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE,
     SO_RCVBUF, SO_RCVLOWAT, SO_RCVTIMEO, SO_REUSEADDR,
     SO_SNDBUF, SO_SNDLOWAT, SO_SNDTIMEO, SO_TYPE,

     IPPROTO_IP, IPPROTO_ICMP, IPPROTO_TCP, IPPROTO_UDP,

     CLOCK_REALTIME, CLOCK_MONOTONIC,
     CLOCK_PROCESS_CPUTIME, CLOCK_THREAD_CPUTIME,

     LC_ALL, LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC,
     LC_TIME,

     CODESET,
     D_T_FMT, D_FMT, T_FMT, T_FMT_AMPM,
     AM_STR, PM_STR,
     DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7,
     ABDAY_1, ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7,
     MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10,
     MON_11, MON_12,
     ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8,
     ABMON_9, ABMON_10, ABMON_11, ABMON_12,
     ERA, ERA_D_T_FMT, ERA_D_FMT, ERA_T_FMT,
     ALT_DIGITS, RADIXCHAR, THOUSEP,
     YESEXPR, NOEXPR,
     CRNCYSTR

    ) = sys_vars;

def AF_UNIX = AF_LOCAL, AF_FILE = AF_LOCAL;

// these values should be ubiquitous

def S_ISUID = 04000, S_ISGID = 02000, S_ISVTX = 01000,
  S_IRWXU = 00700, S_IRUSR = 00400, S_IWUSR = 00200, S_IXUSR = 00100,
  S_IRWXG = 00070, S_IRGRP = 00040, S_IWGRP = 00020, S_IXGRP = 00010,
  S_IRWXO = 00007, S_IROTH = 00004, S_IWOTH = 00002, S_IXOTH = 00001;

/****************************************************************************/

/* File and directory functions. These functions provide the same
   functionality as their C counterparts. */

public extern rename OLD NEW;		// rename a file
public extern unlink NAME;		// delete a file
public extern truncate NAME LEN;	// truncate a file (U)
public extern getcwd, chdir NAME;	// get/set the working directory
public extern mkdir NAME MODE;		// create a new directory
public extern rmdir NAME;		// remove a directory
public extern readdir NAME;		// list the files in a directory
public extern link OLD NEW;		// create a hard link (U)
public extern symlink OLD NEW;		// create a symbolic link (U)
public extern readlink NAME;		// read a symbolic link
public extern mkfifo NAME MODE;		// create a named pipe (U)

public extern access NAME MODE;		// test access mode
public extern chmod NAME MODE;		// set the file mode
public extern chown NAME UID GID;	// set file ownership (U)
public extern lchown NAME UID GID;	// set link ownership (U)
public extern utime NAME TIMES;		// set the file times
public extern umask N;			// set/get file creation mask
public extern stat NAME, lstat NAME;	// file and link information

/* Access routines for the components of the tuples returned by the stat/lstat
   functions. */

public st_dev STAT, st_ino STAT, st_mode STAT, st_nlink STAT, st_uid STAT,
  st_gid STAT, st_rdev STAT, st_size STAT, st_atime STAT, st_mtime STAT,
  st_ctime STAT;

st_dev STAT				= STAT!0;
st_ino STAT				= STAT!1;
st_mode STAT				= STAT!2;
st_nlink STAT				= STAT!3;
st_uid STAT				= STAT!4;
st_gid STAT				= STAT!5;
st_rdev STAT				= STAT!6;
st_size STAT				= STAT!7;
st_atime STAT				= STAT!8;
st_mtime STAT				= STAT!9;
st_ctime STAT				= STAT!10;

/****************************************************************************/

/* Process control. Most of these operations are UNIX-specific. */

public extern system CMD;		// execute command using the shell

public extern fork;			// fork a child process (U)
public extern exec PROG ARGS;		// execute program
public extern spawn PROG ARGS;		// execute program in child process
public extern _spawn MODE PROG ARGS;	// execute child with options
public extern nice INC;			// change nice value (U)
public extern pause;			// pause until a signal occurs (U)
public extern raise SIG;		// raise signal in current process
public extern kill SIG PID;		// send signal to given process (U)
public extern getpid;			// current process id
public extern getppid;			// parent's process id (U)
public extern wait;			// wait for any child process (U)
public extern waitpid PID OPTIONS;	// wait for given child process (U)

/* Routines to interpret the exit codes returned by the spawn/system/wait/
   waitpid functions (U). */

public extern isactive STATUS;
// process is active
public extern isexited STATUS, exitstatus STATUS;
// process has exited normally, get its exit code
public extern issignaled STATUS, termsig STATUS;
// process was terminated by signal, get the signal number
public extern isstopped STATUS, stopsig STATUS;
// process was stopped by signal, get the signal number

// process environment
public extern getenv NAME, setenv NAME VAL;

/* User/group-related functions (U). */

public extern setuid UID, setgid GID;	// set user/group id of process
public extern seteuid UID, setegid GID;	// set effective user/group id
public extern setreuid RUID EUID, setregid RGID EGID;
					// set real and effective ids
public extern getuid, geteuid;		// get real/effective user id
public extern getgid, getegid;		// get real/effective group id
public extern getlogin;			// get real login name

// get/set supplementary group ids of current process
public extern getgroups, setgroups GIDS;

/* Session-related routines (U). */

public extern getpgid PID, setpgid PID PGID;	// get and set process group
public extern getpgrp, setpgrp;			// dito, for calling process
public extern getsid PID;			// get session id of process
public extern setsid;				// create a new session

/****************************************************************************/

/* Low-level I/O. Operations for direct manipulation of files on the file
   descriptor level. These are simple wrappers for the low-level I/O
   operations of the C library. */

/* General operations. */

public extern open NAME FLAGS MODE;	// create a new descriptor
public extern close FD;			// close a descriptor
public extern dup FD, dup2 OLDFD NEWFD;	// duplicate a descriptor
public extern pipe;			// create an unnamed pipe

/* fstat returns the same kind of structure as stat and lstat, see above. */

public extern fstat FD;			// stat descriptor
public extern fchdir FD;		// change directory (U)
public extern fchmod FD MODE;		// change file mode (U)
public extern fchown FD UID GID;	// set file ownership (U)
public extern ftruncate FD LEN;		// truncate a file (U)
public extern fsync FD, fdatasync FD;	// sync the given file (U)

/* Read/write binary data represented as byte strings (see the ByteStr data
   structure above). NOTE: These operations work on standard file objects just
   as well as on descriptors. */

public extern bread FD SIZE;		// read a byte string
public extern bwrite FD DATA;		// write a byte string

/* Position the file pointer. In difference to fseek, this function works on
   file descriptors and returns the new offset. */

public extern lseek FD POS WHENCE;

/* Fcntl operation (U). Note that the ARG parameter depends on the type of
   operation performed. See the manual for details. */

public extern fcntl FD CMD ARG;

/* Select operation. This operation is available on Windows as part of the
   socket interface, but only applies to sockets there. */

/* The input is a tuple (IN,OUT,ERR,TIMEOUT) consisting of three lists of file
   descriptors or file objects to be watched, and an optional integer or
   floating point value specifying a timeout in seconds.  The result is a
   triple indicating the lists of files/descriptors which are now ready to
   perform I/O (which might consist of three empty lists if the timeout was
   exceeded). If no timeout is specified then the function may block
   indefinitely. */

public extern select FILES;

/* Some terminal-related stuff. */

public extern isatty FD;		// is descriptor a terminal?

/* Terminal associated with a file descriptor, and the name of the controlling
   terminal. (U) */

public extern ttyname FD;		// terminal associated with descriptor
public extern ctermid;			// name of controlling terminal

/* Pseudo terminal operations (U). The openpty function returns a pair
   (MASTER, SLAVE) of file descriptors, while forkpty returns a pair (PID,
   MASTER) where PID is 0 in the forked child and the child's process id in
   the parent. */

public extern openpty, forkpty;

/****************************************************************************/

/* Termios interface (U). Terminal attributes are stored in a termios
   structure, represented as a 7-tuple (IFLAG,OFLAG,CFLAG,LFLAG,ISPEED,
   OSPEED,CC). The control character set CC is represented as a list of
   character numbers, indexed by the symbolic constants VEOF etc. See
   termios(3) for further details. */

public extern tcgetattr FD;		// get terminal attributes
public extern tcsetattr FD WHEN ATTR;	// set terminal attributes

public extern tcsendbreak FD DURATION;	// send break
public extern tcdrain FD;		// wait until all output finished
public extern tcflush FD QUEUE;		// flush input or output queue
public extern tcflow FD ACTION;		// control input/output flow

public extern tcgetpgrp FD;		// get terminal process group
public extern tcsetpgrp FD PGID;	// set terminal process group

/* Access components of the termios structure. */

public c_iflag ATTR, c_oflag ATTR, c_cflag ATTR, c_lflag ATTR, 
  c_ispeed ATTR, c_ospeed ATTR, c_cc ATTR;

c_iflag ATTR				= ATTR!0;
c_oflag ATTR				= ATTR!1;
c_cflag ATTR				= ATTR!2;
c_lflag ATTR				= ATTR!3;
c_ispeed ATTR				= ATTR!4;
c_ospeed ATTR				= ATTR!5;
c_cc ATTR				= ATTR!6;

/****************************************************************************/

/* Basic GNU readline interface. While readline doesn't really belong to the
   POSIX interface, it is rather useful and the interpreter uses it anyway, so
   we may as well provide it as a part of the system interface. */

/* The RL_COMPLETION_FUNCTION variable may be set to a custom completion
   function, which returns the list of possible completions for a given
   string. The completion function is invoked with two arguments: the string
   to be completed, and the position index of that string in the current input
   line (the actual text of the input line can be obtained with the
   rl_line_buffer function, see below). The RL_WORD_BREAK_CHARS variable is
   set to a string containing the characters which delimit words. This
   information is used by the cursor movement commands and the completion
   routine to break an input line into separate words. */

public var RL_COMPLETION_FUNCTION;
public var RL_WORD_BREAK_CHARS = " \t\n\"\\'`@$><=;|&{(";

/* Interface functions: readline reads a line with a prompt (providing
   editing, history and completion). The rl_line_buffer function returns the
   text of the current input line, which is useful, e.g., if a completion
   function needs to inspect surrounding context. The add_history routine adds
   a line to the history. The stifle_history sets the maximum size of the
   history and returns the previous size; a negative value indicates an
   unbounded history. The read_history and write_history functions read the
   history from and write it to a file, respectively. */

public extern readline PROMPT, rl_line_buffer;
public extern add_history LINE, stifle_history MAX;
public extern read_history FNAME, write_history FNAME;

/****************************************************************************/

/* System information. */

/* System error codes. */

public extern errno, seterrno N;	// get/set last error code
public extern perror S, strerror N;	// print error message

/* Operating system identification (U). */

public extern uname;			// return OS identification

/* Access components of uname result. */

public un_sysname UNAME, un_nodename UNAME, un_release UNAME,
  un_version UNAME, un_machine UNAME;

un_sysname UNAME			= UNAME!0;
un_nodename UNAME			= UNAME!1;
un_release UNAME			= UNAME!2;
un_version UNAME			= UNAME!3;
un_machine UNAME			= UNAME!4;

/* Hostname. */

public extern gethostname;

/* Various system databases. */

/* Password and group database (U). Password entries are encoded as 7-tuples
   (NAME,PASSWD,UID,GID,GECOS,DIR,SHELL), group entries as 4-tuples
   (NAME,PASSWD,GID,MEMBERS). */

public extern getpwuid UID, getpwnam NAME;	// look up a password entry
public extern getpwent;				// list of all pw entries
public extern getgrgid GID, getgrnam NAME;	// look up group entry
public extern getgrent;				// list of all group entries

/* Access components of password and group structures. */

public pw_name PW, pw_passwd PW, pw_uid PW, pw_gid PW, pw_gecos PW,
  pw_dir PW, pw_shell PW;

pw_name PW				= PW!0;
pw_passwd PW				= PW!1;
pw_uid PW				= PW!2;
pw_gid PW				= PW!3;
pw_gecos PW				= PW!4;
pw_dir PW				= PW!5;
pw_shell PW				= PW!6;

public gr_name GR, gr_passwd GR, gr_gid GR, gr_members GR;

gr_name GR				= GR!0;
gr_passwd GR				= GR!1;
gr_gid GR				= GR!2;
gr_members GR				= GR!3;

/* UNIX password encryption. */

public extern crypt KEY SALT; // (U)

/* The following functions require BSD-style gethostbyname and friends. Only
   the gethostbyname, gethostbyaddr, getprotobyname, getprotobynumber,
   getservbyname and getservbyport operations are available on Windows. The
   meaning of the various items described here is explained under "BSD socket
   interface" below. */

/* Host database. Host entries are of the form (NAME,ALIASES,ADDR_TYPE,
   ADDR_LIST), where NAME denotes the official hostname, ALIASES its
   alternative names, ADDR_TYPE the address family and ADDR_LIST the list of
   addresses. Both hostnames and IP addresses are specified as strings. */

public extern gethostbyname HOST, gethostbyaddr ADDR;
public extern gethostent; // (U)

public h_name HENT, h_aliases HENT, h_addr_type HENT, h_addr_list HENT;

h_name HENT				= HENT!0;
h_aliases HENT				= HENT!1;
h_addr_type HENT			= HENT!2;
h_addr_list HENT			= HENT!3;

/* Protocol database. Protocol entries are of the form (NAME,ALIASES,PROTO)
   denoting official name, aliases and number of the protocol. */

public extern getprotobyname NAME;
public extern getprotobynumber PROTO;
public extern getprotoent; // (U)

public p_name PENT, p_aliases PENT, p_proto PENT;

p_name PENT				= PENT!0;
p_aliases PENT				= PENT!1;
p_proto PENT				= PENT!2;

/* Service database. Service entries are of the form (NAME,ALIASES,PORT,PROTO)
   denoting official name, aliases, port number and protocol number of the
   port. The NAME argument of getservbyname can also be a pair (NAME,PROTO) to
   restrict the search to services for the given protocol (given by its
   name). Likewise, the PORT argument can also be replaced with
   (PORT,PROTO). */

public extern getservbyname NAME;
public extern getservbyport PORT;
public extern getservent; // (U)

public s_name PENT, s_aliases PENT, s_port PENT, s_proto PENT;

s_name PENT				= PENT!0;
s_aliases PENT				= PENT!1;
s_port PENT				= PENT!2;
s_proto PENT				= PENT!3;

/****************************************************************************/

/* BSD socket interface. These functions are available on systems providing a
   BSD-compatible socket layer (BSD, BeOS, Linux, OSX, Windows and most recent
   System V flavours).

   At creation time, a socket is described by the following attributes (see
   socket(2) for more details):

   - Address family (sometimes also referred to as namespace, protocol family
     or domain). The adress families supported by this implementation are
     AF_LOCAL (a.k.a. AF_UNIX a.k.a. AF_FILE), AF_INET and AF_INET6.

   - Communication style (also called the socket type). One distinguishes
     between "connection-based" sockets which are used to establish client/
     server connections, and "connectionless" sockets which allow data to be
     received from and sent to arbitrary addresses. The socket types supported
     by this implementation are SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET,
     SOCK_RAW and SOCK_RDM. Among these, SOCK_STREAM, SOCK_SEQPACKET and
     SOCK_RDM are connection-based. Please note that not all socket types are
     supported for all protocol families.

   - Protocol: For each address a.k.a. protocol family and socket type there
     may be a number of different protocols available. For the AF_LOCAL
     namespace, which refers to the local filesystem, the protocol is always
     0, the default protocol. The available protocols for the internet
     namespaces can be retrieved from the protocol database.

   Before another process can connect to a socket it must also be bound to an
   address. The address format depends on the address family of the socket.
   For the local namespace, the address is simply a filename on the local
   filesystem. For the IPv4 namespace, it is a pair (HOST,PORT) where HOST
   denotes the host name or IP address, specified as a string, and PORT is a
   port number. For the IPv6 namespace, it is a quadrupel (HOST,PORT,FLOWINFO,
   SCOPEID). Host names and known port numbers can be retrieved from the host
   and service databases. */

/* Create a socket, or a pair of connected sockets, for the given address
   family, socket type and protocol. */

public extern socket FAMILY TYPE PROTO;
public extern socketpair FAMILY TYPE PROTO; // (U)

/* Shut down data transmission on a socket. You can stop reading, writing or
   both, depending on whether HOW is SHUT_RD, SHUT_WR or SHUT_RDWR. */

public extern shutdown SOCKET HOW;

/* Close a socket. On most systems this is just identical to close (see
   Low-Level I/O above), but on some systems (in particular, BEOS and Windows)
   socket descriptors are special and you must use this function instead. */

public extern closesocket SOCKET;

/* Bind a socket to an address. */

public extern bind SOCKET ADDR;

/* Start listening for and accept connection requests. These operations are
   used on the server side of a connection-based socket. */

public extern listen SOCKET N;
public extern accept SOCKET;

/* Initiate a connection on a socket. This function can be used on both
   connection-based and connectionless sockets. */

public extern connect SOCKET ADDR;

/* Retrieve information about a socket, and get/set socket options (encoded as
   byte strings). */

public extern getsockname SOCKET;
public extern getpeername SOCKET;
public extern getsockopt SOCKET LEVEL OPT;
public extern setsockopt SOCKET LEVEL OPT DATA;

/* Transmit datagrams on a socket. All data is encoded as byte strings. The
   receive operations return the received data, the send operations the number
   of bytes actually written. For recvfrom/sendto the data is encoded as a
   pair (ADDR,DATA) which includes the source/destination address. */

public extern recv SOCKET FLAGS SIZE, send SOCKET FLAGS DATA;
public extern recvfrom SOCKET FLAGS SIZE, sendto SOCKET FLAGS DATA;

/****************************************************************************/

/* Time functions. Return information about the active timezone and the
   current time, and convert time values to various formats. Also available
   are functions to measure cpu time and high-resolution timers. These
   functions are in close correspondence with the date and time functions of
   the C library, see the manual for details. */

/* Simple time (T) is represented as seconds since the "epoch", broken-down
   time (TM) as a 9-tuple (YEAR,MONTH,DAY,HOUR,MIN,SEC,WDAY,YDAY,ISDST). See
   the description of the tm struct in the ctime(3) manual page for more
   information. */

public extern tzname, timezone, daylight;
public extern ctime T, gmtime T, localtime T;
public extern mktime TM, asctime TM, strftime FORMAT TM;

/* Access components of broken-down time. */

public tm_year TM, tm_month TM, tm_day TM, tm_hour TM, tm_min TM, tm_sec TM,
  tm_wday TM, tm_yday TM, tm_isdst TM;

tm_year TM				= TM!0;
tm_month TM				= TM!1;
tm_day TM				= TM!2;
tm_hour TM				= TM!3;
tm_min TM				= TM!4;
tm_sec TM				= TM!5;
tm_wday TM				= TM!6;
tm_yday TM				= TM!7;
tm_isdst TM				= TM!8;

/* clock and times measure cpu time in different units, given by the constants
   CLOCKS_PER_SEC and CLK_TICK, respectively. The times function returns a
   5-tuple (TOTAL,UTIME,STIME,CHILD_UTIME,CHILD_STIME). See times(2) for
   details. */

public extern clock, times;

/* High-resolution timers (U). This requires the POSIX 1003.1-2001 timer
   extension, otherwise these functions will fail. Note that these operations
   differ from the builtin time and sleep functions in that they use integer
   (unsigned 64 bit) time values specified in nanoseconds. The nanotime
   function returns the current time in nanosecs, the nanores function the
   resolution of the given timer. The nanosleep function sleeps for the
   specified amount of nanoseconds, while the nanosleep_until function sleeps
   until the given (absolute) time arrives. In case of an error condition,
   these functions will set errno accordingly.

   For each of the functions you have to specify an integer-valued timer
   id. In the current implementation, the following timers are supported (the
   corresponding constants are defined at the beginning of this module):

   - CLOCK_REALTIME: The system clock, measured in nanosecs since the epoch.
     This will be the same time as returned by the builtin time function (up
     to rounding issues with the latter).

   - CLOCK_MONOTONIC: Monotonic (non-decreasing) time since some unspecified
     starting point. This clock cannot be reset by the user and is thus to be
     preferred in realtime applications.

   - CLOCK_PROCESS_CPUTIME, CLOCK_THREAD_CPUTIME: Highres per-process and
     per-thread CPU timers. (Normally these are for timing purposes only and
     might be unreliable on SMP systems, see clock_gettime(3) for details.)

   Only CLOCK_REALTIME is guaranteed to exist (on systems which implement the
   highres timers at all, that is). If a given clock is unavailable on the
   host system, the corresponding id will be () (if CLOCK_REALTIME is (), then
   the highres timers are not supported at all).

   Moreover, if CPU timers are available, then the process_cpu_clockid and
   thread_cpu_clockid functions can be used to return the clock id for the
   given process id (0 denotes the current process) and the given thread,
   respectively.

   CAVEAT: While these timers nominally support nanoseconds resolution, the
   actual resolutions depend on your system setup and will typically be much
   coarser (for the system and monotonic clocks, they are usually in the
   milliseconds range on current PCs). Also, be aware that system latencies
   might cause calls to nanosleep and nanosleep_until to wake up late (use
   realtime scheduling priorities to mitigate these effects). */

public extern nanotime ID, nanores ID;
public extern nanosleep ID T, nanosleep_until ID T;
public extern process_cpu_clockid PID, thread_cpu_clockid THREAD;

/****************************************************************************/

/* Internationalization support. These functions give access to the locale and
   internationalization functions provided by the C library on most modern
   operating systems, which let you deal with different character sets and
   language-specific conventions. If you have iconv and gettext on your
   system, interfaces to these functions will be provided as well. */

/* The setlocale function sets the current locale of the program. The CATEGORY
   parameter determines which part of the locale is to be modified, and can be
   any of the LC_XXX constants defined in the manifest constants section at
   the beginning of this module. The LOCALE string must be a valid locale
   value for the given category, or "" to specify that the locale is to be set
   from the corresponding user defaults. LOCALE can also be () if you only
   want to query the current locale. In any case the current locale value for
   the given category is then returned as a string. For a description of the
   different locale categories please refer to the setlocale(3) manpage. */

public extern setlocale CATEGORY LOCALE;

/* The localeconv function returns various numeric formatting information
   about the current locale. The result is returned as a tuple. The following
   localeconv fields are supported (see localeconv(3) for details):

   - DECIMAL_POINT, THOUSANDS_SEP, GROUPING (string): decimal point, thousands
     separator and group sizes for non-monetary quantities

   - INT_CURR_SYMBOL, CURRENCY_SYMBOL (string): the international and the
     local currency symbol

   - MON_DECIMAL_POINT, MON_THOUSANDS_SEP, MON_GROUPING (string): decimal
     point, thousands separator and group sizes for monetary quantities

   - POSITIVE_SIGN, NEGATIVE_SIGN (string): the sign to be printed for
     nonnegative and negative monetary quantities, respectively

   - INT_FRAC_DIGITS, FRAC_DIGITS (integer): the number of fractional digits
     for monetary quantities in international and local formats, respectively

   - P_CS_PRECEDES, N_CS_PRECEDES (integer): flags denoting whether the local
     currency symbol should precede positive/negative monetary quantities

   - P_SEP_BY_SPACE, N_SEP_BY_SPACE (integer): an analogous set of flags
     denoting whether the currency symbol should be separated from the amount
     with a space

   - P_SIGN_POSN, N_SIGN_POSN (integer): where to print the sign for
     positive/negative monetary amounts

   All string values may be empty ("") to indicate an empty or unspecified
   value. Integer values may be -1 to indicate an unspecified value.

   NOTE: You'll rarely have to use this information directly, as the strfmon
   function (see below) allows you to format numbers and monetary values in a
   locale-dependent way. */

public extern localeconv;

/* Access the various fields of the localeconv value: */

public decimal_point LC, thousands_sep LC, grouping LC,
  int_curr_symbol LC, currency_symbol LC,
  mon_decimal_point LC, mon_thousands_sep LC, mon_grouping LC,
  positive_sign LC, negative_sign LC,
  int_frac_digits LC, frac_digits LC,
  p_cs_precedes LC, n_cs_precedes LC,
  p_sep_by_space LC, n_sep_by_space LC,
  p_sign_posn LC, n_sign_posn LC;

decimal_point LC			= LC!0;
thousands_sep LC			= LC!1;
grouping LC				= LC!2;
int_curr_symbol LC			= LC!3;
currency_symbol LC			= LC!4;
mon_decimal_point LC			= LC!5;
mon_thousands_sep LC			= LC!6;
mon_grouping LC				= LC!7;
positive_sign LC			= LC!8;
negative_sign LC			= LC!9;
int_frac_digits LC			= LC!10;
frac_digits LC				= LC!11;
p_cs_precedes LC			= LC!12;
n_cs_precedes LC			= LC!13;
p_sep_by_space LC			= LC!14;
n_sep_by_space LC			= LC!15;
p_sign_posn LC				= LC!16;
n_sign_posn LC				= LC!17;

/* On SUSv2-compatible Unix systems, additional information about the current
   locale is available using the nl_langinfo function. ITEM is one of the
   symbolic constants defined in the manifest constants section at the
   beginning of this module (see nl_langinfo(3) for a description of
   these). The result of nl_langinfo is always a string. */

public extern nl_langinfo ITEM; // (U)

/* The strfmon function provides locale-dependent formatting of numbers and
   monetary values. See strfmon(3) for a description of the syntax of the
   FORMAT string. ARGS is either a singleton value or a tuple of floating
   point values, as required for the given format string. Integers in the ARGS
   parameter are automatically converted to floating point values. */

public extern strfmon FORMAT ARGS;

/* The strcoll function compares two strings in a locale-dependent way; it
   returns <0, 0, >0 iff S1 is, respectively, less than, equal to, or greater
   than S2. The strxfrm function converts the given string into a form which
   can be used for locale-based comparisons; by comparing the transformed
   strings you always get the same results as by checking the result of
   strcoll. */

public extern strcoll S1 S2, strxfrm S;

/* The wcswidth function returns the actual number of columns required to
   print a string, which may be different from the length of the string if the
   string contains non-ASCII unicode characters. If any of the characters in
   the given string is non-printable, -1 is returned. The wcwidth function
   does the same for single characters. */

public extern wcswidth S; // (U)
public wcwidth C; // (U)

wcwidth C:Char				= N where N:Int = wcswidth C;

/* Iconv interface. The IConv type represents conversion state objects for the
   iconv function. Objects of this type are created with iconv_open which
   takes two strings describing the desired target and source encodings as
   arguments, and destroyed with the iconv_close function (this is also done
   automatically when an IConv object is garbage-collected).

   The iconv function does the actual conversion. It takes as arguments the
   current conversion state IC (an IConv object) and the byte string B to be
   converted, and returns the converted byte string. The second argument can
   also be () in which case iconv resets the conversion to the initial state
   and returns the "shift" sequence necessary to return to the initial state,
   if any (this will always be the empty byte string in the case of a
   stateless encoding).

   If anything goes wrong during the conversion, instead of a single byte
   string iconv returns a pair of byte strings (C,D) where C is the
   successfully converted initial part of the sequence and D is the remaining
   data, starting from the position in the source buffer B where the error
   occurred. It is then the responsibility of the application to check the
   errno value in order to determine what exactly went wrong, see iconv(3) for
   details.

   Please note that the supported combinations of source and target encodings
   depend on the system and particular iconv implementation. Using GNU iconv,
   you can obtain the list of all supported encodings with the `iconv --list'
   command. */

public extern type IConv;
public extern iconv_open TO FROM, iconv_close IC, iconv IC B;

/* Gettext interface. These are simple wrappers for the corresponding C
   functions from the GNU gettext library.

   The textdomain function selects the default domain to be used with the
   gettext/ngettext functions. The bindtextdomain function determines the base
   directory where the message files for the given domain are to be
   found. Both functions return the current setting, i.e., the current domain
   for textdomain, and the current directory for the given domain for
   bindtextdomain. To only query the current setting without changing it, use
   () as the DOMAIN argument to textdomain and the DIR argument to
   bindtextdomain.

   The gettext function retrieves a message from a message catalog (determined
   with the textdomain and bindtextdomain functions) and returns the
   translated string. The message to be translated is specified as a string
   MSGID. If no translation can be found then gettext returns MSGID unchanged.

   The other variations of gettext allow you to explicitly specify a domain
   (usually the application name, which defaults to the value set with the
   textdomain function) and a locale category (LC_MESSAGES by default). The
   ngettext functions are similar, but provide a way to translate plural
   forms. See gettext(3) and ngettext(3) for details. */

public extern textdomain DOMAIN, bindtextdomain DOMAIN DIR;
public extern gettext MSGID, dgettext DOMAIN MSGID,
  dcgettext DOMAIN MSGID CATEGORY;
public extern ngettext MSGID1 MSGID2 N, dngettext DOMAIN MSGID1 MSGID2 N,
  dcngettext DOMAIN MSGID1 MSGID2 N CATEGORY;
