NETWIB_SYS(3)

NAME
netwib - section sys

HTML DOC
If you have a browser, read netwib-5.39.0-doc_html.tgz which is easier to read than this manpage.

PRESENTATION
This manpage contains a concatenation of includes for section SYS.

MODULE TYPES
/*-------------------------------------------------------------*/
/* the FILE type is necessary to write to a file */
#if defined NETWIB_EXT_FILE
 /* user included stdio.h (which defines FILE type) before
    netwib.h */
 #define NETWIBFILE FILE
#else
 /* [default] user perhaps forgot to include stdio.h before
    netwib.h, but netwib has to work without bothering user */
 #define NETWIBFILE void
#endif
/*-------------------------------------------------------------*/
/* the HANDLE type is used everywhere under Windows */
#if defined NETWIB_EXT_HANDLE
 /* user included windows.h (which defines FILE type) before
    netwib.h */
 #define NETWIBHANDLE HANDLE
#else
 /* [default] user perhaps forgot to include windows.h before
    netwib.h or is under Unix, but netwib has to work without
    bothering user */
 #define NETWIBHANDLE void*
#endif

MODULE TIME
/*-------------------------------------------------------------*/
/***************************************************************
 * A netwib_time contains a time duration (relative time) or a *
 * date (absolute time).                                       *
 * Fields of a netwib_time can be directly used, but when it is*
 * set nsec must be between 0 and 999999999.                   *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct {
  netwib_uint32 sec;  /* seconds */
  netwib_uint32 nsec; /* nanoseconds */
} netwib_time;
typedef const netwib_time netwib_consttime;
/*-------------------------------------------------------------*/
/***************************************************************
 * Every function should be prepared to receive as input :     *
 *  - netwib_time*                                             *
 *  - NETWIB_TIME_ZERO                                         *
 *  - NETWIB_TIME_INFINITE                                     *
 * However, NETWIB_TIME_ZERO and NETWIB_TIME_INFINITE cannot be*
 * returned as output by a function. Those defines exist to    *
 * quickly specify those specific inputs.                      *
 ***************************************************************/
/* Empty time duration or year 1970 */
#define NETWIB_TIME_ZERO ((netwib_time*)1)
/* Infinite time duration or year 2038/2108 */
#define NETWIB_TIME_INFINITE ((netwib_time*)2)
/*-------------------------------------------------------------*/
/* Name : netwib_time_init_time
   Description :
     Initialize a netwib_time from another netwib_time.
     This function is mainly useful to convert
     NETWIB_TIME_ZERO or NETWIB_TIME_INFINITE to a real structure.
   Input parameter(s) :
     ptimein : time to copy
   Input/output parameter(s) :
   Output parameter(s) :
     *ptimeout : netwib_time set
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_init_time(netwib_consttime *ptimein,
                                 netwib_time *ptimeout);
/*-------------------------------------------------------------*/
/* Name : netwib_time_init_fields
   Description :
     Initialize a netwib_time.
   Input parameter(s) :
     sec : number of seconds
     msec : number of milliseconds
     usec : number of microseconds
     nsec : number of nanoseconds
   Input/output parameter(s) :
   Output parameter(s) :
     *ptime : netwib_time set
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_init_fields(netwib_uint32 sec,
                                   netwib_uint32 msec,
                                   netwib_uint32 usec,
                                   netwib_uint32 nsec,
                                   netwib_time *ptime);
#define netwib_time_init_sec(sec,ptime) netwib_time_init_fields(sec,0,0,0,ptime)
#define netwib_time_init_msec(msec,ptime) netwib_time_init_fields(0,msec,0,0,ptime)
#define netwib_time_init_usec(usec,ptime) netwib_time_init_fields(0,0,usec,0,ptime)
#define netwib_time_init_nsec(nsec,ptime) netwib_time_init_fields(0,0,0,nsec,ptime)
/*-------------------------------------------------------------*/
/* Name : netwib_time_decode_xyz
   Description :
     Obtain time values stored in a netwib_time.
       function                 obtained ranges
       netwib_time_decode_sec    [0..2^32]
       netwib_time_decode_msec   [0..2^32]
       netwib_time_decode_usec   [0..2^32]
       netwib_time_decode_nsec   [0..2^32]
       netwib_time_decode_fields [0..2^32], [0-999], [0-999], [0-999]
   Input parameter(s) :
     *ptime : netwib_time
   Input/output parameter(s) :
   Output parameter(s) :
     *psec : seconds
     *pmsec : milliseconds
     *pusec : microseconds
     *pnsec : nanoseconds
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTCONVERTED : too big to be decoded
*/
netwib_err netwib_time_decode_fields(netwib_consttime *ptime,
                                     netwib_uint32 *psec,
                                     netwib_uint32 *pmsec,
                                     netwib_uint32 *pusec,
                                     netwib_uint32 *pnsec);
netwib_err netwib_time_decode_sec(netwib_consttime *ptime,
                                  netwib_uint32 *psec);
netwib_err netwib_time_decode_msec(netwib_consttime *ptime,
                                   netwib_uint32 *pmsec);
netwib_err netwib_time_decode_usec(netwib_consttime *ptime,
                                   netwib_uint32 *pusec);
netwib_err netwib_time_decode_nsec(netwib_consttime *ptime,
                                   netwib_uint32 *pnsec);
/*-------------------------------------------------------------*/
/* Name : netwib_time_plus_time
   Description :
     Initialize a netwib_time by adding two netwib_time.
   Input parameter(s) :
     ptimetoadd : time to add
   Input/output parameter(s) :
     *ptime : netwib_time incremented by ptime
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_plus_time(netwib_time *ptime,
                                 netwib_consttime *ptimetoadd);
netwib_err netwib_time_plus_fields(netwib_time *ptime,
                                   netwib_uint32 sec,
                                   netwib_uint32 msec,
                                   netwib_uint32 usec,
                                   netwib_uint32 nsec);
#define netwib_time_plus_sec(ptime,sec) netwib_time_plus_fields(ptime,sec,0,0,0)
#define netwib_time_plus_msec(ptime,msec) netwib_time_plus_fields(ptime,0,msec,0,0)
#define netwib_time_plus_usec(ptime,usec) netwib_time_plus_fields(ptime,0,0,usec,0)
#define netwib_time_plus_nsec(ptime,nsec) netwib_time_plus_fields(ptime,0,0,0,nsec)
/*-------------------------------------------------------------*/
/* Name : netwib_time_minus_time
   Description :
     Initialize a netwib_time by adding two netwib_time.
   Input parameter(s) :
     ptimetoadd : time to add
   Input/output parameter(s) :
     *ptime : netwib_time incremented by ptime
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_minus_time(netwib_time *ptime,
                                  netwib_consttime *ptimetosub);
netwib_err netwib_time_minus_fields(netwib_time *ptime,
                                    netwib_uint32 sec,
                                    netwib_uint32 msec,
                                    netwib_uint32 usec,
                                    netwib_uint32 nsec);
#define netwib_time_minus_sec(ptime,sec) netwib_time_minus_fields(ptime,sec,0,0,0)
#define netwib_time_minus_msec(ptime,msec) netwib_time_minus_fields(ptime,0,msec,0,0)
#define netwib_time_minus_usec(ptime,usec) netwib_time_minus_fields(ptime,0,0,usec,0)
#define netwib_time_minus_nsec(ptime,nsec) netwib_time_minus_fields(ptime,0,0,0,nsec)
/*-------------------------------------------------------------*/
/* Name : netwib_time_cmp
   Description :
     Compare two netwib_time.
   Input parameter(s) :
     ptime1 : time
     ptime2 : time
   Input/output parameter(s) :
   Output parameter(s) :
     *pcmp :
       - if time1<time2, *pcmp is set to NETWIB_CMP_LT
       - if time1>time2, *pcmp is set to NETWIB_CMP_GT
       - if time1==time2, *pcmp is set to NETWIB_CMP_EQ
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_cmp(netwib_consttime *ptime1,
                           netwib_consttime *ptime2,
                           netwib_cmp *pcmp);
/*-------------------------------------------------------------*/
/* Name : netwib_time_sleep_xyz
   Description :
     Sleep for a time duration.
     This is not a "real time" sleep. This sleep is not precise.
     On some systems, the duration might exceed the wanted time
     by several milliseconds.
   Input parameter(s) :
     *preltime : relative time
     sec : number of seconds to wait
     msec : number of milliseconds to wait
     usec : number of microseconds to wait
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_sleep_time(netwib_consttime *preltime);
netwib_err netwib_time_sleep_fields(netwib_uint32 sec,
                                    netwib_uint32 msec,
                                    netwib_uint32 usec,
                                    netwib_uint32 nsec);
#define netwib_time_sleep_sec(sec) netwib_time_sleep_fields(sec,0,0,0)
#define netwib_time_sleep_msec(msec) netwib_time_sleep_fields(0,msec,0,0)
#define netwib_time_sleep_usec(usec) netwib_time_sleep_fields(0,0,usec,0)
#define netwib_time_sleep_nsec(nsec) netwib_time_sleep_fields(0,0,0,nsec)
/*-------------------------------------------------------------*/
/* Name : netwib_time_wait_time
   Description :
     Wait an absolute time value.
     This is not a "real time" wait. This wait is not precise.
     On some systems, the duration might exceed the wanted time
     by several milliseconds.
   Input parameter(s) :
     *pabstime : absolute time (from 1970)
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_wait_time(netwib_consttime *pabstime);
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_TIME_ENCODETYPE_NOTHING = 1, /* print nothing */
  NETWIB_TIME_ENCODETYPE_BEST,        /* best display of the form :
                                         2d:3h:4m:5s:6ms:7us:8ns*/
  NETWIB_TIME_ENCODETYPE_BEST2,       /* best display of the form :
                                         2 days 3 hours 4 minutes ...*/
  NETWIB_TIME_ENCODETYPE_SEC,         /* "123s" */
  NETWIB_TIME_ENCODETYPE_SEC2,        /* "123 second(s)" */
  NETWIB_TIME_ENCODETYPE_MSEC,        /* "123ms" */
  NETWIB_TIME_ENCODETYPE_MSEC2,       /* "123 millisecond(s)" */
  NETWIB_TIME_ENCODETYPE_USEC,        /* "123us" */
  NETWIB_TIME_ENCODETYPE_USEC2,       /* "123 microsecond(s)" */
  NETWIB_TIME_ENCODETYPE_NSEC,        /* "123ns" */
  NETWIB_TIME_ENCODETYPE_NSEC2        /* "123 nanosecond(s)" */
} netwib_time_encodetype;
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_time
   Description :
     Append a string representing a netwib_time duration (relative
     time). To display an absolute time, use function
     netwib_time_decode_localtime.
   Input parameter(s) :
     *ptime : time to print
     encodetype : netwib_time_encodetype to use
   Input/output parameter(s) :
   Output parameter(s) :
     pbuf : buffer updated
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_time(netwib_consttime *preltime,
                                  netwib_time_encodetype encodetype,
                                  netwib_buf *pbuf);
/*-------------------------------------------------------------*/
typedef struct {
  netwib_uint32 nsec; /* nanoseconds [0-999999999]*/
  netwib_int32 sec; /* seconds [0-59] */
  netwib_int32 min; /* minutes [0-59] */
  netwib_int32 hour; /* hours [0-23] */
  netwib_int32 mday; /* day [1-31] */
  netwib_int32 mon; /* month [1-12] (!= from struct tm) */
  netwib_uint32 year; /* year (start at 0) (!= from struct tm) */
  netwib_uint32 wday; /* day of the week [0(sun)-6(sat)] */
  netwib_uint32 yday; /* day of the year [1-365/366] (!= from struct tm) */
  netwib_int32 zoneoffset; /* offset in seconds between localtime
                              and GMT (for example GMT+1 is
                              +3600). This field is used only by
                              netwib_time_decode_localtime */
} netwib_localtime;
typedef const netwib_localtime netwib_constlocaltime;
/*-------------------------------------------------------------*/
/* Name : netwib_time_init_now
   Description :
     Initialize a netwib_time with the current UTC/GMT time.
     It uses the number of seconds elapsed since 00:00:00 on
     January 1, 1970, Coordinated Universal Time (UTC)
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     *ptime : netwib_time set to the current time (absolute time)
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_init_now(netwib_time *pabstime);
/*-------------------------------------------------------------*/
/* Name : netwib_time_init_localtime
   Description :
     Initialize a netwib_time using localtime fields
   Input parameter(s) :
     *plocaltime : structure containing day. Fields nsec, wday,
                   and yday are ignored. Other fields
                   are normalized before converting.
   Input/output parameter(s) :
   Output parameter(s) :
     *ptime : netwib_time set to the current local time
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_init_localtime(netwib_constlocaltime *plocaltime,
                                      netwib_time *pabstime);
/*-------------------------------------------------------------*/
/* Name : netwib_time_decode_localtime
   Description :
     Initialize a netwib_localtime using time fields
   Input parameter(s) :
     *ptime : structure containing current time (UTC)
   Input/output parameter(s) :
   Output parameter(s) :
     *plocaltime : netwib_localtime set
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_decode_localtime(netwib_consttime *pabstime,
                                        netwib_localtime *plocaltime);
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_LOCALTIME_ENCODETYPE_NOTHING = 1, /* print nothing */
  NETWIB_LOCALTIME_ENCODETYPE_NSEC_ZERO,   /* 000000000-999999999 */
  NETWIB_LOCALTIME_ENCODETYPE_NSEC_SPACE,  /* ________0-999999999 */
  NETWIB_LOCALTIME_ENCODETYPE_SEC_ZERO,    /* 00-59 */
  NETWIB_LOCALTIME_ENCODETYPE_SEC_SPACE,   /* _0-59 */
  NETWIB_LOCALTIME_ENCODETYPE_MIN_ZERO,    /* 00-59 */
  NETWIB_LOCALTIME_ENCODETYPE_MIN_SPACE,   /* _0-59 */
  NETWIB_LOCALTIME_ENCODETYPE_HOUR_ZERO,   /* 00-23 */
  NETWIB_LOCALTIME_ENCODETYPE_HOUR_SPACE,  /* _0-23 */
  NETWIB_LOCALTIME_ENCODETYPE_MDAY_ZERO,   /* 01-31 */
  NETWIB_LOCALTIME_ENCODETYPE_MDAY_SPACE,  /* _1-31 */
  NETWIB_LOCALTIME_ENCODETYPE_MON_ZERO,    /* 01-12 */
  NETWIB_LOCALTIME_ENCODETYPE_MON_SPACE,   /* _1-12 */
  NETWIB_LOCALTIME_ENCODETYPE_MON_SHORT,   /* Jan */
  NETWIB_LOCALTIME_ENCODETYPE_MON_LONG,    /* January */
  NETWIB_LOCALTIME_ENCODETYPE_YEAR_SHORT,  /* 04 */
  NETWIB_LOCALTIME_ENCODETYPE_YEAR_LONG,   /* 2004 */
  NETWIB_LOCALTIME_ENCODETYPE_WDAY_SHORT,  /* Mon */
  NETWIB_LOCALTIME_ENCODETYPE_WDAY_LONG,   /* Monday */
  NETWIB_LOCALTIME_ENCODETYPE_YDAY_ZERO,   /* 001-365 */
  NETWIB_LOCALTIME_ENCODETYPE_YDAY_SPACE,  /* __1-365 */
  NETWIB_LOCALTIME_ENCODETYPE_ZONE_SEC,    /* +3600 */
  NETWIB_LOCALTIME_ENCODETYPE_ZONE_GMT,    /* GMT+1 */
  NETWIB_LOCALTIME_ENCODETYPE_ZONE_HM,     /* +0100 */
} netwib_localtime_encodetype;
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_localtime
   Description :
     Append a string representing a field of a netwib_localtime.
   Input parameter(s) :
     *plocaltime : localtime to print
     encodetype : netwib_localtime_encodetype to use
   Input/output parameter(s) :
   Output parameter(s) :
     pbuf : buffer updated
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_localtime(netwib_constlocaltime *plocaltime,
                                       netwib_localtime_encodetype encodetype,
                                       netwib_buf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_time_iselapsed
   Description :
     Check if an absolute time has elapsed.
   Input parameter(s) :
     *ptime : time
   Input/output parameter(s) :
   Output parameter(s) :
     *pyes : true if elapsed or equal
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_time_iselapsed(netwib_consttime *pabstime,
                                 netwib_bool *pyes);

MODULE RAND
/*-------------------------------------------------------------*/
/* Name : netwib_uint32_init_rand
   Description :
     Generate a random number
   Input parameter(s) :
     min : minimum value
     max : maximum value
   Input/output parameter(s) :
   Output parameter(s) :
     *pnumber : random number generated
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_uint32_init_rand(netwib_uint32 min,
                                   netwib_uint32 max,
                                   netwib_uint32 *pnumber);
#define netwib_uint32_init_rand_all(pnumber) netwib_uint32_init_rand(0,0xFFFFFFFFu,pnumber)
netwib_err netwib_uint64_init_rand(netwib_uint64 min,
                                   netwib_uint64 max,
                                   netwib_uint64 *pnumber);
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_rand
   Description :
     Generate a random buffer
   Input parameter(s) :
     size : wanted buffer size
     min : minimal value
     max : maximal value
   Input/output parameter(s) :
   Output parameter(s) :
     *pbuf : random buffer generated
   Normal return values :
     NETWIB_ERR_OK : ok
   This function sets NETWIB_BUF_FLAGS_SENSITIVE.
*/
netwib_err netwib_buf_append_rand(netwib_uint32 size,
                                  netwib_byte min,
                                  netwib_byte max,
                                  netwib_buf *pbuf);
#define netwib_buf_append_rand_all(size,pbuf) netwib_buf_append_rand(size,0,255,pbuf)

MODULE PATH
/*-------------------------------------------------------------*/
/***************************************************************
 * Under Windows, '/' and '\' are recognized as directory      *
 * separator. However, under Unix, only '/' is valid.          *
 * So, if you want your code to be portable, use '/'.          *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_path_canon
   Description :
     Clean a filename ("//"->"/", "/./"->"/", "/aa/../"->"/", etc.).
   Input parameter(s) :
     pathname : filename (ex : "/tmp/dir/..//./file")
   Input/output parameter(s) :
   Output parameter(s) :
     *pcanonizedpathname : cleaned filename (ex : "/tmp/file")
   Normal return values :
     NETWIB_ERR_OK : ok
   Examples of canonical paths :
     file          dir          dir/file          dir/dir
     /file         /dir         /dir/file         /dir/dir
     ../file       ../dir       ../dir/file       ../dir/dir
     /             .            ..
    Windows using a drive letter :
     c:file        c:dir        c:dir/file        c:dir/dir
     c:/file       c:/dir       c:/dir/file       c:/dir/dir
     c:../file     c:../dir     c:../dir/file     c:../dir/dir
     c:/           c:           c:..
    Windows using a smb or cifs share :
     //server/share/
     //s/sh/file   //s/sh/dir   //s/sh/dir/file   //s/sh/dir/dir
    Note : a Window share is very similar to an absolute path
           with two leading '/'. To ensure they are not mixed,
           you have to ensure an absolute path does not start
           with '//'.
*/
netwib_err netwib_path_canon(netwib_constbuf *ppathname,
                             netwib_buf *pcanonizedpathname);
/*-------------------------------------------------------------*/
/***************************************************************
 * netwib functions :                                          *
 *  - always work with :                                       *
 *     + canonized path                                        *
 *  - generally work with :                                    *
 *     + relative path with leading "./"                       *
 *     + "c:." instead of "c:" (only under Windows)            *
 *     + path with "\" instead of "/" (only under Windows)     *
 *  - might work with :                                        *
 *     + directory name ending with "/" (not under Windows)    *
 *     + path such as "/dir/../dir2/file"                      *
 *                                                             *
 * So, user should canonize paths before using netwib          *
 * functions. However, functions in this module accept         *
 * un-canonized paths and produce canonized paths. So,         *
 * functions in this module are safe for use.                  *
 ***************************************************************/
/*-------------------------------------------------------------*/
/***************************************************************
 * Empty string ("") is not a valid path. If functions of this *
 * module have an empty parameter, error                       *
 * NETWIB_ERR_PAPATHNOTCANON occurs.                           *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_pathtype_init
   Description :
     Obtain type of a path.
   Input parameter(s) :
     *ppathname : pathname to obtain info for (do not need to be canonized).
   Input/output parameter(s) :
   Output parameter(s) :
     *ppathtype : type as a bitfield
   Normal return values :
     NETWIB_ERR_OK : ok
   Examples :
     pathname     absolute  root   unix  windrive  winshare
      file         0=no       0      1      0         0
      /file        1=yes      0      1      0         0
      ../file        0        0      1      0         0
      /              1        1      1      0         0
      .              0        0      1      0         0
      ..             0        0      1      0         0
      c:file         0        0      0      1         0
      c:/file        1        0      0      1         0
      c:../file      0        0      0      1         0
      c:/            1        1      0      1         0
      c:             0        0      0      1         0
      c:..           0        0      0      1         0
      //s/sh/file    1        0      0      0         1
      //s/sh/        1        1      0      0         1
*/
#define NETWIB_PATHTYPE_ABSOLUTE 0x01 /* absolute: path is fully specified */
#define NETWIB_PATHTYPE_ROOT     0x02 /* root: can't go up */
#define NETWIB_PATHTYPE_UNIX     0x04 /* unix (or windows simple path) */
#define NETWIB_PATHTYPE_WINDRIVE 0x08 /* windows drive: c:, d: */
#define NETWIB_PATHTYPE_WINSHARE 0x10 /* windows smb share: //server/share/ */
typedef netwib_uint32 netwib_pathtype;
netwib_err netwib_pathtype_init(netwib_constbuf *ppathname,
                                netwib_pathtype *ppathtype);
/*-------------------------------------------------------------*/
/* Name : netwib_path_decode_xyz
   Description :
     Separate a path.
   Input parameter(s) :
     ppathname : filename (ex : "/tmp/file") (do not need to be canonized)
   Input/output parameter(s) :
     type : type of information to extract
   Output parameter(s) :
     *pout : output buffer (canonized, even if ppathname is not)
   Normal return values :
     NETWIB_ERR_OK : ok
   Examples :
     pathname     begin   core      parent   child
      file        .       file      .        file
      d/f         .       d/f       d        f
      /file       /       /file     /        file
      /d/f        /       /d/f      /d       f
      ../file     .       ../file   ..       file
      ../d/f      .       ../d/f    ../d     f
      /           /       /         Error1   /
      .           .       .         ..       .
      ..          .       ..        ../..    ..
      c:file      c:      file      c:       file
      c:d/f       c:      d/f       c:d      f
      c:/file     c:/     /file     c:/      file
      c:/d/f      c:/     /d/f      c:/d     f
      c:../file   c:      ../file   c:..     file
      c:../d/f    c:      ../d/f    c:../d   f
      c:/         c:/     /         Error1   /
      c:          c:      .         c:..     .
      c:..        c:      ..        c:../..  ..
      //s/t/file  //s/t/  /file     //s/t/   file
      //s/t/d/f   //s/t/  /d/f      //s/t/d  f
      //s/t/      //s/t/  /         Error1   /
   Errors are :
     Error1 : NETWIB_ERR_PAPATHROOTDOTDOT
*/
typedef enum {
  NETWIB_PATH_DECODETYPE_BEGIN = 1, /* root directory or . */
  NETWIB_PATH_DECODETYPE_CORE,      /* path starting at begin */
  NETWIB_PATH_DECODETYPE_PARENT,    /* parent directory */
  NETWIB_PATH_DECODETYPE_CHILD,     /* last item */
  NETWIB_PATH_DECODETYPE_EXTENSION  /* file extension without the dot
                                       (empty if no extension) ; pout is
                                       a netwib_bufext */
  /* note : pathname == begin+core or parent+child */
} netwib_path_decodetype;
netwib_err netwib_path_decode(netwib_constbuf *ppathname,
                              netwib_path_decodetype type,
                              netwib_buf *pout);
#define netwib_path_decode_begin(pathname,pout) netwib_path_decode(pathname,NETWIB_PATH_DECODETYPE_BEGIN,pout)
#define netwib_path_decode_core(pathname,pout) netwib_path_decode(pathname,NETWIB_PATH_DECODETYPE_CORE,pout)
#define netwib_path_decode_parent(pathname,pout) netwib_path_decode(pathname,NETWIB_PATH_DECODETYPE_PARENT,pout)
#define netwib_path_decode_child(pathname,pout) netwib_path_decode(pathname,NETWIB_PATH_DECODETYPE_CHILD,pout)
#define netwib_path_decode_extension(pathname,pout) netwib_path_decode(pathname,NETWIB_PATH_DECODETYPE_EXTENSION,pout)
/*-------------------------------------------------------------*/
/* Name : netwib_path_init_xyz
   Description :
     Initialize a path.
   Input parameter(s) :
     See below (do not need to be canonized)
   Input/output parameter(s) :
     pout : path initialized (canonized, even if input is not)
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
typedef enum {
  NETWIB_PATH_INITTYPE_CONCAT = 1,
  NETWIB_PATH_INITTYPE_JAIL,
  NETWIB_PATH_INITTYPE_ABS,
  NETWIB_PATH_INITTYPE_RELA,
  NETWIB_PATH_INITTYPE_RELB,
} netwib_path_inittype;
/*
   Definitions :
     concat : path from the beginning of dirname1 to pathname2
                 [dirname1]-[pathname2]
                 X-------------------->
              If pathname2 is absolute, an error occurs (except if
              dirname1 is a root).
     jail : same as concat except pathname2 is considered as an
            absolute path inside dirname1. It's a kind of chroot
            or jail with a rootdir of dirname1. Resulting filename
            cannot escape from dirname1.
     abs : absolute path to pathname2 (pathname2 is in a
           file located in dirname1 directory)
              root
                [dirname1]-[pathname2]
              X---------------------->
           If pathname2 is absolute, result is pathname2.
           If dirname1 is not absolute, an error occurs.
     rela : relative path to go to pathname2 from a file
            in dirname1 directory (pathname2 is in a
            file located in dirname1 directory)
               [dirname1]-[pathname2]
                        X----------->
            If pathname2 is relative, result is pathname2.
            If pathname2 is absolute, dirname1 must be absolute.
     relb : relative path to go to pathname2 from a file
            in dirname1 directory (pathname1 and pathname2
            are located in the same directory)
               [dirname1]
               [  pathname2   ]
                        X----->
            If pathname2 is absolute, dirname1 must be absolute.
            If pathname2 is relative, dirname1 must be relative.
   Examples of concat, jail and abs :
     dirname1   pathname2  concat       jail         abs
     d1         d2/f2      d1/d2/f2     d1/d2/f2     Error
     d1         ../d2/f2   d2/f2        Error        Error
     d1         /d2/f2     Error        d1/d2/f2     /d2/f2
     ../d1      d2/f2      ../d1/d2/f2  ../d1/d2/f2  Error
     ../d1      ../d2/f2   ../d2/f2     Error        Error
     ../d1      /d2/f2     Error        ../d1/d2/f2  /d2/f2
     /d1        d2/f2      /d1/d2/f2    /d1/d2/f2    /d1/d2/f2
     /d1        ../d2/f2   /d2/f2       Error        /d2/f2
     /d1        /d2/f2     Error        /d1/d2/f2    /d2/f2
     isroot     /d2/f2     x/d2/f2      x/d2/f2      /d2/f2
   Examples of rela and relb :
     dirname1   pathname2  rela         relb
     d1         d2/f2      d2/f2        ../d2/f2
     d1         ../d2/f2   ../d2/f2     ../../d2/f2
     d1         /d2/f2     Error        Error
     ../d1      d2/f2      d2/f2        Error
     ../d1      ../d2/f2   ../d2/f2     ../d2/f2
     ../d1      /d2/f2     Error        Error
     /d1        d2/f2      d2/f2        Error
     /d1        ../d2/f2   ../d2/f2     Error
     /d1        /d2/f2     ../d2/f2     ../d2/f2
     d1         d1         d1           . (because pathname2 is like ...)
     /d1        /d1        .            . (dirname1, so it's a directory)
   The errors have the code : NETWIB_ERR_PAPATHCANTINIT.
*/
netwib_err netwib_path_init(netwib_constbuf *pdirname1,
                            netwib_constbuf *ppathname2,
                            netwib_path_inittype type,
                            netwib_buf *pout);
#define netwib_path_init_concat(dirname1,pathname2,pout) netwib_path_init(dirname1,pathname2,NETWIB_PATH_INITTYPE_CONCAT,pout)
#define netwib_path_init_jail(dirname1,pathname2,pout) netwib_path_init(dirname1,pathname2,NETWIB_PATH_INITTYPE_JAIL,pout)
#define netwib_path_init_abs(dirname1,pathname2,pout) netwib_path_init(dirname1,pathname2,NETWIB_PATH_INITTYPE_ABS,pout)
#define netwib_path_init_rela(dirname1,pathname2,pout) netwib_path_init(dirname1,pathname2,NETWIB_PATH_INITTYPE_RELA,pout)
#define netwib_path_init_relb(dirname1,pathname2,pout) netwib_path_init(dirname1,pathname2,NETWIB_PATH_INITTYPE_RELB,pout)

MODULE PATHNAME
/*-------------------------------------------------------------*/
/* Name : netwib_pathname_exists
   Description :
     Check if a path exists.
   Input parameter(s) :
     *ppathname : pathname
   Input/output parameter(s) :
   Output parameter(s) :
     *pyes : if path exists
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_pathname_exists(netwib_constbuf *ppathname,
                                  netwib_bool *pyes);

MODULE PATHSTAT
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_PATHSTAT_TYPE_UNKNOWN = 0, /* unknown type */
  NETWIB_PATHSTAT_TYPE_REG,         /* regular file */
  NETWIB_PATHSTAT_TYPE_DIR,         /* directory */
  NETWIB_PATHSTAT_TYPE_LINK,        /* link */
  NETWIB_PATHSTAT_TYPE_SOCK,        /* socket */
  NETWIB_PATHSTAT_TYPE_BLOCK,       /* block file */
  NETWIB_PATHSTAT_TYPE_CHAR,        /* char file */
  NETWIB_PATHSTAT_TYPE_FIFO         /* fifo */
} netwib_pathstat_type;
/*-------------------------------------------------------------*/
/***************************************************************
 * On conventional filesystems, maximum file size is           *
 * 0x7FFFFFFF (2G) because it is stored as signed (as netwib   *
 * defines size as unsigned, we could extend this limit to 4G, *
 * but this poses some other problems because all underlying   *
 * system calls have a limit of 2G).                           *
 * On large filesystems, maximum file size can be greater and  *
 * might not feet in an netwib_uint32 size. If file size is    *
 * > 0x7FFFFFFF, size is set to NETWIB_PATHSTAT_SIZE_GT2G.     *
 * In both cases, size64 variable contains the real value.     *
 ***************************************************************/
#define NETWIB_PATHSTAT_SIZE_GT2G 0x80000000u
typedef struct {
  netwib_pathstat_type type;
  netwib_uint32 size; /* set to NETWIB_PATHSTAT_SIZE_GT2G
                         if netwib_uint32 variable is too
                         small to contain real size */
  netwib_uint64 size64; /* real size, not truncated */
  netwib_time mtime; /* last modification time */
} netwib_pathstat;
/*-------------------------------------------------------------*/
/* Name : netwib_pathstat_init
   Description :
     Get information of a path.
   Input parameter(s) :
     *ppathstat : pathstat
   Input/output parameter(s) :
   Output parameter(s) :
     *ptype : type of the path
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_OKFILENOTFOUND : file was not found
*/
netwib_err netwib_pathstat_init(netwib_constbuf *ppath,
                                netwib_pathstat *pstat);

MODULE DIRNAME
/*-------------------------------------------------------------*/
/***************************************************************
 * NOTE ABOUT SECURITY UNDER UNIX                              *
 * The only way to deal securely with a file/dir is to store   *
 * it in a secure directory (every dir in the path should only *
 * be writable by root or current user).                       *
 * Otherwise a malicious user can create a symlink and force   *
 * corruption/creation/removing of a file/dir.                 *
 * So, to secure your program, you should force user to work   *
 * only in secured directories. Function netwib_dirname_secure *
 * permits to check if a directory is secure. Note that netwib *
 * functions do not check for secure directories internally :  *
 * you should do it yourself.                                  *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_secure
   Description :
     Check if a directory is secure.
   Input parameter(s) :
     *pdirname : name of the directory
   Input/output parameter(s) :
   Output parameter(s) :
     *pyes : true if directory is secure
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_secure(netwib_constbuf *pdirname,
                                 netwib_bool *pyes);
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_cwd
   Description :
     Get current working directory.
   Input parameter(s) :
   Input/output parameter(s) :
     *pdirname : name of the directory
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_cwd(netwib_buf *pdirname);
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_exists
   Description :
     Check if a directory exist.
   Input parameter(s) :
     *pdirname : name of the directory
   Input/output parameter(s) :
   Output parameter(s) :
     *pyes : true if directory exists
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_exists(netwib_constbuf *pdirname,
                                 netwib_bool *pyes);
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_create
   Description :
     Create a directory.
     Warning : this function is not secured against
               symlink races
   Input parameter(s) :
     *pdirname : name of the directory
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_create(netwib_constbuf *pdirname);
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_remove
   Description :
     Remove a directory.
   Input parameter(s) :
     *pdirname : name of the directory
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_remove(netwib_constbuf *pdirname);
/*-------------------------------------------------------------*/
/* Name : netwib_dirname_rename
   Description :
     Rename a directory.
   Input parameter(s) :
     *polddirname : previous name of the directory
     *pnewdirname : new name for the directory
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dirname_rename(netwib_constbuf *polddirname,
                                 netwib_constbuf *pnewdirname);

MODULE FILENAME
/*-------------------------------------------------------------*/
/* Name : netwib_filename_exists
   Description :
     Check if a regular file exists.
   Input parameter(s) :
     *pfilename : filename
   Input/output parameter(s) :
   Output parameter(s) :
     *pyes : if file exists
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_filename_exists(netwib_constbuf *pfilename,
                                  netwib_bool *pyes);
/*-------------------------------------------------------------*/
/* Name : netwib_filename_size
   Description :
     Get size of a file.
   Input parameter(s) :
     *pfilename : filename
   Input/output parameter(s) :
   Output parameter(s) :
     *psize : size of the file
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTFOUND : file was not found
   Note :
     On a large filesystem, if file size is greater than
     2G, this function returns the error NETWIB_ERR_PAFILE2G.
     Use netwib_pathstat_init instead.
*/
netwib_err netwib_filename_size(netwib_constbuf *pfilename,
                                netwib_uint32 *psize);
/*-------------------------------------------------------------*/
/* Name : netwib_filename_create
   Description :
     Create an empty file. If it exists, truncate its contents.
   Input parameter(s) :
     *pfilename : filename
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_filename_create(netwib_constbuf *pfilename);
/*-------------------------------------------------------------*/
/* Name : netwib_filename_remove
   Description :
     Remove a file.
   Input parameter(s) :
     *pfilename : filename
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTFOUND : file was not found
*/
netwib_err netwib_filename_remove(netwib_constbuf *pfilename);
/*-------------------------------------------------------------*/
/* Name : netwib_filename_rename
   Description :
     Rename a file.
   Input parameter(s) :
     *poldfilename : old filename
     *pnewfilename : new filename
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTFOUND : file was not found
*/
netwib_err netwib_filename_rename(netwib_constbuf *poldfilename,
                                  netwib_constbuf *pnewfilename);
/*-------------------------------------------------------------*/
/* Name : netwib_filename_copy
   Description :
     Copy a file.
   Input parameter(s) :
     *poldfilename : old filename
     *pnewfilename : new filename
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTFOUND : file was not found
*/
netwib_err netwib_filename_copy(netwib_constbuf *poldfilename,
                                netwib_constbuf *pnewfilename);

MODULE DIR
/*-------------------------------------------------------------*/
/***************************************************************
 * A netwib_dir permits to loop through all filenames in a     *
 * directory.                                                  *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct netwib_dir netwib_dir;
/*-------------------------------------------------------------*/
/* Name : netwib_dir_init
   Description :
     Open a directory.
   Input parameter(s) :
     *pdirname : directory name
   Input/output parameter(s) :
   Output parameter(s) :
     **ppdir : netwib_dir initialized
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dir_init(netwib_constbuf *pdirname,
                           netwib_dir **ppdir);
/*-------------------------------------------------------------*/
/* Name : netwib_dir_close
   Description :
     Close a netwib_dir.
   Input parameter(s) :
   Input/output parameter(s) :
     **ppdir : netwib_dir closed
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_dir_close(netwib_dir **ppdir);
/*-------------------------------------------------------------*/
/* Types to control a netwib_dir */
typedef enum {
  NETWIB_DIR_CTLTYPE_REWIND = 1        /* position at beginning */
} netwib_dir_ctltype;
netwib_err netwib_dir_ctl_set(netwib_dir *pdir,
                              netwib_dir_ctltype type,
                              netwib_ptr p,
                              netwib_uint32 ui);
netwib_err netwib_dir_ctl_get(netwib_dir *pdir,
                              netwib_dir_ctltype type,
                              netwib_ptr p,
                              netwib_uint32 *pui);
/*-------------------------------------------------------------*/
/* netwib_err f(netwib_dir *pdir); */
#define netwib_dir_ctl_set_rewind(pdir) netwib_dir_ctl_set(pdir,NETWIB_DIR_CTLTYPE_REWIND,NULL,0)
/*-------------------------------------------------------------*/
/* Name : netwib_dir_next
   Description :
     Obtain the next file of a netwib_dir.
   Input parameter(s) :
   Input/output parameter(s) :
     **ppdir : netwib_dir
     pbuffilename : buffer containing the filename
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
   Notes :
     If directory files change between two calls,
     the next result might be incorrect, but it will not crash.
*/
netwib_err netwib_dir_next(netwib_dir *pdir,
                           netwib_buf *pbuffilename);

MODULE THREAD
/*-------------------------------------------------------------*/
typedef struct netwib_thread netwib_thread;
/*-------------------------------------------------------------*/
/* thread ends when this function returns */
typedef netwib_err (*netwib_thread_pf)(netwib_ptr infosin,
                                       netwib_ptr *pinfosout);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_init
   Description :
     Create a new thread, which will execute *pfunc and exit.
   Input parameter(s) :
     *pfunc : function executed by the new thread :
              infosin : set with infosin
              pinfosout : eventually set by user
     infosin : data to pass to the thread
   Input/output parameter(s) :
   Output parameter(s) :
     **ppthread : thread created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_init(netwib_thread_pf pfunc,
                              netwib_ptr infosin,
                              netwib_thread **ppthread);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_close
   Description :
     Free memory allocated by a netwib_thread.
     Note : this function does not terminate the thread.
            function netwib_thread_wait must be called before
   Input parameter(s) :
   Input/output parameter(s) :
     **ppthread : thread to free
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_close(netwib_thread **ppthead);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_wait
   Description :
     Wait for the end of the thread.
   Input parameter(s) :
     *pthread : thread to wait for
     *pabstime : end time. If *pabstime is reached, function
                 returns (*pevent set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *pevent : true if thread ended
     *preturnederror : value returned by the thread
     *pinfosout : info eventually set by thread
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_wait(netwib_thread *pthread,
                              netwib_consttime *pabstime,
                              netwib_bool *pevent,
                              netwib_err *preturnederror,
                              netwib_ptr *pinfosout);

MODULE THREADMUT
/*-------------------------------------------------------------*/
typedef struct netwib_thread_mutex netwib_thread_mutex;
/*-------------------------------------------------------------*/
/* Name : netwib_thread_mutex_init
   Description :
     Initialize a mutex.
   Input parameter(s) :
   Input/output parameter(s) :
     *ppmutex : netwib_thread_mutex initialized
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_mutex_init(netwib_thread_mutex **ppmutex);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_mutex_close
   Description :
     Close a mutex.
   Input parameter(s) :
   Input/output parameter(s) :
     *ppmutex : netwib_thread_mutex closed
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_mutex_close(netwib_thread_mutex **ppmutex);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_mutex_lock
   Description :
     Wait for the mutex.
   Input parameter(s) :
     *pmutex : netwib_thread_mutex
     *pabstime : end time. If *pabstime is reached, locking is
                 not done (*plocked set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *plocked : the mutex could be locked
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_mutex_lock(netwib_thread_mutex *pmutex,
                                    netwib_consttime *pabstime,
                                    netwib_bool *plocked);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_mutex_unlock
   Description :
     Unlock a mutex.
   Input parameter(s) :
   Input/output parameter(s) :
     *pmutex : netwib_thread_mutex to unlock
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_mutex_unlock(netwib_thread_mutex *pmutex);

MODULE THREADRWL
/*-------------------------------------------------------------*/
typedef struct netwib_thread_rwlock netwib_thread_rwlock;
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_init
   Description :
     Initialize a rwlock.
   Input parameter(s) :
   Input/output parameter(s) :
     *pprwlock : netwib_thread_rwlock initialized
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_init(netwib_thread_rwlock **pprwlock);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_close
   Description :
     Close a rwlock.
   Input parameter(s) :
   Input/output parameter(s) :
     *pprwlock : netwib_thread_rwlock closed
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_close(netwib_thread_rwlock **pprwlock);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_rdlock
   Description :
     Wait for the rwlock.
     We lock for reading.
   Input parameter(s) :
     *prwlock : netwib_thread_rwlock
     *pabstime : end time. If *pabstime is reached, locking is
                 not done (*plocked set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *plocked : the rwlock could be locked
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_rdlock(netwib_thread_rwlock *prwlock,
                                       netwib_consttime *pabstime,
                                       netwib_bool *plocked);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_rdunlock
   Description :
     Unlock reading of a rwlock.
   Input parameter(s) :
   Input/output parameter(s) :
     *prwlock : netwib_thread_rwlock to unlock
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_rdunlock(netwib_thread_rwlock *prwlock);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_wrlock
   Description :
     Wait for the rwlock.
     We lock for writing.
   Input parameter(s) :
     *prwlock : netwib_thread_rwlock
     *pabstime : end time. If *pabstime is reached, locking is
                 not done (*plocked set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *plocked : the rwlock could be locked
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_wrlock(netwib_thread_rwlock *prwlock,
                                       netwib_consttime *pabstime,
                                       netwib_bool *plocked);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_rwlock_wrunlock
   Description :
     Unlock writing of a rwlock.
   Input parameter(s) :
   Input/output parameter(s) :
     *prwlock : netwib_thread_rwlock to unlock
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_rwlock_wrunlock(netwib_thread_rwlock *prwlock);

MODULE THREADCOND
/*-------------------------------------------------------------*/
typedef struct netwib_thread_cond netwib_thread_cond;
/*-------------------------------------------------------------*/
/* Name : netwib_thread_cond_init
   Description :
     Initialize a condition.
   Input parameter(s) :
   Input/output parameter(s) :
     *ppcond : netwib_thread_cond initialized
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_cond_init(netwib_thread_cond **ppcond);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_cond_close
   Description :
     Close a condition.
   Input parameter(s) :
   Input/output parameter(s) :
     *ppcond : netwib_thread_cond closed
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_cond_close(netwib_thread_cond **ppcond);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_cond_broadcast
   Description :
     Inform every waiting thread.
   Input parameter(s) :
     value : value to broadcast
   Input/output parameter(s) :
     *pcond : netwib_thread_cond
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_cond_broadcast(netwib_thread_cond *pcond,
                                        netwib_uint32 value);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_cond_wait
   Description :
     Wait for the condition.
   Input parameter(s) :
     *pcond : netwib_thread_cond
     *pabstime : end time. If *pabstime is reached, function
                 returns (*pevent set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *pevent : condition reached
     *pvalue : value received
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_cond_wait(netwib_thread_cond *pcond,
                                   netwib_consttime *pabstime,
                                   netwib_bool *pevent,
                                   netwib_uint32 *pvalue);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_cond_reinit
   Description :
     Reset the condition. So netwib_thread_cond_broadcast
     can be used again.
   Input parameter(s) :
   Input/output parameter(s) :
     *pcond : netwib_thread_cond
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_cond_reinit(netwib_thread_cond *pcond);

MODULE THREADTSD
/*-------------------------------------------------------------*/
/***************************************************************
 * TSD : Thread Specific Data                                  *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct netwib_thread_tsd netwib_thread_tsd;
/*-------------------------------------------------------------*/
/* Name : netwib_thread_tsd_init
   Description :
     Initialize a tsd.
   Input parameter(s) :
   Input/output parameter(s) :
     *pptsd : netwib_thread_tsd initialized
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_tsd_init(netwib_thread_tsd **pptsd);
/*-------------------------------------------------------------*/
/* Name : netwib_thread_tsd_close
   Description :
     Close a tsd.
   Input parameter(s) :
   Input/output parameter(s) :
     *pptsd : netwib_thread_tsd closed
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_thread_tsd_close(netwib_thread_tsd **pptsd);
/*-------------------------------------------------------------*/
/* Types to control a netwib_thread_tsd */
typedef enum {
  NETWIB_THREAD_TSD_CTLTYPE_VALUE = 1   /* get/set value */
} netwib_thread_tsd_ctltype;
netwib_err netwib_thread_tsd_ctl_set(netwib_thread_tsd *ptsd,
                                     netwib_thread_tsd_ctltype type,
                                     netwib_ptr p,
                                     netwib_uint32 ui);
netwib_err netwib_thread_tsd_ctl_get(netwib_thread_tsd *ptsd,
                                     netwib_thread_tsd_ctltype type,
                                     netwib_ptr p,
                                     netwib_uint32 *pui);
/*-------------------------------------------------------------*/
/* netwib_err f(netwib_thread_tsd *pthread_tsd, netwib_ptr ptr); */
#define netwib_thread_tsd_ctl_set_value(pthread_tsd,ptr) netwib_thread_tsd_ctl_set(pthread_tsd,NETWIB_THREAD_TSD_CTLTYPE_VALUE,ptr,0)
/* netwib_err f(netwib_thread_tsd *pthread_tsd, netwib_ptr ptr); */
#define netwib_thread_tsd_ctl_get_value(pthread_tsd,ptr) netwib_thread_tsd_ctl_get(pthread_tsd,NETWIB_THREAD_TSD_CTLTYPE_VALUE,ptr,0)

MODULE THREADLIST
/*-------------------------------------------------------------*/
/***************************************************************
 * Those functions deals with several threads, referenced      *
 * by their id.                                                *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct {
  netwib_thread *pthread;
  netwib_uint32 threadid;
} netwib_threadringitem;
/*-------------------------------------------------------------*/
/* Name : netwib_threadlist_init
   Description :
     Create a new threadlist.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppring : netwib_ring initialized
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_threadlist_init(netwib_ring **ppring);
/*-------------------------------------------------------------*/
/* Name : netwib_threadlist_close
   Description :
     Wait for threads in the list (this can be infinite if one
     thread never ends). If one thread returns on error, it is
     ignored. Then, close the threadlist.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppring : netwib_ring to close
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_threadlist_close(netwib_ring **ppring);
/*-------------------------------------------------------------*/
/* Name : netwib_threadlist_add
   Description :
     Add a new thread.
   Input parameter(s) :
     *pthread : thread to add
     threadid : id of the newly added thread (any value decided
                by user)
   Input/output parameter(s) :
     *pring : netwib_ring where to add the thread
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_threadlist_add(netwib_ring *pring,
                                 netwib_thread *pthread,
                                 netwib_uint32 threadid);
/*-------------------------------------------------------------*/
/* Name : netwib_threadlist_del
   Description :
     Remove a thread from the ring.
   Input parameter(s) :
     threadid : id of the thread to remove
   Input/output parameter(s) :
     *pring : netwib_ring where to remove the thread
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_threadlist_del(netwib_ring *pring,
                                 netwib_uint32 threadid);
/*-------------------------------------------------------------*/
/* Name : netwib_threadlist_wait
   Description :
     Wait for the end of one thread. When this occurs, the
     netwib_thread associated is closed (use netwib_threadlist_del
     to remove a thread from the list : you can wait and close
     it yourself).
   Input parameter(s) :
     *pring : netwib_ring containing threads
     *pabstime : end time. If *pabstime is reached, function
                 returns (*pevent set to NETWIB_FALSE).
   Input/output parameter(s) :
   Output parameter(s) :
     *pevent : a thread finished
     *pthreadid : id of the thread
     *preturnederror : value returned by the thread
     *pinfosout : info eventually set by thread
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_DATAEND : there is no more thread in the ring
*/
netwib_err netwib_threadlist_wait(netwib_ring *pring,
                                  netwib_consttime *pabstime,
                                  netwib_bool *pevent,
                                  netwib_uint32 *pthreadid,
                                  netwib_err *preturnederror,
                                  netwib_ptr *pinfosout);
/*-------------------------------------------------------------*/
/***************************************************************
 * For other functions, you can directly use functions of      *
 * ring.h.                                                     *
 * To do so, booleans "eraseitems" and "duplicateitems" have   *
 * be set to NETWIB_TRUE. See netwib_threadlist_close for      *
 * example.                                                    *
 ***************************************************************/

MODULE IO
/*-------------------------------------------------------------*/
/***************************************************************
 * A netwib_io is the main way to exchange data in netwib.     *
 *                                                             *
 * A concrete example first :                                  *
 *   ----.     ,-----.     ,-------.     ,----.     ,------    *
 *   file >---->readl >---( program )---->conv >---->socket    *
 *   ----'     `-----'     `-------'     `----'     `------    *
 *                                                             *
 * It works like this :                                        *
 *  - read data from a file                                    *
 *  - read only line by line                                   *
 *  - treat it in the program                                  *
 *  - write data for output                                    *
 *  - convert data, for example replacing '\' by "\\"          *
 *  - write data to socket                                     *
 *                                                             *
 * This example contains 3 types of netwib_io :                *
 *  - file and socket are "io final link"                      *
 *  - readl and conv are "io link"                             *
 *  - file and socket are also "io link" (because a            *
 *    "io final link" is a special kind of "io link")          *
 *  - conv is a "io chain" composed of conv+socket             *
 *  - readl is a "io chain" composed of readl+file             *
 *  - socket is a "io chain" composed of only socket           *
 *  - file is a "io chain" composed of only file               *
 *                                                             *
 * Using the same program, we might for example read data      *
 * from a file and write them back to a socket. This can be    *
 * represented as :                                            *
 *   ------.      ,-------.      ,---------                    *
 *    file  >----( program )-----> socket                      *
 *   ------'      `-------'      `---------                    *
 * Another variant would be to plug readl or conv to other     *
 * "io chain", such as :                                       *
 *   ----.     ,-----.     ,-------.     ,----.     ,------    *
 *   ipc  >---->readl >---( program )---->conv >---->record    *
 *   ----'     `-----'     `-------'     `----'     `------    *
 * An "io chain" can be bi-directional. For example :          *
 *   --------.       ,--.      ,-------.                       *
 *    socket  >------>l5 >----( program )-.                    *
 *           <------<   <--.   `-------'  |                    *
 *   --------'       `--'   `-------------'                    *
 *                                                             *
 * Note : you can find other examples at the end of this file  *
 *                                                             *
 * The main ideas to remember is :                             *
 *  - a "io chain" is composed of one or more "io link"        *
 *  - a "io link" might be intermediary or "io final link"     *
 *  - those 3 types use the same structure : netwib_io         *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct netwib_io netwib_io;
/*-------------------------------------------------------------*/
/* direction */
typedef enum {
  NETWIB_IO_WAYTYPE_READ = 1,    /* read */
  NETWIB_IO_WAYTYPE_WRITE,       /* write */
  NETWIB_IO_WAYTYPE_RDWR,        /* read and write */
  NETWIB_IO_WAYTYPE_NONE,        /* nor read nor write */
  NETWIB_IO_WAYTYPE_SUPPORTED    /* every way supported by the io */
} netwib_io_waytype;
/*-------------------------------------------------------------*/
/***************************************************************
 * Currently, system "io final link" are :                     *
 *    Name      Definition     Read/Write                      *
 *   FILE   : regular file   : read/write                      *
 *   FD     : file desc      : read/write                      *
 *   HANDLE : Windows HANDLE : read/write                      *
 *   KBD    : keyboard       : read                            *
 *   RECORD : record         : read/write                      *
 *   SOCK   : socket         : read/write                      *
 *   SNIFF  : sniff          : read                            *
 *   SPOOF  : spoof          : write                           *
 * They are initialized by :                                   *
 *  - netwib_io_init_file                                      *
 *  - netwib_io_init_fd                                        *
 *  - etc.                                                     *
 ***************************************************************/
/*-------------------------------------------------------------*/
/***************************************************************
 * Those five functions permits to create and to navigate      *
 * through a "io chain".                                       *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_plug
   Description :
     Create a chain by pluging one link/chain to another.
   Input parameter(s) :
     *piowheretoplug : io where to plug
     typeofplug : type of plug
   Input/output parameter(s) :
     *pio : current io
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_plug(netwib_io *pio,
                          netwib_io_waytype typeofplug,
                          netwib_io *piowheretoplug);
/* netwib_err f(netwib_io *pio, netwib_io *piowheretoplug); */
#define netwib_io_plug_read(pio,piowheretoplug) netwib_io_plug(pio,NETWIB_IO_WAYTYPE_READ,piowheretoplug)
#define netwib_io_plug_write(pio,piowheretoplug) netwib_io_plug(pio,NETWIB_IO_WAYTYPE_WRITE,piowheretoplug)
#define netwib_io_plug_rdwr(pio,piowheretoplug) netwib_io_plug(pio,NETWIB_IO_WAYTYPE_RDWR,piowheretoplug)
#define netwib_io_plug_supported(pio,piowheretoplug) netwib_io_plug(pio,NETWIB_IO_WAYTYPE_SUPPORTED,piowheretoplug)
/*-------------------------------------------------------------*/
/***************************************************************
 * There are three ways to unplug :                            *
 *      ,----.     ,----.     ,----.     ,----.     ,----.     *
 *   ---> io1 >----> io2 >----> io3 >----> io4 >----> io5 >--  *
 *      `----'     `----'     `----'     `----'     `----'     *
 *                                                             *
 * netwib_io_unplug_next with:                                 *
 *   pio = &io1                                                *
 *  ==> cut between io1 and io2, and put &io2 in pnextio       *
 *                                                             *
 * netwib_io_unplug_before with:                               *
 *   pio = &io1                                                *
 *   psearchedio = &io3                                        *
 *  ==> cut between io2 and io3                                *
 *                                                             *
 * netwib_io_unplug_after with:                                *
 *   pio = &io1                                                *
 *   psearchedio = &io3                                        *
 *  ==> cut between io3 and io4, and put &io4 in pafterio      *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_unplug_xyz
   Description :
     Separate a chain by unplugging one link/chain from another.
   Input parameter(s) :
     typeofplug : type of plug
     *psearchedio : searched io
   Input/output parameter(s) :
     *pio : io chain
   Output parameter(s) :
     **ppnextio : next io or NULL if at end
     **ppafterio : next io or NULL if at end
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_NOTFOUND : psearchedio was not found
*/
netwib_err netwib_io_unplug_next(netwib_io *pio,
                                 netwib_io_waytype typeofplug,
                                 netwib_io **ppnextio);
netwib_err netwib_io_unplug_before(netwib_io *pio,
                                   netwib_io_waytype typeofplug,
                                   netwib_io *psearchedio);
netwib_err netwib_io_unplug_after(netwib_io *pio,
                                  netwib_io_waytype typeofplug,
                                  netwib_io *psearchedio,
                                  netwib_io **ppafterio);
#define netwib_io_unplug_next_read(pio,ppnextio) netwib_io_unplug_next(pio,NETWIB_IO_WAYTYPE_READ,ppnextio)
#define netwib_io_unplug_before_read(pio,psearchedio) netwib_io_unplug_before(pio,NETWIB_IO_WAYTYPE_READ,psearchedio)
#define netwib_io_unplug_after_read(pio,psearchedio,ppafterio) netwib_io_unplug_after(pio,NETWIB_IO_WAYTYPE_READ,psearchedio,ppafterio)
#define netwib_io_unplug_next_write(pio,ppnextio) netwib_io_unplug_next(pio,NETWIB_IO_WAYTYPE_WRITE,ppnextio)
#define netwib_io_unplug_before_write(pio,psearchedio) netwib_io_unplug_before(pio,NETWIB_IO_WAYTYPE_WRITE,psearchedio)
#define netwib_io_unplug_after_write(pio,psearchedio,ppafterio) netwib_io_unplug_after(pio,NETWIB_IO_WAYTYPE_WRITE,psearchedio,ppafterio)
#define netwib_io_unplug_next_rdwr(pio,ppnextio) netwib_io_unplug_next(pio,NETWIB_IO_WAYTYPE_RDWR,ppnextio)
#define netwib_io_unplug_before_rdwr(pio,psearchedio) netwib_io_unplug_before(pio,NETWIB_IO_WAYTYPE_RDWR,psearchedio)
#define netwib_io_unplug_after_rdwr(pio,psearchedio,ppafterio) netwib_io_unplug_after(pio,NETWIB_IO_WAYTYPE_RDWR,psearchedio,ppafterio)
#define netwib_io_unplug_next_supported(pio,ppnextio) netwib_io_unplug_next(pio,NETWIB_IO_WAYTYPE_SUPPORTED,ppnextio)
#define netwib_io_unplug_before_supported(pio,psearchedio) netwib_io_unplug_before(pio,NETWIB_IO_WAYTYPE_SUPPORTED,psearchedio)
#define netwib_io_unplug_after_supported(pio,psearchedio,ppafterio) netwib_io_unplug_after(pio,NETWIB_IO_WAYTYPE_SUPPORTED,psearchedio,ppafterio)
/*-------------------------------------------------------------*/
/* Name : netwib_io_next
   Description :
     Obtain the next io in the chain.
   Input parameter(s) :
     *pio : io
   Input/output parameter(s) :
     **ppionext : io after pio of type typetofollow
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_DATAEND : there is no more io after
*/
netwib_err netwib_io_next(netwib_io *pio,
                          netwib_io_waytype typetofollow,
                          netwib_io **ppionext);
/* netwib_err f(netwib_io *pio, netwib_io *pionext); */
#define netwib_io_next_read(pio,pionext) netwib_io_next(pio,NETWIB_IO_WAYTYPE_READ,pionext)
#define netwib_io_next_write(pio,pionext) netwib_io_next(pio,NETWIB_IO_WAYTYPE_WRITE,pionext)
#define netwib_io_next_rdwr(pio,pionext) netwib_io_next(pio,NETWIB_IO_WAYTYPE_RDWR,pionext)
#define netwib_io_next_supported(pio,pionext) netwib_io_next(pio,NETWIB_IO_WAYTYPE_SUPPORTED,pionext)
/*-------------------------------------------------------------*/
/***************************************************************
 * Those three functions permits to exchange data through a    *
 * "io chain".                                                 *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_write_xyz
   Description :
     Write data to a netwib_io.
   Input parameter(s) :
     *pbuf : buffer to write
   Input/output parameter(s) :
     **pio : netwib_io where to write
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_write(netwib_io *pio,
                           netwib_constbuf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_io_read_xyz
   Description :
     Read data to a netwib_io.
   Input parameter(s) :
   Input/output parameter(s) :
     **pio : netwib_io where to read
     *pbuf : buffer storing read data
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_DATAEND : end of data
*/
netwib_err netwib_io_read(netwib_io *pio,
                          netwib_buf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_io_unread
   Description :
     Put data back in the read io.
   Input parameter(s) :
   Input/output parameter(s) :
     **pio : netwib_io where to read
     *pbuf : buffer containing data
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_unread(netwib_io *pio,
                            netwib_constbuf *pbuf);
/*-------------------------------------------------------------*/
/***************************************************************
 * Those three functions permits to control an "io chain".     *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_wait
   Description :
     Wait for data in the io.
   Input parameter(s) :
     *pabstime : end time. If *pabstime is reached, function
                 returns (*pevent set to NETWIB_FALSE).
   Input/output parameter(s) :
     **pio : netwib_io where to wait
   Output parameter(s) :
     *pevent : an event occurred
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_wait(netwib_io *pio,
                          netwib_io_waytype way,
                          netwib_consttime *pabstime,
                          netwib_bool *pevent);
/* netwib_err f(netwib_io *pio, netwib_consttime *pabstime, netwib_bool *pevent); */
#define netwib_io_wait_read(pio,pabstime,pevent) netwib_io_wait(pio,NETWIB_IO_WAYTYPE_READ,pabstime,pevent)
#define netwib_io_wait_write(pio,pabstime,pevent) netwib_io_wait(pio,NETWIB_IO_WAYTYPE_WRITE,pabstime,pevent)
#define netwib_io_wait_rdwr(pio,pabstime,pevent) netwib_io_wait(pio,NETWIB_IO_WAYTYPE_RDWR,pabstime,pevent)
#define netwib_io_wait_supported(pio,pabstime,pevent) netwib_io_wait(pio,NETWIB_IO_WAYTYPE_SUPPORTED,pabstime,pevent)
/*-------------------------------------------------------------*/
/* Explaining those values would be too complicated here. Please
   refer to the defines using them (which are documented).
*/
typedef enum {
  /** values working on current io (they are not recursive) **/
  NETWIB_IO_CTLTYPE_SUPPORT = 1,
  NETWIB_IO_CTLTYPE_NUMUSERS,
  NETWIB_IO_CTLTYPE_NUMUSERSINC,
  /** values working on current io (if NETWIB_ERR_OK is returned) or
      on next io (if NETWIB_ERR_PLEASETRYNEXT is returned) **/
  NETWIB_IO_CTLTYPE_RES = 100,
  NETWIB_IO_CTLTYPE_END,
  /** values which are specific **/
  /* file : 200 */
  NETWIB_IO_CTLTYPE_FILE_SEEK_BEGIN = 200,
  NETWIB_IO_CTLTYPE_FILE_SEEK_CURRENT,
  NETWIB_IO_CTLTYPE_FILE_SEEK_END,
  NETWIB_IO_CTLTYPE_FILE_TELL,
  NETWIB_IO_CTLTYPE_FILE_TRUNCATE,
  /* fd : 300 */
  /* handle : 400 */
  /* ipc : 500 */
  NETWIB_IO_CTLTYPE_IPC_SIDEREAD = 500,
  NETWIB_IO_CTLTYPE_IPC_SIDEWRITE,
  NETWIB_IO_CTLTYPE_IPC_NOTUSED,
  /* kbd : 600 */
  NETWIB_IO_CTLTYPE_KBD_ECHO = 600,
  NETWIB_IO_CTLTYPE_KBD_LINE,
  NETWIB_IO_CTLTYPE_KBD_PURGE,
  /* record : 700 */
  /* sock : 800 */
  NETWIB_IO_CTLTYPE_SOCK_IP4OPTS = 800,
  NETWIB_IO_CTLTYPE_SOCK_IP6EXTS,
  NETWIB_IO_CTLTYPE_SOCK_LOCAL,
  NETWIB_IO_CTLTYPE_SOCK_REMOTE,
  NETWIB_IO_CTLTYPE_SOCK_MULTICASTTTL,
  NETWIB_IO_CTLTYPE_SOCK_SOCKTYPE,
  /* sockv : 900 */
  NETWIB_IO_CTLTYPE_SOCKV_ANSWERALIVE = 900,
  /* sniff : 1000 */
  NETWIB_IO_CTLTYPE_SNIFF_FILTER = 1000,
  NETWIB_IO_CTLTYPE_SNIFF_DLT,
  /* spoof : 1100 */
  NETWIB_IO_CTLTYPE_SPOOF_DLT= 1100,
  /** values which are specific to iousual.h **/
  /* ioutil : 2000 */
  NETWIB_IO_CTLTYPE_DATA_LINE_MSDOS = 2000,
  NETWIB_IO_CTLTYPE_DATA_CHUNK_MINSIZE,
  NETWIB_IO_CTLTYPE_DATA_CHUNK_MAXSIZE,
  NETWIB_IO_CTLTYPE_DATA_FIXED_SIZE,
  NETWIB_IO_CTLTYPE_DATA_TYPE,
  NETWIB_IO_CTLTYPE_STORAGE_FLUSH,
  /** values which are specific to users' utilities **/
  /* user defined : start at 10000 */
  NETWIB_IO_CTLTYPE_USER_BEGIN = NETWIB_ENUM_USER_BEGIN
} netwib_io_ctltype;
/* Those functions permit to set/get parameters (pointer and
   integer) about a netwib_io. It should not be used directly,
   but by the defines.
   In function netwib_io_ctl_get, parameter p could be
   a "netwib_ptr *pp" instead of "netwib_ptr p", but it
   complicates things for nothing : a pointer can be
   used for what we want. For example, its easier to use
   ctl_get(..., &buf, &ui) instead of ("&&buf", &ui).
*/
netwib_err netwib_io_ctl_set(netwib_io *pio,
                             netwib_io_waytype way,
                             netwib_io_ctltype ctltype,
                             netwib_ptr p,
                             netwib_uint32 ui);
netwib_err netwib_io_ctl_get(netwib_io *pio,
                             netwib_io_waytype way,
                             netwib_io_ctltype ctltype,
                             netwib_ptr p,
                             netwib_uint32 *pui);
/*-------------------------------------------------------------*/
/***************************************************************
 * This function permits to close an "io chain".               *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_close
   Description :
     Close a chain (links are closed only if nobody use them
     anymore : numusers == 0).
   Input parameter(s) :
   Input/output parameter(s) :
     **ppio : netwib_io to close
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_close(netwib_io **ppio);
/*-------------------------------------------------------------*/
/***************************************************************
 * Common control defines                                      *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_IO_RESTYPE_FILE = 1,
  NETWIB_IO_RESTYPE_FD,
  NETWIB_IO_RESTYPE_HANDLE,
  NETWIB_IO_RESTYPE_IPC,
  NETWIB_IO_RESTYPE_KBD,
  NETWIB_IO_RESTYPE_SCREEN,
  NETWIB_IO_RESTYPE_STREAM,
  NETWIB_IO_RESTYPE_RECORD,
  NETWIB_IO_RESTYPE_SOCK,
  NETWIB_IO_RESTYPE_SOCKV,
  NETWIB_IO_RESTYPE_SNIFF,
  NETWIB_IO_RESTYPE_SPOOF,
  NETWIB_IO_RESTYPE_NULL,
  NETWIB_IO_RESTYPE_MEM,
  NETWIB_IO_RESTYPE_TLV,
  NETWIB_IO_RESTYPE_EXEC,
  NETWIB_IO_RESTYPE_SHELLSERVER,
  NETWIB_IO_RESTYPE_SHELLCLIENT,
  NETWIB_IO_RESTYPE_USER_BEGIN = NETWIB_ENUM_USER_BEGIN
} netwib_io_restype;
/* Obtain the resource type of a netwib_io */
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_io_restype *pres); */
#define netwib_io_ctl_get_res(pio,way,pres) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_RES,NULL,(netwib_uint32*)pres)
/*-------------------------------------------------------------*/
/* indicate the end of data */
/* netwib_err f(netwib_io *pio, netwib_io_waytype way); */
#define netwib_io_ctl_set_end(pio,way) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_END,NULL,0)
#define netwib_io_ctl_set_end_write(pio) netwib_io_ctl_set_end(pio,NETWIB_IO_WAYTYPE_WRITE)
/*-------------------------------------------------------------*/
/***************************************************************
 * Now, a big example ...                                      *
 ***************************************************************/
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#if 0
/* Complete example :
  We create a module (named m) having one input (i1) and two
  outputs (o1, o2) :
            ############# m #############
            #                           #
            #         ooooooooo         #  o1
        i1  #  ,--.   o       o--------------->
      >-------->l1 >--o HEART o   ,--.  #
            #  `--'   o       o--->l2 >------->
            #         ooooooooo   `--'  #  o2
            #                           #
            #############################
  The module contains 2 ios :
   - l1 : reads line by line
   - l2 : converts data to base64
  The heart of the module reads data from l1's output. If the
  data starts by 'A', then it is sent to o1. Else, data goes
  through l2.
  *** Usage 1 :
   - i1 is plugged to a file through io l3
   - o1 is plugged to file2
   - o2 is plugged to file3 through io l4
   - l3 reads data and duplicates it (read 'qa', output 'qqaa')
   - l4 reads data, displays it to screen and sends to output
                                                   ,-------
                               #####       ,-------> file2
      -------.      ,--.       #   >------'        `-------
       file1  >----->l3 >------> m #     ,--.      ,-------
      -------'      `--'       #   >----->l4 >-----> file3
                               #####     `--'      `-------
  *** Usage 2 :
   - i1 is plugged to socket soc1
   - o1 is plugged to null (data is junked)
   - o2 is plugged back to the same socket
                               #####               ,------
      ------.                  #   >---------------> null
       soc1  >-----------------> m #               `------
            <-------.          #   >----.
      ------'        \         #####    |
                      `-----------------'
  *** Usage 3 :
   - i1 is plugged to a socket through io l3
   - o1 is plugged to null (data is junked)
   - o2 is plugged back to the same socket through io l4
                               #####               ,------
                    ,--.       #   >---------------> null
      ------.    ,-->l3 >------> m #               `------
       soc1  >--'   `--'       #   >----.
            <--.    ,--.       #####    |
      ------'   `--< l4<----------------'
                    `--'
  *** Usage 4 :
   - l5 is a bi-directional io converting string to uppercase
   - l5 is plugged to socket soc1
   - i1 is plugged to l5
   - o1 is plugged to null (data is junked)
   - o2 is plugged back to l5
                               #####               ,------
                               #   >---------------> null
      ------.       ,--.    ,--> m #               `------
       soc1  >------>l5 >--'   #   >----.
            <------<   <--.    #####    |
      ------'       `--'   `------------'
  *** Usage 5 :
   - i1 is plugged to file1 through l5
   - o1 is plugged to null (data is junked)
   - o2 is plugged to file2 through l5
                               #####               ,------
     -------.                  #   >---------------> null
      file1  >--.   ,--.    ,--> m #               `------
     -------'    `-->l5 >--'   #   >----.
     -------.   ,--<   <--.    #####    |
      file2 <--'    `--'   `------------'
     -------'
  *** Usage 6 :
   - i1 is plugged to file1
   - o1 are o2 are both plugged to file2
                               #####
      -------.                 #   >------------.  ,-------
       file1  >----------------> m #             --> file2
      -------'                 #   >------------'  `-------
                               #####
  *** Usage 7 :
   - m2 is a module similar to m except it has 2 inputs
     and one output
   - i1 is plugged to file1
   - i2 is plugged to file1
   - o1 is plugged to null (data is junked)
   - o2 is plugged to file2
                               #####
      -------.   ,------------->   #               ,------
       file1  >--              # m >---------------> null
      -------'   `------------->   #               `------
                               #####
*/
/*-------------------------------------------------------------*/
/* l1 is netwib_io_init_read_line */
/*-------------------------------------------------------------*/
/* l2 : converts data to base64 */
netwib_err l2_write(netwib_io *pio,
                    netwib_constbuf *pbuf);
netwib_err l2_write(netwib_io *pio,
                    netwib_constbuf *pbuf)
{
  netwib_buf bufbase64;
  netwib_io *pionext;
  netwib_err ret;
  /* obtain the next io in the chain */
  netwib_er(netwib_io_next_write(pio, &pionext));
  /* converts pbuf to base64 */
  netwib_er(netwib_buf_init_mallocdefault(&bufbase64));
  netwib_er(netwib_buf_encode(pbuf, NETWIB_ENCODETYPE_BASE64, &bufbase64));
  /* write data to the next io */
  ret = netwib_io_write(pionext, &bufbase64);
  netwib_er(netwib_buf_close(&bufbase64));
  return(ret);
}
netwib_err l2_init(netwib_io **ppio);
netwib_err l2_init(netwib_io **ppio)
{
  netwib_er(netwib_io_init(NETWIB_FALSE, NETWIB_TRUE, NULL,
                           NULL/*read*/, &l2_write,
                           NULL/*wait*/, NULL/*unread*/,
                           NULL/*ctlset*/, NULL/*ctlget*/,
                           NULL/*close*/, ppio));
  return(NETWIB_ERR_OK);
}
/*-------------------------------------------------------------*/
/* l3 reads data and duplicates it (read 'qa', output 'qqaa') */
netwib_err l3_dup(netwib_constbuf *pinbuf,
                  netwib_buf *poutbuf);
netwib_err l3_dup(netwib_constbuf *pinbuf,
                  netwib_buf *poutbuf)
{
  netwib_data data;
  netwib_uint32 datasize, i;
  data = netwib__buf_ref_data_ptr(pinbuf);
  datasize = netwib__buf_ref_data_size(pinbuf);
  for (i = 0; i < datasize; i++) {
    netwib_er(netwib_buf_append_byte(data[i], poutbuf));
    netwib_er(netwib_buf_append_byte(data[i], poutbuf));
  }
  return(NETWIB_ERR_OK);
}
netwib_err l3_read(netwib_io *pio,
                   netwib_buf *pbuf);
netwib_err l3_read(netwib_io *pio,
                   netwib_buf *pbuf)
{
  netwib_buf buf;
  netwib_io *pionext;
  /* obtain the next io in the chain */
  netwib_er(netwib_io_next_read(pio, &pionext));
  /* read data */
  netwib_er(netwib_buf_init_mallocdefault(&buf));
  netwib_er(netwib_io_read(pionext, &buf));
  /* duplicate buf */
  netwib_er(l3_dup(&buf, pbuf));
  netwib_er(netwib_buf_close(&buf));
  return(NETWIB_ERR_OK);
}
netwib_err l3_init(netwib_io **ppio);
netwib_err l3_init(netwib_io **ppio)
{
  netwib_er(netwib_io_init(NETWIB_FALSE, NETWIB_TRUE, NULL,
                           &l3_read/*read*/, NULL/*write*/,
                           NULL/*wait*/, NULL/*unread*/,
                           NULL/*ctlset*/, NULL/*ctlget*/,
                           NULL/*close*/, ppio));
  return(NETWIB_ERR_OK);
}
/*-------------------------------------------------------------*/
/* l4 reads data, displays it to screen and sends to output */
netwib_err l4_write(netwib_io *pio,
                    netwib_constbuf *pbuf);
netwib_err l4_write(netwib_io *pio,
                    netwib_constbuf *pbuf)
{
  netwib_buf bufbase64;
  netwib_io *pionext;
  netwib_err ret;
  /* obtain the next io in the chain */
  netwib_er(netwib_io_next_write(pio, &pionext));
  /* display it */
  netwib_er(netwib_buf_display(pbuf, NETWIB_ENCODETYPE_DUMP));
  /* write data to the next io */
  ret = netwib_io_write(pionext, pbuf);
  return(ret);
}
netwib_err l4_init(netwib_io **ppio);
netwib_err l4_init(netwib_io **ppio)
{
  netwib_er(netwib_io_init(NETWIB_FALSE, NETWIB_TRUE, NULL,
                           NULL/*read*/, &l4_write,
                           NULL/*wait*/, NULL/*unread*/,
                           NULL/*ctlset*/, NULL/*ctlget*/,
                           NULL/*close*/, ppio));
  return(NETWIB_ERR_OK);
}
/*-------------------------------------------------------------*/
/* l5 convert data to uppercase */
netwib_err l5_up(netwib_constbuf *pinbuf,
                 netwib_buf *poutbuf);
netwib_err l5_up(netwib_constbuf *pinbuf,
                 netwib_buf *poutbuf)
{
  netwib_data data;
  netwib_uint32 datasize, i;
  netwib_byte c;
  data = netwib__buf_ref_data_ptr(pinbuf);
  datasize = netwib__buf_ref_data_size(pinbuf);
  for (i = 0; i < datasize; i++) {
    c = data[i];
    netwib_c2_upper(c);
    netwib_er(netwib_buf_append_byte(c, poutbuf));
  }
  return(NETWIB_ERR_OK);
}
netwib_err l5_read(netwib_io *pio,
                   netwib_buf *pbuf);
netwib_err l5_read(netwib_io *pio,
                   netwib_buf *pbuf)
{
  netwib_buf buf;
  netwib_io *pionext;
  netwib_er(netwib_io_next_read(pio, &pionext));
  netwib_er(netwib_buf_init_mallocdefault(&buf));
  netwib_er(netwib_io_read(pionext, &buf));
  netwib_er(l5_up(&buf, pbuf));
  netwib_er(netwib_buf_close(&buf));
  return(NETWIB_ERR_OK);
}
netwib_err l5_write(netwib_io *pio,
                    netwib_constbuf *pbuf);
netwib_err l5_write(netwib_io *pio,
                    netwib_constbuf *pbuf)
{
  netwib_buf buf;
  netwib_io *pionext;
  netwib_err ret;
  netwib_er(netwib_io_next_write(pio, &pionext));
  netwib_er(netwib_buf_init_mallocdefault(&buf));
  netwib_er(l5_up(pbuf, &buf));
  ret = netwib_io_write(pionext, &buf);
  netwib_er(netwib_buf_close(&buf));
  return(ret);
}
netwib_err l5_init(netwib_io **ppio);
netwib_err l5_init(netwib_io **ppio)
{
  netwib_er(netwib_io_init(NETWIB_FALSE, NETWIB_TRUE, NULL,
                           &l5_read, &l5_write,
                           NULL/*wait*/, NULL/*unread*/,
                           NULL/*ctlset*/, NULL/*ctlget*/,
                           NULL/*close*/, ppio));
  return(NETWIB_ERR_OK);
}
/*-------------------------------------------------------------*/
/* module m */
netwib_err m(netwib_io *pi1,
             netwib_io *po1,
             netwib_io *po2);
netwib_err m(netwib_io *pi1,
             netwib_io *po1,
             netwib_io *po2)
{
  netwib_buf buf;
  netwib_err ret;
  netwib_io *pl1, *pl2;
  netwib_data data;
  netwib_uint32 datasize;
  /* create l1 */
  netwib_er(netwib_io_init_line(&pl1));
  /* create l2 */
  netwib_er(l2_init(&pl2));
  /* add l1 to i1 */
  netwib_er(netwib_io_plug_read(pl1, pi1));
  /* add l2 to o2 */
  netwib_er(netwib_io_plug_read(pl2, po2));
  /* main loop */
  netwib_er(netwib_buf_init_mallocdefault(&buf));
  while (NETWIB_TRUE) {
    netwib__buf_reinit(&buf);
    ret = netwib_io_read(pl1, &buf);
    if (ret == NETWIB_ERR_DATAEND) {
      ret = NETWIB_ERR_OK;
      break;
    } else if (ret != NETWIB_ERR_OK) {
      break;
    }
    data = netwib__buf_ref_data_ptr(&buf);
    datasize = netwib__buf_ref_data_size(&buf);
    if (datasize && data[0] == 'A') {
      ret = netwib_io_write(po1, &buf);
    } else {
      ret = netwib_io_write(pl2, &buf);
    }
    if (ret != NETWIB_ERR_OK) {
      break;
    }
  }
  netwib_er(netwib_buf_close(&buf));
  /* close only l1 and l2 (not the complete chain) */
  netwib_er(netwib_io_close(&pl1));
  netwib_er(netwib_io_close(&pl2));
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 1 */
netwib_err usage1(void);
netwib_err usage1(void)
{
  netwib_err ret;
  netwib_buf filename;
  netwib_io *pfile1, *pfile2, *pfile3, *pl3 , *pl4;
  /* open files */
  netwib_er(netwib_buf_init_ext_string("file1", &filename));
  netwib_er(netwib_io_init_file_read(&filename, &pfile1));
  netwib_er(netwib_buf_init_ext_string("file2", &filename));
  netwib_er(netwib_io_init_file_write(&filename, &pfile2));
  netwib_er(netwib_buf_init_ext_string("file3", &filename));
  netwib_er(netwib_io_init_file_write(&filename, &pfile3));
  /* initialize l3 and l4 */
  netwib_er(l3_init(&pl3));
  netwib_er(l4_init(&pl4));
  /* create chains */
  netwib_er(netwib_io_plug_read(pl3, pfile1));
  netwib_er(netwib_io_plug_write(pl4, pfile3));
  /* core loop */
  ret = m(pl3, pfile2, pl4);
  /* close chains */
  netwib_er(netwib_io_close(&pl3)); /* or close_read */
  netwib_er(netwib_io_close(&pfile2)); /* or close_write */
  netwib_er(netwib_io_close(&pl4)); /* or close_write */
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 2 */
netwib_err usage2(void);
netwib_err usage2(void)
{
  netwib_err ret;
  netwib_io *psock, *pnull;
  netwib_ip ipad;
  /* open socket */
  netwib_er(netwib_ip_init_ip4(0x7F000001, &ipad));
  netwib_er(netwib_io_init_sock_tcp_cli_easy(&ipad, 1234, &psock));
  /* open null */
  netwib_er(netwib_io_init_null(&pnull));
  /* core loop */
  ret = m(psock, pnull, psock);
  /* close chains */
  netwib_er(netwib_io_close(&psock));
  netwib_er(netwib_io_close(&pnull)); /* or close_write */
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 3 */
netwib_err usage3(void);
netwib_err usage3(void)
{
  netwib_err ret;
  netwib_io *psock, *pnull, *pl3 , *pl4;
  netwib_ip ipad;
  /* open socket */
  netwib_er(netwib_ip_init_ip4(0x7F000001, &ipad));
  netwib_er(netwib_io_init_sock_tcp_cli_easy(&ipad, 1234, &psock));
  /* open null */
  netwib_er(netwib_io_init_null(&pnull));
  /* initialize l3 and l4 */
  netwib_er(l3_init(&pl3));
  netwib_er(l4_init(&pl4));
  /* create chains */
  netwib_er(netwib_io_plug_read(pl3, psock));
  netwib_er(netwib_io_plug_write(pl4, psock));
  /* core loop */
  ret = m(pl3, pnull, pl4);
  /* close chains */
  netwib_er(netwib_io_close(&pl3)); /* or close_read */
  netwib_er(netwib_io_close(&pnull)); /* or close_write */
  netwib_er(netwib_io_close(&pl4)); /* or close_write */
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 4 */
netwib_err usage4(void);
netwib_err usage4(void)
{
  netwib_err ret;
  netwib_io *psock, *pnull, *pl5;
  netwib_ip ipad;
  /* open socket */
  netwib_er(netwib_ip_init_ip4(0x7F000001, &ipad));
  netwib_er(netwib_io_init_sock_tcp_cli_easy(&ipad, 1234, &psock));
  /* open null */
  netwib_er(netwib_io_init_null(&pnull));
  /* initialize l5 */
  netwib_er(l5_init(&pl5));
  /* create chains */
  netwib_er(netwib_io_plug_read(pl5, psock));
  netwib_er(netwib_io_plug_write(pl5, psock));
  /* core loop */
  ret = m(pl5, pnull, pl5);
  /* close chains */
  netwib_er(netwib_io_close(&pl5));
  netwib_er(netwib_io_close(&pnull)); /* or close_write */
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 5 */
netwib_err usage5(void);
netwib_err usage5(void)
{
  netwib_err ret;
  netwib_buf filename;
  netwib_io *pfile1, *pfile2, *pnull, *pl5;
  /* open files */
  netwib_er(netwib_buf_init_ext_string("file1", &filename));
  netwib_er(netwib_io_init_file_read(&filename, &pfile1));
  netwib_er(netwib_buf_init_ext_string("file2", &filename));
  netwib_er(netwib_io_init_file_write(&filename, &pfile2));
  /* open null */
  netwib_er(netwib_io_init_null(&pnull));
  /* initialize l5 */
  netwib_er(l5_init(&pl5));
  /* create chains */
  netwib_er(netwib_io_plug_read(pl5, pfile1));
  netwib_er(netwib_io_plug_write(pl5, pfile2));
  /* core loop */
  ret = m(pl5, pnull, pl5);
  /* close chains */
  netwib_er(netwib_io_close(&pl5));
  netwib_er(netwib_io_close(&pnull)); /* or close_write */
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 6 */
netwib_err usage6(void);
netwib_err usage6(void)
{
  netwib_err ret;
  netwib_buf filename;
  netwib_io *pfile1, *pfile2;
  /* open files */
  netwib_er(netwib_buf_init_ext_string("file1", &filename));
  netwib_er(netwib_io_init_file_read(&filename, &pfile1));
  netwib_er(netwib_buf_init_ext_string("file2", &filename));
  netwib_er(netwib_io_init_file_write(&filename, &pfile2));
  /* core loop */
  ret = m(pfile1, pfile2, pfile2);
  /* close chains */
  netwib_er(netwib_io_close(&pfile1));
  netwib_er(netwib_io_close(&pfile2));
  return(ret);
}
/*-------------------------------------------------------------*/
/* usage 7 */
netwib_err usage7(void);
netwib_err m2(netwib_io *pi1,
              netwib_io *pi2,
              netwib_io *po1);
netwib_err usage7(void)
{
  netwib_err ret;
  netwib_buf filename;
  netwib_io *pfile1, *pnull;
  /* open files */
  netwib_er(netwib_buf_init_ext_string("file1", &filename));
  netwib_er(netwib_io_init_file_read(&filename, &pfile1));
  /* open null */
  netwib_er(netwib_io_init_null(&pnull));
  /* core loop */
  ret = m2(pfile1, pfile1, pnull);
  /* close chains */
  netwib_er(netwib_io_close(&pfile1));
  netwib_er(netwib_io_close(&pnull));
  return(ret);
}
#endif

MODULE IONEW
/*-------------------------------------------------------------*/
/***************************************************************
 * Functions herein allow to create a new netwib_io.           *
 ***************************************************************/
/*-------------------------------------------------------------*/
/***************************************************************
 * Following functions can return :                            *
 *  - NETWIB_ERR_OK : the job was done (by the io or a next in *
 *                    the chain)                               *
 *  - NETWIB_ERR_PLEASETRYNEXT : the io doesn't know how to do *
 *                               what was requested, so please *
 *                               try next                      *
 *  - NETWIB_ERR_PLEASECONSTRUCT : if way is                   *
 *                                 NETWIB_IO_WAYTYPE_RDWR or   *
 *                                _SUPPORTED, the library has  *
 *                                to do the task using _READ   *
 *                                and _WRITE                   *
 *  - NETWIB_ERR_PLEASELOOPTIME : there is no event, so please *
 *                                loop to reach abstime        *
 ***************************************************************/
/* Function called when netwib_io_read is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
*/
typedef netwib_err (*netwib_io_read_pf)(netwib_io *pio,
                                        netwib_buf *pbuf);
/* Function called when netwib_io_write is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
*/
typedef netwib_err (*netwib_io_write_pf)(netwib_io *pio,
                                         netwib_constbuf *pbuf);
/* Function called when netwib_io_wait is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
     NETWIB_ERR_PLEASECONSTRUCT
     NETWIB_ERR_PLEASELOOPTIME
*/
typedef netwib_err (*netwib_io_wait_pf)(netwib_io *pio,
                                        netwib_io_waytype way,
                                        netwib_consttime *pabstime,
                                        netwib_bool *pevent);
/* Function called when netwib_io_unread is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
*/
typedef netwib_err (*netwib_io_unread_pf)(netwib_io *pio,
                                          netwib_constbuf *pbuf);
/* Function called when netwib_io_ctl_set is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
     NETWIB_ERR_PLEASECONSTRUCT
*/
typedef netwib_err (*netwib_io_ctl_set_pf)(netwib_io *pio,
                                           netwib_io_waytype way,
                                           netwib_io_ctltype ctltype,
                                           netwib_ptr p,
                                           netwib_uint32 ui);
/* Function called when netwib_io_ctl_get is called on the io
   This function should return :
     NETWIB_ERR_OK
     NETWIB_ERR_PLEASETRYNEXT
     NETWIB_ERR_PLEASECONSTRUCT
*/
typedef netwib_err (*netwib_io_ctl_get_pf)(netwib_io *pio,
                                           netwib_io_waytype way,
                                           netwib_io_ctltype ctltype,
                                           netwib_ptr p,
                                           netwib_uint32 *pui);
/* Function called when netwib_io_close is called on the io
   This function should return :
     NETWIB_ERR_OK
*/
typedef netwib_err (*netwib_io_close_pf)(netwib_io *pio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init
   Description :
     Create a user defined netwib_io.
   Input parameter(s) :
     readsupported : read is supported
     writesupported : write is supported
     pcommon : common data which can be shared between functions
     pfx : functions or NULL if not needed
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init(netwib_bool readsupported,
                          netwib_bool writesupported,
                          netwib_ptr pcommon,
                          netwib_io_read_pf pfread,
                          netwib_io_write_pf pfwrite,
                          netwib_io_wait_pf pfwait,
                          netwib_io_unread_pf pfunread,
                          netwib_io_ctl_set_pf pfctl_set,
                          netwib_io_ctl_get_pf pfctl_get,
                          netwib_io_close_pf pfclose,
                          netwib_io **ppio);
/*-------------------------------------------------------------*/
/***************************************************************
 * Those structure definitions should only be used in functions*
 * for netwib_io_init.                                         *
 ***************************************************************/
typedef struct {
  netwib_io *pnext; /* next io in the chain */
  netwib_bool supported; /* true if way is supported */
  netwib_uint32 numusers; /* number of io using this one */
} netwib_io_way_t;
struct netwib_io {
  netwib_io_way_t rd; /* read information */
  netwib_io_way_t wr; /* write information */
  netwib_ptr pcommon; /* pointer used in netwib_io_init */
  netwib_io_write_pf pfwrite;
  netwib_io_read_pf pfread;
  netwib_io_unread_pf pfunread;
  netwib_io_wait_pf pfwait;
  netwib_io_ctl_set_pf pfctl_set;
  netwib_io_ctl_get_pf pfctl_get;
  netwib_io_close_pf pfclose;
};
/*-------------------------------------------------------------*/
/***************************************************************
 * Previous structure is useful to do simple things. But,      *
 * it's complicated to deal with several netwib_io_waytype.    *
 * Those defines can be used :                                 *
 *  - to work on "pnext", use netwib_io_next (in io.h)         *
 *  - to work on "supported", use netwib_io_ctl_s/get_support  *
 *  - to work on "numusers", use netwib_io_ctl_s/get_numusers  *
 ***************************************************************/
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_bool yes); */
#define netwib_io_ctl_set_support(pio,way,yes) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_SUPPORT,NULL,(netwib_uint32)yes)
#define netwib_io_ctl_get_support(pio,way,pyes) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_SUPPORT,NULL,(netwib_uint32*)pyes)
/* netwib_err f(netwib_io *pio,netwib_io_waytype way,netwib_uint32 numusers);*/
#define netwib_io_ctl_set_numusers(pio,way,numusers) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_NUMUSERS,NULL,numusers)
#define netwib_io_ctl_get_numusers(pio,way,pnumusers) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_NUMUSERS,NULL,pnumusers)
/* only increment or decrement */
#define netwib_io_ctl_set_numusers_inc(pio,way) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_NUMUSERSINC,NULL,+1)
#define netwib_io_ctl_set_numusers_dec(pio,way) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_NUMUSERSINC,NULL,(netwib_uint32)-1)

MODULE IOUSUAL
/*-------------------------------------------------------------*/
/***************************************************************
 * Functions herein are examples of frequently needed          *
 * netwib_io.                                                  *
 ***************************************************************/
/*-------------------------------------------------------------*/
/***************************************************************
 *                           FINAL LINKS                       *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_null
   Description :
     Create an io junking data and giving nothing.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_null(netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_mem
   Description :
     Create an io storing and reading data from memory.
   Input parameter(s) :
     pbufread : buffer where data is read
     pbufwrite : buffer where data is written
     *plockbufread : lock used when another thread want to
                     access pbufread
     *plockbufwrite : lock used when another thread want to
                      access pbufwrite
     closebufsatend : if the buffers are closed when the io
                      is closed (in locked version, this also
                      close rwlocks)
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_mem(netwib_buf *pbufread,
                              netwib_buf *pbufwrite,
                              netwib_bool closebufsatend,
                              netwib_io **ppio);
netwib_err netwib_io_init_mem_lock(netwib_thread_rwlock *plockbufread,
                                   netwib_buf *pbufread,
                                   netwib_thread_rwlock *plockbufwrite,
                                   netwib_buf *pbufwrite,
                                   netwib_bool closebufsatend,
                                   netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_tlv
   Description :
     Create an io storing and reading data from memory.
   Input parameter(s) :
     pbufread : buffer where data is read
     pbufwrite : buffer where data is written
     *plockbufread : lock used when another thread want to
                     access pbufread
     *plockbufwrite : lock used when another thread want to
                      access pbufwrite
     closebufsatend : if the buffers are closed when the io
                      is closed (in locked version, this also
                      close rwlocks)
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
   Note :
     If canslide is set on pbufread or pbufwrite, it will be
     faster.
*/
netwib_err netwib_io_init_tlv(netwib_buf *pbufread,
                              netwib_buf *pbufwrite,
                              netwib_bool closebufsatend,
                              netwib_io **ppio);
netwib_err netwib_io_init_tlv_lock(netwib_thread_rwlock *plockbufread,
                                   netwib_buf *pbufread,
                                   netwib_thread_rwlock *plockbufwrite,
                                   netwib_buf *pbufwrite,
                                   netwib_bool closebufsatend,
                                   netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_exec
   Description :
     Create an io redirecting read and write requests to
     a sub process.
   Input parameter(s) :
     pbufcommand : command (for example "/bin/ls /")
     providedway : if user will read or write from the io
     killonclose : if true, a close kills the process
     pexitednormally : address of a boolean which will receive :
                        - NETWIB_TRUE : if program exited normally
                        - NETWIB_FALSE : else
                       if NULL, do not set it
     preturnedvalue : address of a uint32 which will receive
                      value returned by the program
                      if NULL, do not set it
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
   Example 1 :
     /bin/ls a b "c"
    corresponds to :
     filename = /bin/ls
     argv[0] = ls
     argv[1] = a
     argv[2] = b
     argv[3] = c
   Example 2 :
     ls "a \"'\t\\a\x41"
    corresponds to :
     filename = ls
     argv[0] = ls
     argv[1] = a "'_tabulation_\a_0x41_
     argv[3] = NULL
    Note : \ sequences recognized inside "" are : abtnr
*/
netwib_err netwib_io_init_exec(netwib_constbuf *pbufcommand,
                               netwib_io_waytype providedway,
                               netwib_bool killonclose,
                               netwib_bool *pexitednormally,
                               netwib_uint32 *preturnedvalue,
                               netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_shellserver
   Description :
     Create an io redirecting read and write requests to
     a shell.
     It should be used with netwib_io_init_shellclient.
     IMPORTANT: It is currently only implemented for Linux.
   Input parameter(s) :
     uid : requested user id
     *pbufterm : TERM environment variable
     *pbufpath : PATH environment variable
     killonclose : if true, a close kills the process
     pexitednormally : address of a boolean which will receive :
                        - NETWIB_TRUE : if program exited normally
                        - NETWIB_FALSE : else
                       if NULL, do not set it
     preturnedvalue : address of a uint32 which will receive
                      value returned by the last command executed
                      in the shell
                      if NULL, do not set it
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_LONOTIMPLEMENTED : not on Linux
*/
netwib_err netwib_io_init_shellserver(netwib_uint32 uid,
                                      netwib_constbuf *pbufterm,
                                      netwib_bool killonclose,
                                      netwib_bool *pexitednormally,
                                      netwib_uint32 *preturnedvalue,
                                      netwib_io **ppio);
#define NETWIB_IO_INIT_SHELLSERVER_UID_NONE 0xFFFFFFFFu
#define NETWIB_IO_INIT_SHELLSERVER_TERM_NONE NULL
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_shellclient
   Description :
     Create an io redirecting read and write requests to
     a console.
     It should be used with netwib_io_init_shellserver.
     IMPORTANT: It is currently only implemented for Linux.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_LONOTIMPLEMENTED : not on Linux
*/
netwib_err netwib_io_init_shellclient(netwib_io **ppio);
/* to obtain term for netwib_io_init_shellserver() */
netwib_err netwib_shellclient_term(netwib_bufext *pbufterm);
/*-------------------------------------------------------------*/
/***************************************************************
 *                       INTERMEDIARY LINKS                    *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_data
   Description :
     Create several type of io. For example line io can be used
     like this to read line by line :
       netwib_er(netwib_io_init_file_read("/tmp/f", &pio));
       netwib_er(netwib_io_init_data_line(&pioline));
       netwib_er(netwib_io_plug_read(&pioline, &pio));
       netwib_er(netwib_io_read(&pioline, &b));
       etc.
       netwib_er(netwib_io_close_read(&pioline);
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
typedef enum {
  NETWIB_IO_INIT_DATA_TYPE_LINE = 1,
  NETWIB_IO_INIT_DATA_TYPE_CHUNK,
  NETWIB_IO_INIT_DATA_TYPE_FIXED,
  NETWIB_IO_INIT_DATA_TYPE_TRANSPARENT
} netwib_io_init_data_type;
netwib_err netwib_io_init_data(netwib_io_init_data_type rdtype,
                               netwib_io_init_data_type wrtype,
                               netwib_io **ppio);
/*-------------------------------------------------------------*/
/* read/write line by line */
#define netwib_io_init_data_line(ppio) netwib_io_init_data(NETWIB_IO_INIT_DATA_TYPE_LINE,NETWIB_IO_INIT_DATA_TYPE_LINE,ppio)
/* If write writes '\r\n'(true) or '\n'(false) */
/* netwib_err f(netwib_io *pio, netwib_bool add_r); */
#define netwib_io_ctl_set_data_line_msdos(pio,add_r) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_WRITE,NETWIB_IO_CTLTYPE_DATA_LINE_MSDOS,NULL,add_r)
#define netwib_io_ctl_get_data_line_msdos(pio,padd_r) netwib_io_ctl_get(pio,NETWIB_IO_WAYTYPE_WRITE,NETWIB_IO_CTLTYPE_DATA_LINE_MSDOS,NULL,padd_r)
/*-------------------------------------------------------------*/
/* read/write a chunk of data */
/* note : when end is reached, last returned chunk might be smaller */
#define netwib_io_init_data_chunk(ppio) netwib_io_init_data(NETWIB_IO_INIT_DATA_TYPE_CHUNK,NETWIB_IO_INIT_DATA_TYPE_CHUNK,ppio)
/* To change size of read/written data : between minsize and maxsize */
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_uint32 size); */
#define netwib_io_ctl_set_data_chunk_minsize(pio,way,minsize) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_DATA_CHUNK_MINSIZE,NULL,minsize)
#define netwib_io_ctl_set_data_chunk_maxsize(pio,way,maxsize) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_DATA_CHUNK_MAXSIZE,NULL,maxsize)
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_uint32 *psize); */
#define netwib_io_ctl_get_data_chunk_minsize(pio,way,pminsize) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_DATA_CHUNK_MINSIZE,NULL,pminsize)
#define netwib_io_ctl_get_data_chunk_maxsize(pio,way,pmaxsize) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_DATA_CHUNK_MAXSIZE,NULL,pmaxsize)
/*-------------------------------------------------------------*/
/* read/write fixed size of data */
/* note : when end is reached, last returned data might be smaller */
#define netwib_io_init_data_fixed(ppio) netwib_io_init_data(NETWIB_IO_INIT_DATA_TYPE_FIXED,NETWIB_IO_INIT_DATA_TYPE_FIXED,ppio)
/* To change size of read data. */
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_uint32 size); */
#define netwib_io_ctl_set_data_fixed_size(pio,way,size) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_DATA_FIXED_SIZE,NULL,size)
/* netwib_err f(netwib_io *pio, netwib_io_waytype way, netwib_uint32 *psize); */
#define netwib_io_ctl_get_data_fixed_size(pio,way,psize) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_DATA_FIXED_SIZE,NULL,psize)
/*-------------------------------------------------------------*/
/* transparent : does nothing */
#define netwib_io_init_data_transparent(ppio) netwib_io_init_data(NETWIB_IO_INIT_DATA_TYPE_TRANSPARENT,NETWIB_IO_INIT_DATA_TYPE_TRANSPARENT,ppio)
/*-------------------------------------------------------------*/
/* To change io type */
/* netwib_err f(netwib_io *pio, netwib_io_init_data_type type); */
#define netwib_io_ctl_set_data_type(pio,way,type) netwib_io_ctl_set(pio,way,NETWIB_IO_CTLTYPE_DATA_TYPE,NULL,type)
/* netwib_err f(netwib_io *pio, netwib_io_init_data_type *ptype); */
#define netwib_io_ctl_get_data_type(pio,way,ptype) netwib_io_ctl_get(pio,way,NETWIB_IO_CTLTYPE_DATA_TYPE,NULL,ptype)
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_storage
   Description :
     Create an io buffering data. It can be plugged in front
     of low level io not supporting unread for example.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_storage(netwib_io **ppio);
#define netwib_io_ctl_set_storage_flush(pio) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_STORAGE_FLUSH,NULL,0)
/*-------------------------------------------------------------*/
/***************************************************************
 *                         MULTIPLEX LINKS                     *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_rdwr
   Description :
     Create an io redirecting read an write requests to two
     distinct io.
   Input parameter(s) :
     preadio : io where data is read
     pwriteio : io where data is written
     closeiosatend : if the io are closed when the io
                     is closed
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_rdwr(netwib_io *preadio,
                               netwib_io *pwriteio,
                               netwib_bool closeiosatend,
                               netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_tee
   Description :
     Write data to 2 io.
     Read data from 2 io.
   Input parameter(s) :
     pio1 : first io where data is read/written
     pio2 : second io where data is read/written
     closeiosatend : if pio1/pio2 are closed when the io
                     is closed
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_tee(netwib_io *pio1,
                              netwib_io *pio2,
                              netwib_bool closeiosatend,
                              netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_debug
   Description :
     Display information for each request.
   Input parameter(s) :
     pnormalio : io where normal data is read/written
     pdebugio : io where debugging data is written
     closeiosatend : if io are closed when the io
                     is closed
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_debug(netwib_io *pnormalio,
                                netwib_io *pdebugio,
                                netwib_bool closeiosatend,
                                netwib_io **ppio);

MODULE WAIT
/*-------------------------------------------------------------*/
/***************************************************************
 * A netwib_wait permits to wait for an event during a user    *
 * defined duration.                                           *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef struct netwib_wait netwib_wait;
/*-------------------------------------------------------------*/
/* Name : netwib_wait_init
   Description :
     Initialize a netwib_wait : wait for an event decided by a
     function.
   Input parameter(s) :
     pfuncevent : memory address of the function which will
                  be called to check for an event
                  For each call, the first parameter ('infos')
                  will be set with the optional parameter below.
     pfuncclose : optional parameter (can be NULL) which
                  contain the function to call to free
                  resources allocated by infos (when
                  netwib_wait_close will be called)
   Input/output parameter(s) :
     infos : optional parameter (can be NULL) which will be
             used as the first parameter for *pfunc.
             This may be used to send information to *pfunc.
   Output parameter(s) :
     **ppwait : netwib_wait associated to function
   Normal return values :
     NETWIB_ERR_OK : ok
*/
typedef netwib_err (*netwib_wait_event_pf)(netwib_ptr infos,
                                           netwib_consttime *pabstime,
                                           netwib_bool *pevent);
typedef netwib_err (*netwib_wait_close_pf)(netwib_ptr infos);
netwib_err netwib_wait_init(netwib_wait_event_pf pfuncevent,
                            netwib_ptr infos,
                            netwib_wait_close_pf pfuncclose,
                            netwib_wait **ppwait);
/*-------------------------------------------------------------*/
/* Name : netwib_wait_close
   Description :
     Close a netwib_wait.
   Input parameter(s) :
   Input/output parameter(s) :
     **ppwait : netwib_wait to close
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_close(netwib_wait **ppwait);
/*-------------------------------------------------------------*/
/* Name : netwib_wait_init_io
   Description :
     Initialize a netwib_wait : wait for data from the netwib_io.
   Input parameter(s) :
     *pio : netwib_io where to wait for data
   Input/output parameter(s) :
   Output parameter(s) :
     **ppwait : netwib_wait associated to *pio
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_init_io(netwib_io *pio,
                               netwib_io_waytype way,
                               netwib_wait **ppwait);
/* netwib_err f(netwib_io *pio, netwib_wait **ppwait); */
#define netwib_wait_init_io_read(pio,ppwait) netwib_wait_init_io(pio,NETWIB_IO_WAYTYPE_READ,ppwait)
#define netwib_wait_init_io_write(pio,ppwait) netwib_wait_init_io(pio,NETWIB_IO_WAYTYPE_WRITE,ppwait)
#define netwib_wait_init_io_rdwr(pio,ppwait) netwib_wait_init_io(pio,NETWIB_IO_WAYTYPE_RDWR,ppwait)
/*-------------------------------------------------------------*/
/* Name : netwib_wait_init_thread_end
   Description :
     Initialize a netwib_wait : wait for the end of a thread.
   Input parameter(s) :
     *pthread : thread to wait for
   Input/output parameter(s) :
     preturnederror : address of a variable which will contain
                      returned error
     pinfosout : address of a variable which will contain
                 output information
   Output parameter(s) :
     *ppwait : netwib_wait associated to *pthread
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_init_thread_end(netwib_thread *pthread,
                                       netwib_err *preturnederror,
                                       netwib_ptr *pinfosout,
                                       netwib_wait **ppwait);
/*-------------------------------------------------------------*/
/* Name : netwib_wait_init_thread_cond
   Description :
     Initialize a netwib_wait : wait for a condition
   Input parameter(s) :
     *pcond : condition to wait for
   Input/output parameter(s) :
     *pvalue : address of a variable which will contain
               condition value
   Output parameter(s) :
     *ppwait : netwib_wait associated to *pcond
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_init_thread_cond(netwib_thread_cond *pcond,
                                        netwib_uint32 *pvalue,
                                        netwib_wait **ppwait);
/*-------------------------------------------------------------*/
/* Name : netwib_wait_wait1
   Description :
     Wait for 1 event.
   Input parameter(s) :
     *pwait : netwib_wait to wait for
     *pabstime : end time
   Input/output parameter(s) :
   Output parameter(s) :
     *pevent : an event occurred on *pwait. If *pabstime is
               reached *pevent is set to NETWIB_FALSE.
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_wait1(netwib_wait *pwait,
                             netwib_consttime *pabstime,
                             netwib_bool *pevent);
/*-------------------------------------------------------------*/
/* Name : netwib_wait_wait5
   Description :
     Wait for 1 event amongst 5 netwib_wait.
   Input parameter(s) :
     *pwait1..5 : netwib_wait to wait for
     *pabstime : end time
   Input/output parameter(s) :
   Output parameter(s) :
     *pevent1..5 : an event occurred on *pwait1..5
                   If abstime is reached *pevent is set
                   to NETWIB_FALSE.
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_wait_wait5(netwib_wait *pwait1,
                             netwib_wait *pwait2,
                             netwib_wait *pwait3,
                             netwib_wait *pwait4,
                             netwib_wait *pwait5,
                             netwib_consttime *pabstime,
                             netwib_bool *pevent1,
                             netwib_bool *pevent2,
                             netwib_bool *pevent3,
                             netwib_bool *pevent4,
                             netwib_bool *pevent5);
#define netwib_wait_wait4(pwait1,pwait2,pwait3,pwait4,pabstime,pevent1,pevent2,pevent3,pevent4) netwib_wait_wait5(pwait1,pwait2,pwait3,pwait4,NULL,pabstime,pevent1,pevent2,pevent3,pevent4,NULL)
#define netwib_wait_wait3(pwait1,pwait2,pwait3,pabstime,pevent1,pevent2,pevent3) netwib_wait_wait5(pwait1,pwait2,pwait3,NULL,NULL,pabstime,pevent1,pevent2,pevent3,NULL,NULL)
#define netwib_wait_wait2(pwait1,pwait2,pabstime,pevent1,pevent2) netwib_wait_wait5(pwait1,pwait2,NULL,NULL,NULL,pabstime,pevent1,pevent2,NULL,NULL,NULL)

MODULE WAITLIST
/*-------------------------------------------------------------*/
typedef struct {
  netwib_wait *pwait;
  netwib_uint32 waitident; /* because waitid exists */
} netwib_waitringitem;
/*-------------------------------------------------------------*/
/* Name : netwib_waitlist_init
   Description :
     Initialize a list of events. It can be use to wait for more
     than 5 event (otherwise use netwib_wait_wait5) which is
     easier.
   Input parameter(s) :
   Input/output parameter(s) :
     **ppring : ring initialized
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_waitlist_init(netwib_ring **ppring);
/*-------------------------------------------------------------*/
/* Name : netwib_waitlist_add
   Description :
     Add an event to the waiting ring.
   Input parameter(s) :
     waitident : id of the item to add (any value chosen by user)
     *pwait : netwib_wait to add
   Input/output parameter(s) :
     *pring : ring where to add items
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_waitlist_add(netwib_ring *pring,
                               netwib_wait *pwait,
                               netwib_uint32 waitident);
/*-------------------------------------------------------------*/
/* Name : netwib_waitlist_del
   Description :
     Remove an event to the waiting ring.
   Input parameter(s) :
     waitident : id of the item to remove
   Input/output parameter(s) :
     *pring : ring where to remove items
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_waitlist_del(netwib_ring *pring,
                               netwib_uint32 waitident);
/*-------------------------------------------------------------*/
/* Name : netwib_waitlist_wait
   Description :
     Wait for an event in the waiting ring. The netwib_wait
     is never closed by this function (different behavior
     compared to netwib_threadlist_wait).
   Input parameter(s) :
     *pabstime : end time
   Input/output parameter(s) :
     *pring : ring where to wait for
   Output parameter(s) :
     *pevent : true if an event occurred. If *pabstime is
               reached *pevent is set to NETWIB_FALSE.
     *pringofwaitid : ring of all events id
                      This ring contains netwib_uintptr
                      cast-ed to netwib_ptr. This ring is
                      initialized only when there is an event.
                      It's user's job to close this ring with :
                  netwib_ring_close(ppringofwaitid, NETWIB_FALSE)
   Normal return values :
     NETWIB_ERR_OK : ok
     NETWIB_ERR_DATAEND: ring is empty
*/
netwib_err netwib_waitlist_wait(netwib_ring *pring,
                                netwib_consttime *pabstime,
                                netwib_bool *pevent,
                                netwib_ring **ppringofwaitid);
#define netwib_waitlist_waitident_init_ptr(p) ((netwib_uint32)(netwib_uintptr)(p))
/*-------------------------------------------------------------*/
/***************************************************************
 * For other functions, you can directly use functions of      *
 * ring.h.                                                     *
 * To do so, booleans "eraseitems" and "duplicateitems" have   *
 * be set to NETWIB_TRUE. See netwib_waitlist_close for        *
 * example.                                                    *
 ***************************************************************/
#define netwib_waitlist_close(ppring) netwib_ring_close(ppring,NETWIB_TRUE)

MODULE FILE
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_FILE_INITTYPE_READ = 1,    /* open the file for reading */
  NETWIB_FILE_INITTYPE_WRITE,       /* open the file for writing */
  NETWIB_FILE_INITTYPE_APPEND,      /* open the file for appending */
  NETWIB_FILE_INITTYPE_RDWR         /* open the file for reading and writing */
} netwib_file_inittype;
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_file
   Description :
     Open a file.
   Input parameter(s) :
     *pfilename : file name
     textmode : (useful under Windows and ignored under Unix)
                if file has to be opened in text mode ("\n" are
                converted to "\r\n" for output; "\r\n" are
                converted to "\n" for input)
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_file(netwib_constbuf *pfilename,
                               netwib_file_inittype type,
                               netwib_bool textmode,
                               netwib_io **ppio);
#define netwib_io_init_file_read(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_READ,NETWIB_FALSE,ppio)
#define netwib_io_init_file_write(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_WRITE,NETWIB_FALSE,ppio)
#define netwib_io_init_file_append(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_APPEND,NETWIB_FALSE,ppio)
#define netwib_io_init_file_rdwr(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_RDWR,NETWIB_FALSE,ppio)
#define netwib_io_init_file_textread(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_READ,NETWIB_TRUE,ppio)
#define netwib_io_init_file_textwrite(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_WRITE,NETWIB_TRUE,ppio)
#define netwib_io_init_file_textappend(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_APPEND,NETWIB_TRUE,ppio)
#define netwib_io_init_file_textrdwr(filename,ppio) netwib_io_init_file(filename,NETWIB_FILE_INITTYPE_RDWR,NETWIB_TRUE,ppio)
/*-------------------------------------------------------------*/
/* set current position from beginning of file */
/* netwib_err f(netwib_io *pio, netwib_int32 pos); */
#define netwib_file_ctl_set_seek_begin(pio,pos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_BEGIN,NULL,(netwib_uint32)pos)
/* netwib_err f(netwib_io *pio, const netwib_int64 *ppos); */
#define netwib_file_ctl_set_seek64_begin(pio,ppos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_BEGIN,ppos,0)
/*-------------------------------------------------------------*/
/* set current position from current position of file */
/* netwib_err f(netwib_io *pio, netwib_int32 pos); */
#define netwib_file_ctl_set_seek_current(pio,pos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_CURRENT,NULL,(netwib_uint32)pos)
/* netwib_err f(netwib_io *pio, const netwib_int64 *ppos); */
#define netwib_file_ctl_set_seek64_current(pio,ppos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_CURRENT,ppos,0)
/*-------------------------------------------------------------*/
/* set current position from end of file */
/* netwib_err f(netwib_io *pio, netwib_int32 pos); */
#define netwib_file_ctl_set_seek_end(pio,pos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_END,NULL,(netwib_uint32)pos)
/* netwib_err f(netwib_io *pio, const netwib_int64 *ppos); */
#define netwib_file_ctl_set_seek64_end(pio,ppos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_SEEK_END,ppos,0)
/*-------------------------------------------------------------*/
/* get current position from beginning of file */
/* netwib_err f(netwib_io *pio, netwib_int32 *ppos); */
#define netwib_file_ctl_get_tell(pio,ppos) netwib_io_ctl_get(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_TELL,NULL,(netwib_uint32*)ppos)
/* netwib_err f(netwib_io *pio, netwib_int64 *ppos); */
#define netwib_file_ctl_get_tell64(pio,ppos) netwib_io_ctl_get(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_TELL,ppos,NULL)
/*-------------------------------------------------------------*/
/* truncate file to indicated size */
/* netwib_err f(netwib_io *pio, netwib_int32 pos); */
#define netwib_file_ctl_set_truncate(pio,pos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_TRUNCATE,NULL,(netwib_uint32)pos)
/* netwib_err f(netwib_io *pio, const netwib_int64 *ppos); */
#define netwib_file_ctl_set_truncate64(pio,ppos) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_SUPPORTED,NETWIB_IO_CTLTYPE_FILE_TRUNCATE,ppos,0)
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_filetemp
   Description :
     Open a temporary file, and give back the chosen file name.
   Input parameter(s) :
     textmode : (useful under Windows and ignored under Unix)
                if file has to be opened in text mode ("\n" are
                converted to "\r\n")
   Input/output parameter(s) :
     *pfilename : file name
                  If its size is 0, choose a filename in
                  system's temporary directory.
                  If it contains something, append 6 random
                  characters to create the file name. So, it must
                  end with '/' to be interpreted as a directory.
                  The chosen filename is set in this variable.
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_filetemp(netwib_bool textmode,
                                   netwib_buf *pfilename,
                                   netwib_io **ppio);

MODULE FD
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_fd
   Description :
     Open a file descriptor.
   Input parameter(s) :
     fd : file descriptor
   Input/output parameter(s) :
     closefdatend : if fd have to be closed when the io is
                    closed
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_fd(int fd,
                             netwib_bool closefdatend,
                             netwib_io **ppio);

MODULE STREAM
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_stream
   Description :
     Open a file descriptor.
   Input parameter(s) :
     pfile : stream
   Input/output parameter(s) :
     closefileatend : if pfile have to be closed when the io is
                      closed
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_stream(NETWIBFILE *pfile,
                                 netwib_bool closefileatend,
                                 netwib_io **ppio);

MODULE KBD
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_kbd_xyz
   Description :
     Open the keyboard. Its default state is to echo pressed
     keys and to read line by line.
   Input parameter(s) :
     fd : file descriptor to eventually use
     h : HANDLE to eventually use
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_kbddefault(netwib_io **ppio);
netwib_err netwib_io_init_kbd_fd(int fd,
                                 netwib_io **ppio);
netwib_err netwib_io_init_kbd_handle(NETWIBHANDLE h,
                                     netwib_io **ppio);
/*-------------------------------------------------------------*/
/* decides if pressed keys have to be displayed */
/* netwib_err f(netwib_io *pio, netwib_bool b); */
#define netwib_kbd_ctl_set_echo(pio,b) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_READ,NETWIB_IO_CTLTYPE_KBD_ECHO,NULL,b)
/* netwib_err f(netwib_io *pio, netwib_bool *pb); */
#define netwib_kbd_ctl_get_echo(pio,pb) netwib_io_ctl_get(pio,NETWIB_IO_WAYTYPE_READ,NETWIB_IO_CTLTYPE_KBD_ECHO,NULL,pb)
/* decides if we read line by line or char by char */
/* netwib_err f(netwib_io *pio, netwib_bool b); */
#define netwib_kbd_ctl_set_line(pio,b) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_READ,NETWIB_IO_CTLTYPE_KBD_LINE,NULL,b)
/* netwib_err f(netwib_io *pio, netwib_bool *pb); */
#define netwib_kbd_ctl_get_line(pio,pb) netwib_io_ctl_get(pio,NETWIB_IO_WAYTYPE_READ,NETWIB_IO_CTLTYPE_KBD_LINE,NULL,pb)
/* purge pressed characters not yet read */
/* netwib_err f(netwib_io *pio); */
#define netwib_kbd_ctl_set_purge(pio) netwib_io_ctl_set(pio,NETWIB_IO_WAYTYPE_READ,NETWIB_IO_CTLTYPE_KBD_PURGE,NULL,0)

MODULE KBDCHAR
/*-------------------------------------------------------------*/
/* Name : netwib_char_init_kbd
   Description :
     Ask user to enter a character
   Input parameter(s) :
     *pmessage : message to print before
     *pallowedchar : string containing allowed characters
                     For example : "aAbBrR"
                     If NULL all char are allowed
     defaultchar : default character (0 means no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pchar : character chosen
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_char_init_kbd(netwib_constbuf *pmessage,
                                netwib_constbuf *pallowedchars,
                                netwib_char defaultchar,
                                netwib_char *pchar);
#define NETWIB_CHAR_INIT_KBD_NODEF 0

MODULE KBDINT
/*-------------------------------------------------------------*/
/* Name : netwib_uint32_init_kbd
   Description :
     Ask user to enter an integer.
   Input parameter(s) :
     *pmessage : message to print before
     min : minvalue which can be entered (if 0 no min)
     max : maxvalue which can be entered (if 0xFFFFFFFFu no max)
     defaultnumber : default number (if 0xFFFFFFFFu no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pnumber : number chosen
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_uint32_init_kbd(netwib_constbuf *pmessage,
                                  netwib_uint32 min,
                                  netwib_uint32 max,
                                  netwib_uint32 defaultnumber,
                                  netwib_uint32 *pnumber);
#define NETWIB_UINT32_INIT_KBD_NOMIN 0
#define NETWIB_UINT32_INIT_KBD_NOMAX 0xFFFFFFFFu
#define NETWIB_UINT32_INIT_KBD_NODEF 0xFFFFFFFFu
netwib_err netwib_uint64_init_kbd(netwib_constbuf *pmessage,
                                  netwib_uint64 defaultnumber,
                                  netwib_uint64 *pnumber);
/*-------------------------------------------------------------*/
/* Name : netwib_int32_init_kbd
   Description :
     Ask user to enter an integer.
   Input parameter(s) :
     *pmessage : message to print before
     min : minvalue which can be entered (if -0x80000000 no min)
     max : maxvalue which can be entered (if 0x7FFFFFFF no max)
     defaultnumber : default number (if 0x7FFFFFFF no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pnumber : number chosen
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_int32_init_kbd(netwib_constbuf *pmessage,
                                 netwib_int32 min,
                                 netwib_int32 max,
                                 netwib_int32 defaultnumber,
                                 netwib_int32 *pnumber);
#define NETWIB_INT32_INIT_KBD_NOMIN (-0x7FFFFFFF-1)
#define NETWIB_INT32_INIT_KBD_NOMAX 0x7FFFFFFF
#define NETWIB_INT32_INIT_KBD_NODEF 0x7FFFFFFF
netwib_err netwib_int64_init_kbd(netwib_constbuf *pmessage,
                                 netwib_int64 defaultnumber,
                                 netwib_int64 *pnumber);

MODULE KBDBUF
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_kbd
   Description :
     Ask user to enter a text on keyboard.
   Input parameter(s) :
     *pmessage : message to print before asking user
     *pdefaultext : text string to use if user enters nothing
                    if NULL, there is no default
   Input/output parameter(s) :
   Output parameter(s) :
     pbuf : output buffer set with the text
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_kbd(netwib_constbuf *pmessage,
                                 netwib_constbuf *pdefaulttext,
                                 netwib_buf *pbuf);
#define NETWIB_BUF_APPEND_KBD_NODEF NULL
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_password
   Description :
     Ask user to enter a password on keyboard.
   Input parameter(s) :
     *pmessage : message to print before asking user
     *pdefaultext : text string to use if user enters nothing
   Input/output parameter(s) :
   Output parameter(s) :
     pbuf : output buffer set with the text
   Normal return values :
     NETWIB_ERR_OK : ok
   This function sets NETWIB_BUF_FLAGS_SENSITIVE.
*/
netwib_err netwib_buf_append_password(netwib_constbuf *pmessage,
                                      netwib_constbuf *pdefaulttext,
                                      netwib_buf *pbuf);

MODULE KBDPRESS
/*-------------------------------------------------------------*/
/* Name : netwib_kbd_press
   Description :
     Ask user to press a key
   Input parameter(s) :
     *pmessage : message to print before
   Input/output parameter(s) :
   Output parameter(s) :
     *pchar : character chosen
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_kbd_press(netwib_constbuf *pmessage,
                            netwib_char *pchar);
/*-------------------------------------------------------------*/
/* Name : netwib_kbd_purge
   Description :
     Purge every pressed keys
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_kbd_purge(void);

MODULE SCREEN
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_screen
   Description :
     Write data to screen.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_screen(netwib_io **ppio);

MODULE BUFENC
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_encodetype
   Description :
     Append the description text of an encodetype.
   Input parameter(s) :
     encodetype : netwib_encodetype to append
   Input/output parameter(s) :
     *pbuf : buffer where text is appended
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_encodetype(netwib_encodetype encodetype,
                                        netwib_buf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_encodetype_init_kbd
   Description :
     Initialize a netwib_encodetype with data entered through keyboard.
   Input parameter(s) :
     *pmessage : message to print before
     displayonlymostuseful : only most useful values are shown
     defaultencodetype : default encodetype to use if user enters nothing
                         (if 0xFFFFFFFFu, means no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pencodetype : netwib_encodetype initialized
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_encodetype_init_kbd(netwib_constbuf *pmessage,
                                      netwib_bool displayonlymostuseful,
                                      netwib_encodetype defaultencodetype,
                                      netwib_encodetype *pencodetype);
#define NETWIB_ENCODETYPE_INIT_KBD_NODEF (netwib_encodetype)0xFFFFFFFFu

MODULE BUFDEC
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_decodetype
   Description :
     Append the description text of an decodetype.
   Input parameter(s) :
     decodetype : netwib_decodetype to append
   Input/output parameter(s) :
     *pbuf : buffer where text is appended
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_decodetype(netwib_decodetype decodetype,
                                        netwib_buf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_decodetype_init_kbd
   Description :
     Initialize a netwib_decodetype with data entered through keyboard.
   Input parameter(s) :
     *pmessage : message to print before
     defaultdecodetype : default decodetype to use if user enters nothing
                         (if 0xFFFFFFFFu, means no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pdecodetype : netwib_decodetype initialized
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_decodetype_init_kbd(netwib_constbuf *pmessage,
                                      netwib_decodetype defaultdecodetype,
                                      netwib_decodetype *pdecodetype);
#define NETWIB_DECODETYPE_INIT_KBD_NODEF (netwib_decodetype)0xFFFFFFFFu

MODULE DISP
/*-------------------------------------------------------------*/
/* Name : netwib_buf_display
   Description :
     Print data contained in a netwib_buf.
   Input parameter(s) :
     *pbuf : buffer to print
     encodetype : netwib_encodetype to use
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_display(netwib_constbuf *pbuf,
                              netwib_encodetype encodetype);
/*-------------------------------------------------------------*/
/* Name : netwib_fmt_display
   Description :
     Print formatted data.
   Input parameter(s) :
     fmt : format as explained in dat/fmt.h
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_fmt_display(netwib_conststring fmt,
                              ...);

MODULE RECORD
/*-------------------------------------------------------------*/
/***************************************************************
 * A record is a file where we can save and read data.         *
 * Each data is separated by an empty newline.                 *
 ***************************************************************/
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_RECORD_ENCODETYPE_HEXA0 = NETWIB_ENCODETYPE_HEXA0,
  NETWIB_RECORD_ENCODETYPE_HEXA1 = NETWIB_ENCODETYPE_HEXA1,
  NETWIB_RECORD_ENCODETYPE_HEXA2 = NETWIB_ENCODETYPE_HEXA2,
  NETWIB_RECORD_ENCODETYPE_HEXA4 = NETWIB_ENCODETYPE_HEXA4,
  NETWIB_RECORD_ENCODETYPE_MIXED0 = NETWIB_ENCODETYPE_MIXED0,
  NETWIB_RECORD_ENCODETYPE_MIXED1 = NETWIB_ENCODETYPE_MIXED1,
  NETWIB_RECORD_ENCODETYPE_HEXA0_WRAP = NETWIB_ENCODETYPE_HEXA0_WRAP,
  NETWIB_RECORD_ENCODETYPE_HEXA1_WRAP = NETWIB_ENCODETYPE_HEXA1_WRAP,
  NETWIB_RECORD_ENCODETYPE_HEXA2_WRAP = NETWIB_ENCODETYPE_HEXA2_WRAP,
  NETWIB_RECORD_ENCODETYPE_HEXA4_WRAP = NETWIB_ENCODETYPE_HEXA4_WRAP,
  NETWIB_RECORD_ENCODETYPE_MIXED0_WRAP = NETWIB_ENCODETYPE_MIXED0_WRAP,
  NETWIB_RECORD_ENCODETYPE_MIXED1_WRAP = NETWIB_ENCODETYPE_MIXED1_WRAP,
  NETWIB_RECORD_ENCODETYPE_DUMP = NETWIB_ENCODETYPE_DUMP,
  NETWIB_RECORD_ENCODETYPE_MIXED0H_WRAP = NETWIB_ENCODETYPE_MIXED0H_WRAP,
  NETWIB_RECORD_ENCODETYPE_MIXED1H_WRAP = NETWIB_ENCODETYPE_MIXED1H_WRAP,
  NETWIB_RECORD_ENCODETYPE_BIN = 1000,  /* binary */
  NETWIB_RECORD_ENCODETYPE_PCAP,        /* libpcap format */
  /* aliases */
  NETWIB_RECORD_ENCODETYPE_HEXA = NETWIB_RECORD_ENCODETYPE_HEXA1,
  NETWIB_RECORD_ENCODETYPE_MIXED = NETWIB_RECORD_ENCODETYPE_MIXED1,
  NETWIB_RECORD_ENCODETYPE_HEXA_WRAP = NETWIB_RECORD_ENCODETYPE_HEXA1_WRAP,
  NETWIB_RECORD_ENCODETYPE_MIXED_WRAP = NETWIB_RECORD_ENCODETYPE_MIXED1_WRAP,
  NETWIB_RECORD_ENCODETYPE_MIXEDH_WRAP = NETWIB_RECORD_ENCODETYPE_MIXED1H_WRAP
} netwib_record_encodetype;
/*-------------------------------------------------------------*/
/* Name : netwib_record_encodetype_init_kbd
   Description :
     Initialize a netwib_encodetype with data entered through keyboard.
   Input parameter(s) :
     *pmessage : message to print before
     displayonlymostuseful : only most useful values are shown
     defaultencodetype : default encodetype to use if user enters nothing
                      (if 0xFFFFFFFFu, means no default)
   Input/output parameter(s) :
   Output parameter(s) :
     *pencodetype : netwib_encodetype initialized
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_record_encodetype_init_kbd(netwib_constbuf *pmessage,
                                             netwib_bool displayonlymostuseful,
                                             netwib_record_encodetype defaultencodetype,
                                             netwib_record_encodetype *pencodetype);
#define NETWIB_RECORD_ENCODETYPE_INIT_KBD_NODEF (netwib_record_encodetype)0xFFFFFFFFu
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_record_encodetype
   Description :
     Append the description text of an encodetype.
   Input parameter(s) :
     encodetype : netwib_record_encodetype to append
   Input/output parameter(s) :
     *pbuf : buffer where text is appended
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_record_encodetype(netwib_record_encodetype encodetype,
                                               netwib_buf *pbuf);
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_record
   Description :
     Open a record.
   Input parameter(s) :
     *precordname : filename of the record
   Input/output parameter(s) :
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_record(netwib_constbuf *precordname,
                                 netwib_file_inittype inittype,
                                 netwib_record_encodetype encodetype,
                                 netwib_io **ppio);
#define netwib_io_init_record_read(recordname,ppio) netwib_io_init_record(recordname,NETWIB_FILE_INITTYPE_READ,NETWIB_RECORD_ENCODETYPE_INIT_KBD_NODEF,ppio)
#define netwib_io_init_record_write(recordname,encodetype,ppio) netwib_io_init_record(recordname,NETWIB_FILE_INITTYPE_WRITE,encodetype,ppio)
#define netwib_io_init_record_append(recordname,ppio) netwib_io_init_record(recordname,NETWIB_FILE_INITTYPE_APPEND,NETWIB_RECORD_ENCODETYPE_INIT_KBD_NODEF,ppio)

MODULE BEEP
/*-------------------------------------------------------------*/
/* Name : netwib_beep
   Description :
     Beep.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_beep(void);

MODULE GLOBAL
/*-------------------------------------------------------------*/
/***************************************************************
 * Functions herein permit to change global configuration of   *
 * netwib.                                                     *
 ***************************************************************/
/*-------------------------------------------------------------*/
/* See below for the meaning of those values */
typedef enum {
  NETWIB_GLOBAL_CTLTYPE_ERR_PURGE = 1,
  NETWIB_GLOBAL_CTLTYPE_CONF_UPDATE,
  NETWIB_GLOBAL_CTLTYPE_DEBUG_CTRLC_PRESSED
} netwib_global_ctltype;
netwib_err netwib_global_ctl_set(netwib_global_ctltype type,
                                 netwib_ptr p,
                                 netwib_uint32 ui);
netwib_err netwib_global_ctl_get(netwib_global_ctltype type,
                                 netwib_ptr p,
                                 netwib_uint32 *pui);
/*-------------------------------------------------------------*/
/* purge last error */
/* netwib_err f(void); */
#define netwib_global_ctl_set_err_purge() netwib_global_ctl_set(NETWIB_GLOBAL_CTLTYPE_ERR_PURGE,NULL,0)
/*-------------------------------------------------------------*/
/* update configuration. Care must be taken to ensure nobody
   is currently looping through current configuration
   (lock/mutex). */
/* netwib_err f(void); */
#define netwib_global_ctl_set_conf_update() netwib_global_ctl_set(NETWIB_GLOBAL_CTLTYPE_CONF_UPDATE,NULL,0)
/*-------------------------------------------------------------*/
/* if Control-C was pressed (used only in Debug mode under Linux,
   in order to detect memory leaks) */
/* netwib_err f(netwib_bool *pbool); */
#define netwib_global_ctl_get_debug_ctrlc_pressed(pbool) netwib_global_ctl_get(NETWIB_GLOBAL_CTLTYPE_DEBUG_CTRLC_PRESSED,NULL,(netwib_uint32 *)pbool)
#define netwib__debug_ctrlc_pressed_break() { netwib_err netwib__debug_ctrlc_pressed_break_ret; netwib_bool netwib__debug_ctrlc_pressed_break_pressed; netwib__debug_ctrlc_pressed_break_ret = netwib_global_ctl_get_debug_ctrlc_pressed(&netwib__debug_ctrlc_pressed_break_pressed); if (netwib__debug_ctrlc_pressed_break_ret == NETWIB_ERR_OK && netwib__debug_ctrlc_pressed_break_pressed) break; }

MODULE INIT
/*-------------------------------------------------------------*/
/* Name : netwib_init
   Description :
     Initialize netwib.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_init(void);
/*-------------------------------------------------------------*/
/* Name : netwib_close
   Description :
     Finish to use netwib's functions.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_close(void);

MODULE ERROR
/*-------------------------------------------------------------*/
typedef enum {
  NETWIB_ERR_ENCODETYPE_TEXT = 1,    /* append the error text */
  NETWIB_ERR_ENCODETYPE_NUMTEXT,     /* append "Error n : text" */
  NETWIB_ERR_ENCODETYPE_FULL         /* full (error, errno, h_errno,
                                        GetLastError, errstr) :
                                        "Error n : text\n `--> message\n"
                                     */
} netwib_err_encodetype;
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_err
   Description :
     Append a string representing an error.
   Input parameter(s) :
     error : error to print
     encodetype : netwib_err_encodetype to use
   Input/output parameter(s) :
   Output parameter(s) :
     *pbuf : netwib_buf receiving data
   Normal return values :
     NETWIB_ERR_OK : ok
   Notes :
     - Error code might have been set by a previous error. By
       example, error in open() sets errno, and then an error
       is gethostbyname() sets h_errno, and both will be
       displayed because the first one is not purged.
       This is normal, because if user directly used
       gethostbyname(), he knows he doesn't have to look at
        errno.
     - If an error occurred in function open() and sets errno.
       Then, memory might need to be freed (so errno will be
       unset). Then error is returned to user, but errno is
       zero.
    As a conclusion, user might not_get/get_incorrect errno,
    h_errno or GetLastError.
*/
netwib_err netwib_buf_append_err(netwib_err error,
                                 netwib_err_encodetype encodetype,
                                 netwib_buf *buf);
/*-------------------------------------------------------------*/
/* Name : netwib_err_display
   Description :
     Print the error associated to a netwib_err.
   Input parameter(s) :
     error : error to print
     encodetype : netwib_err_encodetype to use
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_err_display(netwib_err error,
                              netwib_err_encodetype encodetype);
/*-------------------------------------------------------------*/
/***************************************************************
 * Every netwib function return an netwib_err corresponding to *
 * an error code. Developer have to test this value to ensure  *
 * everything went fine. There is 3 ways to do it :            *
 *                                                             *
 *  1 - doing the test by hand :                               *
 *    ret = function(...);                                     *
 *    if (ret != NETWIB_ERR_OK) {                              *
 *      return(ret);                                           *
 *    }                                                        *
 *                                                             *
 *  2 - use netwib_er :                                        *
 *    netwib_er(function(...));                                *
 *                                                             *
 *  3 - use netwib_eg :                                        *
 *    Note : this define uses a "goto". Developers tend to     *
 *           hate using goto. I also do, but there is one case *
 *           where goto are very useful. This case is for      *
 *           error handling because it creates an error flow   *
 *           similar to exceptions in Java or C++.             *
 *           I'll try to explain it : a program has two flows  *
 *           inside : the normal flow (the real job done) and  *
 *           the error flow (what to do when an error occurs). *
 *           With most algorithms, both flow use the same path,*
 *           so there is no need to use goto. But, when flow   *
 *           differs, we have to complicate the algorithm to   *
 *           deal with both normal and errors conditions.      *
 *           Without goto, it quickly becomes hard to read     *
 *           code, to free (only allocated) resources, to close*
 *           (only opened) descriptors, etc.                   *
 *           With goto, we have something like :               *
 *    {
 *      netwib_io *pio1, *pio2, *pio3;
 *      netwib_bool pio1set, pio2set, pio3set;
 *      netwib_err ret;
 *
 *      pio1set = pio2set = pio3set = NETWIB_FALSE;
 *      ret = NETWIB_ERR_OK;
 *
 *      netwib_eg(netwib_io_init...(&pio1));
 *      pio1set = NETWIB_TRUE;
 *      netwib_eg(netwib_io_init...(&pio2));
 *      pio2set = NETWIB_TRUE;
 *      here_complicated_code_which_can_use_"netwib_eg()"
 *      netwib_eg(netwib_io_close(&pio2));
 *      pio2set = NETWIB_FALSE;
 *      here_complicated_code_which_can_use_"netwib_eg()"
 *      netwib_eg(netwib_io_init...(&pio3));
 *      pio3set = NETWIB_TRUE;
 *
 *     netwib_gotolabel :
 *      if (pio1set) { netwib_er(netwib_io_close(&pio1)); }
 *      if (pio2set) { netwib_er(netwib_io_close(&pio2)); }
 *      if (pio3set) { netwib_er(netwib_io_close(&pio3)); }
 *      return(ret);
 *    }
 *           As seen in this simple example, program flow and  *
 *           error flow are separated.                         *
 ***************************************************************/
/* if (r != NETWIB_ERR_OK) return(r) */
#define netwib_er(r) {netwib_err netwib_coderr=r;if(netwib_coderr!=NETWIB_ERR_OK)return(netwib_coderr);}
/* the label */
#define netwib_gotolabel netwibleavefunction
/* goto label and return r (note : this uses a variable named "ret") */
#define netwib_goto(r) {ret = r; goto netwibleavefunction;}
/* if (r != NETWIB_ERR_OK) { goto label and return r } */
#define netwib_eg(r) {netwib_err netwib_coderr=r;if(netwib_coderr!=NETWIB_ERR_OK)netwib_goto(netwib_coderr);}

MODULE INTERNAL
/*-------------------------------------------------------------*/
/* Name : netwib_internal_version
   Description :
     Obtain netwib version.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     *pversionmajor : major version
     *pversionminor : minor version
     *pversionmicro : micro version
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_internal_version(netwib_uint32 *pversionmajor,
                                   netwib_uint32 *pversionminor,
                                   netwib_uint32 *pversionmicro);
/*-------------------------------------------------------------*/
/* Name : netwib_buf_append_internal
   Description :
     Append a string representing all compilation parameters.
   Input parameter(s) :
   Input/output parameter(s) :
     *pbuf : netwib_buf receiving data
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_buf_append_internal(netwib_buf *buf);
/*-------------------------------------------------------------*/
/* Name : netwib_internal_display
   Description :
     Print all compilation parameters.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_internal_display(void);

MODULE UNIX
/*-------------------------------------------------------------*/
/* Name : netwib_unix_symlink
   Description :
     Create a symlink plinkname -> ppathname
   Input parameter(s) :
     ppathname : pointed path
     plinkname : link
   Input/output parameter(s) :
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_unix_symlink(netwib_constbuf *ppathname,
                               netwib_constbuf *plinkname);
/*-------------------------------------------------------------*/
/* Name : netwib_unix_readlink
   Description :
     Read a symlink value
   Input parameter(s) :
     plinkname : link
   Input/output parameter(s) :
     ppathname : stored/pointed path
   Output parameter(s) :
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_unix_readlink(netwib_constbuf *plinkname,
                                netwib_buf *ppathname);

MODULE WINDOWS
/*-------------------------------------------------------------*/
/* Name : netwib_io_init_handle
   Description :
     Open a Windows HANDLE. This function only exists
     Windows.
   Input parameter(s) :
     h : HANDLE
   Input/output parameter(s) :
     closeatend : if HANDLE have to be closed when the io is
                  closed
   Output parameter(s) :
     **ppio : io created
   Normal return values :
     NETWIB_ERR_OK : ok
*/
netwib_err netwib_io_init_handle(NETWIBHANDLE h,
                                 netwib_bool closeatend,
                                 netwib_io **ppio);
/*-------------------------------------------------------------*/
/* Name : netwib_windowstype_init
   Description :
     Get system version.
   Input parameter(s) :
   Input/output parameter(s) :
   Output parameter(s) :
     *ptype : system type
   Normal return values :
     NETWIB_ERR_OK : ok
*/
typedef enum {
  NETWIB_WINDOWSTYPE_UNKNOWN = 0, /* Unknown system */
  NETWIB_WINDOWSTYPE_31,          /* Windows 3.1 */
  NETWIB_WINDOWSTYPE_95,          /* Windows 95 */
  NETWIB_WINDOWSTYPE_98,          /* Windows 98 */
  NETWIB_WINDOWSTYPE_ME,          /* Windows Me */
  NETWIB_WINDOWSTYPE_NT350,       /* Windows NT 3.5.0 */
  NETWIB_WINDOWSTYPE_NT351,       /* Windows NT 3.5.1 */
  NETWIB_WINDOWSTYPE_NT4,         /* Windows NT 4 */
  NETWIB_WINDOWSTYPE_2000,        /* Windows 2000 */
  NETWIB_WINDOWSTYPE_XP,          /* Windows XP */
  NETWIB_WINDOWSTYPE_2003,        /* Windows 2003 */
  NETWIB_WINDOWSTYPE_2008,        /* Windows 2008 */
  NETWIB_WINDOWSTYPE_7            /* Windows 7 */
} netwib_windowstype;
netwib_err netwib_windowstype_init(netwib_windowstype *ptype);

SEE ALSO
netwib(3), netwib_dat(3), netwib_sys(3), netwib_net(3), netwib_pkt(3), netwib_shw(3), netwib_err(3)