summaryrefslogtreecommitdiff
path: root/man
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-09 13:02:45 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-09 13:02:45 +0200
commit96cf8dffe4f7b0b910f790066ae622dc429eb522 (patch)
treecc1343a0ac92bb4836cae2dd63a97fa045765e7f /man
initial commit of version 23fehQlibs-23
Diffstat (limited to 'man')
-rw-r--r--man/INSTALL12
-rw-r--r--man/alloc.368
-rw-r--r--man/buffer.3185
-rw-r--r--man/byte.382
-rw-r--r--man/case.3124
-rw-r--r--man/cdbmake.361
-rw-r--r--man/cdbread.3177
-rw-r--r--man/constmap.356
-rw-r--r--man/dns.3249
-rw-r--r--man/dnsstub.3109
-rw-r--r--man/env.368
-rw-r--r--man/error.375
-rw-r--r--man/fd.379
-rw-r--r--man/fmt.390
-rw-r--r--man/getln.3102
-rw-r--r--man/getoptb.322
-rw-r--r--man/iopause.387
-rw-r--r--man/ip4.373
-rw-r--r--man/ip6.398
-rw-r--r--man/logmsg.3109
-rw-r--r--man/pathexec.3124
-rw-r--r--man/scan.381
-rw-r--r--man/socket_bind.3117
-rw-r--r--man/socket_connect.3110
-rw-r--r--man/socket_if.397
-rw-r--r--man/socket_info.347
-rw-r--r--man/socket_recv.356
-rw-r--r--man/socket_send.376
-rw-r--r--man/socket_setup.3105
-rw-r--r--man/socket_tcp.358
-rw-r--r--man/socket_udp.358
-rw-r--r--man/str.361
-rw-r--r--man/stralloc.3160
-rw-r--r--man/taia.391
-rw-r--r--man/timeout.336
-rw-r--r--man/timeoutconn.352
-rw-r--r--man/wait.396
-rw-r--r--man/x.html99
38 files changed, 3450 insertions, 0 deletions
diff --git a/man/INSTALL b/man/INSTALL
new file mode 100644
index 0000000..7281ed9
--- /dev/null
+++ b/man/INSTALL
@@ -0,0 +1,12 @@
+Imstallation of fehQlibs man pages
+==================================
+
+a) It is expected that the fehQlibs are installed at /usr/local.
+b) Check your manpath settings: $ manpath
+c) You might want to compress the manpages: gzip *.3
+d) If available, the compressed or raw man pages can be simply copied to
+ - /usr/local/man/man3 or
+ - /usr/local/share/man/man3
+ 'root' is required to complete this step.
+
+That's it!
diff --git a/man/alloc.3 b/man/alloc.3
new file mode 100644
index 0000000..5bd40d2
--- /dev/null
+++ b/man/alloc.3
@@ -0,0 +1,68 @@
+.TH qlibs: alloc 3
+.SH NAME
+alloc \- allocate memory
+.SH SYNTAX
+.B #include \(dqalloc.h\(dq
+
+char *\fBalloc\fP(\fInew\fR);
+
+void \fBalloc_free\fP(\fIx\fR);
+
+void \fBalloc_re\fP(&\fIx\fR,\fIold\fR,\fInew\fR);
+
+char *\fIx\fR;
+.br
+unsigned int \fIold\fR;
+.br
+unsigned int \fInew\fR;
+.SH DESCRIPTION
+.B alloc
+allocates enough space from the heap for
+.I new
+bytes of data,
+adequately aligned for any data type.
+.I new
+may be 0.
+.B alloc
+returns a pointer to the space.
+If space is not available,
+.B alloc
+returns 0,
+setting
+.B errno
+appropriately.
+
+.B alloc_free
+returns space to the heap.
+
+.B alloc_re
+expands the space allocated to
+.I x
+from
+.I old
+bytes to
+.I new
+bytes.
+It allocates new space,
+copies
+.I old
+bytes from the old space to the new space,
+returns the old space to the heap,
+and changes
+.I x
+to point to the new space.
+It then returns 1.
+If space is not available,
+.B alloc_re
+returns 0,
+leaving the old space alone.
+.SH "CVE-2005-1513"
+This version of
+.B alloc
+respects
+.I limits.h
+to avoid memory resource exhaustion.
+.SH "SEE ALSO"
+sbrk(2),
+malloc(3),
+error(3)
diff --git a/man/buffer.3 b/man/buffer.3
new file mode 100644
index 0000000..2d4d0d2
--- /dev/null
+++ b/man/buffer.3
@@ -0,0 +1,185 @@
+.TH buffer 3
+.SH NAME
+buffer \- generic read/write buffering
+.SH SYNTAX
+.B #include \(dqbuffer.h\(dq
+
+buffer* buffer_0; /* like stdio's stdin */
+.br
+buffer* buffer_1; /* like stdio's stdout */
+.br
+buffer* buffer_2; /* like stdio's stderr */
+
+void \fBbuffer_init\fR(buffer &\fIb\fR,ssize_t (*\fIop\fR)(int,char *,size_t),
+ int \fIfd\fR, char *\fIy\fR, size_t \fIylen\fR);
+.br
+ssize_t \fBbuffer_get\fP(buffer *\fIb\fR,char *\fIx\fR,size_t \fIlen\fR);
+
+int \fBbuffer_put\fP(buffer *\fIb\fR,const char *\fIx\fR,size_t \fIlen\fR);
+.br
+int \fBbuffer_puts\fP(buffer *\fIb\fR,const char *\fIx\fR);
+.br
+int \fBbuffer_putalign\fP(buffer *\fIb\fR,char *\fIx\fR,unsigned int \fIlen\fR);
+.br
+int \fBbuffer_putsalign\fP(buffer *\fIb\fR,char *\fIx\fR);
+
+int \fBbuffer_putflush\fP(buffer *\fIb\fR,char *\fIx\fR,unsigned int \fIlen\fR);
+.br
+int \fBbuffer_putsflush\fP(buffer *\fIb\fR,char *\fIx\fR);
+
+int \fBbuffer_flush\fP(buffer *\fIb\fR);
+.br
+int \fBbuffer_copy\fP(buffer *\fIbo\fR,buffer *\fIbi\fR);
+
+int \fBbuffer_unixread\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR);
+.br
+int \fBbuffer_unixwrite\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR);
+.SH DESCRIPTION
+.B buffer.h
+describes a generic buffer interface that can be used for
+read and write buffering. Buffers must be initialized with
+\fBbuffer_init\fR.
+
+A buffer can only be used for reading or writing at the same time, not
+both.
+
+Unlike
+.BR stdio ,
+these write buffers are not flushed automatically at
+program termination; you must manually call \fBbuffer_flush\fR,
+\fBbuffer_putflush\fR, or \fBbuffer_putsflush\fR.
+
+.B buffer_init
+prepares \fIb\fR to store a string in \fIy\fR[0], \fIy\fR[1], ...,
+\fIy\fR[\fIylen\fR-1]. Initially the string is empty.
+
+.B buffer_init
+also prepares \fIb\fR to use the read/write operation specified by
+\fIop\fR and \fIfd\fR.
+
+You can use
+
+ buffer \fIb\fR = BUFFER_INIT(\fIop\fR,\fIfd\fR,\fIy\fR,\fIylen\fR);
+
+to initialize \fIb\fR statically if \fIop\fR, \fIfd\fR, \fIy\fR, and \fIylen\fR
+are compile-time constants.
+
+You can call
+.B buffer_init
+again at any time. Note that this discards the currently buffered string.
+
+.B buffer_get
+copies data to \fIx\fR[0], \fIx\fR[1], ...,
+\fIx\fR[\fIlen\fR-1] from the beginning of a string stored in
+preallocated space; removes these \fIlen\fR bytes from the string; and
+returns \fIlen\fR.
+
+If, however, the string has fewer than \fIlen\fR (but more than 0)
+bytes,
+.I buffer_get
+copies only that many bytes, and returns that number.
+
+If the string is empty,
+.B buffer_get
+first uses a \fBread operation\fR to
+feed data into the string. The \fBread operation\fR may indicate end of
+input.
+
+The preallocated space and the \fBread operation\fR are specified by
+\fIb\fR. You must initialize \fBb\fR using
+.B buffer_init
+before calling
+.B buffer_get
+(or use the pre-initialized \fIbuffer_0\fR).
+
+.B buffer_put
+writes \fIlen\fR bytes from \fIx\fR to \fIb\fR.
+
+The difference to
+.B buffer_putalign
+is that, when there isn't enough space
+for new data,
+.B buffer_put
+calls
+.B buffer_flush
+before copying any data, while
+.B buffer_putalign
+fills all available space with data before calling
+.B buffer_flush.
+
+.B buffer_copy
+copies one buffer to other one.
+The output buffer needs to have at least the
+preallocated size of the input buffer.
+.B buffer_unixread
+and
+.B buffer_unixwrite
+perform the same operation like standard Unix
+.B read
+or
+.BR write.
+.SH MACROS
+Apart from this basic usage, some helpful macro
+definitions are provided:
+.B BUFFER_INIT(op,fd,buf,len)
+uses
+.I op
+function to operate (read/write) on
+.I buf
+with
+.I len
+to file descriptor
+.IR fd .
+.B buffer_GETC(buf,c)
+returns the upmost position of character
+.I c
+within buffer
+.I buf
+or 0.
+.B buffer_PUTC(buf,c)
+adds character
+.I c
+to buffer
+.IR buf.
+.SH EXAMPLE
+ #include <buffer.h>
+ #include <open.h>
+
+ char buf[BUFFER_INSIZE]; // defined in buffer.h
+ int fd = open_read("/etc/services");
+ buffer input;
+
+ if (fd >= 0) {
+ char x;
+ buffer_init(&input,read,fd,buf,sizeof buf);
+ while (buffer_get(&input,&x,1) == 1) {
+ buffer_put(buffer_1,&x,1);
+ if (x == '\\n') break;
+ }
+ buffer_flush(buffer_1);
+ }
+.SH "RETURN CODES"
+.B buffer_put
+and
+.B buffer_get
+return
+.I 0
+if everything was fine,
+.IR -1 ,
+on error (setting \fIerrno\fR).
+.B buffer_copy
+returns
+.IR -2 ,
+if the input buffer can't be read, and
+.IR -3 ,
+if the data can't successfully copied
+to the output buffer. On success
+.B buffer_copy
+returns
+.IR 0 .
+.SH "REFERENCES"
+https://cr.yp.to/lib/buffer_get.html
+
+https://cr.yp.to/lib/buffer_put.html
+.SH "SEE ALSO"
+stdio(3)
diff --git a/man/byte.3 b/man/byte.3
new file mode 100644
index 0000000..277e479
--- /dev/null
+++ b/man/byte.3
@@ -0,0 +1,82 @@
+.TH qlibs byte 3
+.SH NAME
+byte \- byte manipulation/evaluation
+.SH SYNTAX
+.B #include \(dqbyte.h\(dq
+
+unsigned int \fBbyte_chr\fP(const char *\fIhaystack\fR,unsigned int \fIlen\fR,char \fIneedle\fR);
+.br
+unsigned int \fBbyte_rchr\fP(const char *\fIhaystack\fR,unsigned int \fIlen\fR,char \fIneedle\fR);
+
+void \fBbyte_copy\fP(char *\fIout\fR,unsigned int \fIlen\fR,const char *\fIin\fR);
+.br
+void \fBbyte_copyr\fP(char *\fIout\fR,unsigned int \fIlen\fR,const char *\fIin\fR);
+
+int \fBbyte_diff\fP(const char *\fIone\fR,unsigned int \fIlen\fR,const char *\fItwo\fR);
+
+int \fBbyte_equal\fP(const char *\fIone\fR,unsigned int \fIlen\fR,const char *\fItwo\fR);
+
+void \fBbyte_fill\fP(char *\fIout\fR,unsigned int \fIlen\fR,const char \fIc\fR);
+.br
+void \fBbyte_zero\fP(char *\fIout\fR,unsigned int \fIlen\fR);
+.SH DESCRIPTION
+.B byte_chr
+returns the smallest integer \fIi\fR between 0 and
+\fIlen\fR-1 inclusive such that \fIone\fR[\fIi\fR] equals \fIneedle\fR.
+If no such integer exists,
+.B byte_chr
+returns \fIlen\fR.
+.B byte_chr
+may read all bytes \fIone\fR[0], \fIone\fR[1], ...,
+\fIone\fR[\fIlen\fR-1], even if not all the bytes are relevant to the
+answer.
+
+.B byte_rchr
+returns the largest integer \fIi\fR between 0 and
+\fIlen\fR-1 inclusive such that \fIone\fR[\fIi\fR] equals \fIneedle\fR.
+If no such integer exists,
+.B byte_rchr
+returns \fIlen\fR.
+.B byte_rchr
+may read all bytes \fIone\fR[0], \fIone\fR[1], ...,
+\fIone\fR[\fIlen\fR-1], even if not all the bytes are relevant to the
+answer.
+
+.B byte_copy
+copies \fIin\fR[0] to \fIout\fR[0], \fIin\fR[1] to
+\fIout\fR[1], etc., and finally \fIin\fR[\fIlen\fR-1] to
+\fIout\fR[\fIlen\fR-1].
+
+.B byte_copyr
+copies \fIin\fR[\fIlen\fR-1] to \fIout\fR[\fIlen\fR-1],
+\fIin\fR[\fIlen\fR-2] to \fIout\fR[\fIlen\fR-2], etc., and
+\fIin\fR[0] to \fIout\fR[0].
+
+.B byte_diff
+returns negative, 0, or positive, depending on whether
+the string \fIone\fR[0], \fIone\fR[1], ..., \fIone\fR[\fIlen\fR-1] is
+lexicographically smaller than, equal to, or greater than the string
+\fIone\fR[0], \fIone\fR[1], ..., \fIone\fR[\fIlen\fR-1].
+When the strings are different,
+.B byte_diff
+does not read bytes past the first difference.
+
+.B byte_equal
+returns
+.I 1
+if the strings are equal,
+.I 0
+otherwise.
+When the strings are different,
+.B byte_equal
+does not read bytes past the first difference.
+
+.B byte_fill
+fills \fIout\fR[0], \fIout\fR[1], ..., \fIout\fR[\fIlen\fR-1]
+with a single byte \fIc\fR.
+
+.B byte_zero
+sets \fIout\fR[0], \fIout\fR[1], ..., \fIout\fR[\fIlen\fR-1] to 0.
+.SH "SEE ALSO"
+case(3),
+stralloc(3)
diff --git a/man/case.3 b/man/case.3
new file mode 100644
index 0000000..c9a879a
--- /dev/null
+++ b/man/case.3
@@ -0,0 +1,124 @@
+.TH qlibs: case 3
+.SH NAME
+case \- case independent string manipulation/evaluation
+.SH SYNTAX
+.B #include \(dqcase.h\(dq
+
+void \fBcase_lowers\fP(\fIs\fR);
+.br
+void \fBcase_lowerb\fP(\fIs\fR,\fIlen\fR);
+.br
+void \fBcase_uppers\fP(\fIs\fR);
+.br
+void \fBcase_upperb\fP(\fIs\fR,\fIlen\fR);
+.br
+int \fBcase_diffs\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_equals\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_diffrs\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_equalrs\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_starts\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_diffb\fP(\fIs\fR,\fIlen\fR,\fIt\fR);
+.br
+int \fBcase_startb\fP(\fIs\fR,\fIlen\fR,\fIt\fR);
+
+char *\fIs\fR;
+.br
+char *\fIt\fR;
+.br
+unsigned int \fIlen\fR;
+.SH DESCRIPTION
+.B case_lowers
+converts each uppercase byte in the string
+.I s
+to lowercase.
+.I s
+must be 0-terminated.
+
+.B case_lowerb
+converts each uppercase byte in the buffer
+.IR s ,
+of length
+.IR len ,
+to lowercase.
+
+.B case_uppers
+converts each lowercase byte in the string
+.I s
+to uppercase.
+.I s
+must be 0-terminated.
+
+.B case_upperb
+converts each lowercase byte in the buffer
+.IR s ,
+of length
+.IR len ,
+to uppercase.
+
+.B case_diffs
+lexicographically compares lowercase versions of the strings
+.I s
+and
+.IR t .
+It returns something positive, negative, or zero
+when the first is larger than, smaller than, or equal to the second.
+.I s
+and
+.I t
+must be 0-terminated.
+
+.B case_equals
+means
+.BR !case_diffs .
+
+.B case_diffrs
+and
+.B case_equalrs
+compare strings from right to left instead from left to right.
+
+.B case_starts
+returns 1 if a lowercase version of
+.I s
+starts with a lowercase version of
+.IR t .
+.I s
+and
+.I t
+must be 0-terminated.
+
+.B case_diffb
+lexicographically compares lowercase versions of the buffers
+.I s
+and
+.IR t ,
+each of length
+.IR len .
+It returns something positive, negative, or zero
+when the first is larger than, smaller than, or equal to the second.
+
+.B case_startb
+returns 1 if a lowercase version of the buffer
+.IR s ,
+of length
+.IR len ,
+starts with a lowercase version of the string
+.IR t .
+.I t
+must be 0-terminated.
+
+The
+.B case
+routines
+are ASCII-specific.
+They are suitable for programs that handle
+case-independent networking protocols.
+
+All comparisons are performed on unsigned bytes.
+.SH "SEE ALSO"
+byte(3),
+stralloc(3)
diff --git a/man/cdbmake.3 b/man/cdbmake.3
new file mode 100644
index 0000000..7e7fd3e
--- /dev/null
+++ b/man/cdbmake.3
@@ -0,0 +1,61 @@
+.TH qlibs:cdbmake 3
+.SH NAME
+cdmake \- generate and fill a constant database
+.SH SYNTAX
+.B #include \(dqcdmake.h\(dq
+
+int \fBcdb_make_start\fP(struct cdb *\fIc\fR,int \fIfd\fR);
+.br
+int \fBcdb_make_add\fP(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned int \fIkeylen\fR,
+ char *\fIdata\fR,unsigend int \fIdatalen\fR);
+.br
+int \fBcdb_make_finish\fP(struct cdb *\fIc\fR);
+.SH DESCRIPTION
+.B cdb_make_start
+generates and intitialises a new cdb named
+.I c
+and makes it available via file descriptor
+.IR fd .
+
+.B cdb_make_add
+adds entries using the file descriptor
+.I fd
+given as
+.I key
+with length
+.I keylen
+into the cdb returning the hashed values
+.I data
+with length
+.IR datalen .
+
+.B cdb_make_finish
+finalises the data structure provided as
+.IR fd .
+
+.SH "RETURN CODES"
+Usually, the
+.B cdb_make_*
+routines provide a return code of
+.I 0
+for successful operations and
+.I -1
+if anything is going wrong.
+
+.SH EXAMPLE
+#include <cdbmake.h>
+
+ int fd;
+ stralloc data = {0};
+ stralloc key = {0};
+
+ struct cdb_make c;
+
+ if (cdb_make_start(&c,fd) == -1) die_write();
+ if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1)
+ die_write();
+ if (cdb_make_finish(&c) == -1) die_write();
+ if (fsync(fd) == -1) die_write();
+
+.SH "SEE ALSO"
+cdbread(3)
diff --git a/man/cdbread.3 b/man/cdbread.3
new file mode 100644
index 0000000..6d4641f
--- /dev/null
+++ b/man/cdbread.3
@@ -0,0 +1,177 @@
+.TH qlibs:cdbread 3
+.SH NAME
+cdbread \- fetch information from a constant database
+.SH SYNTAX
+.B #include \(dqcdbread.h\(dq
+
+void \fBcdb_init\fP(struct cdb *\fIc\fR,int \fIfd\fR);
+.br
+int \fBcdb_read\fP(struct cdb *\fIc\fR,char *\fIdata\fR,unsigned int \fIdlen\fR,uint32 \fIpos\fR);
+.br
+int \fBcdb_findstart\fP(int \fIfd\fR,char *\fIkey\fR,unsigned int \fIlen\fR);
+.br
+int \fBcdb_findnext\fP(int \fIfd\fR,char *\fIkey\fR,unsigned int \fIlen\fR);
+.br
+int \fBcdb_find\fP(int \fIfd\fR,char *\fIney\fR,unsigned int \fIlen\fR);
+
+.br
+int \fBcdb_findnext\fP(int \fIfd\fR,char *\fIkey\fR,unsigned int \fIlen\fR);
+.br
+void \fBcdb_free\fP(struct cdb *\fIc\fR):
+.SH DESCRIPTION
+.B cdb_free
+unallocates
+.I c
+if
+.I c
+is allocated.
+Otherwise it leaves
+.I c
+alone.
+.B cdb_free
+does not close
+.IR fd .
+
+.B cdb_init
+allocates
+.B c
+to hold information about a constant database read by descriptor
+.IR fd .
+You may call
+.B cdb_init
+repeatedly; if
+.I c
+is already allocated,
+.B cdb_init
+unallocates it first.
+
+.B cdb_read
+reads
+.I dlen
+bytes into
+.I d
+from byte position
+.I dpos
+in the database. You must allocate
+.I c
+before calling
+.BR cdb_read .
+Normally
+.B cdb_read
+returns
+.IR 0 .
+If the database file is shorter than
+.I dpos+dlen
+bytes, or if there is a disk read error,
+.B cdb_read
+returns
+.IR -1 ,
+setting
+.I errno
+appropriately.
+
+.B cdb_findstart
+prepares
+.I c
+to search for the first record under a new
+.IR key .
+You must allocate
+.I c
+before calling
+.BR cdb_findstart ,
+and you must call
+.B cdb_findstart
+before calling
+.BR cdb_findnext .
+
+.B cdb_findnext
+looks for the nth record under
+.I key
+in the database, where
+.I n
+is the number of calls to
+.B cdb_findnext
+after the most recent call to
+.BR cdb_findstart .
+If it finds the record,
+.B cdb_findnext
+returns
+.IR 1 ;
+if there are exactly n-1 such records,
+.B cdb_findnext
+returns
+.IR 0 ;
+if there are fewer than n-1 such records, the behavior of
+.B cdb_findnext
+is undefined; if there is a database format error or disk error,
+.B cdb_findnext
+returns
+.IR -1 , setting
+.I errno
+appropriately. Each call to
+.B cdb_findnext
+(before another call to
+.BR cdb_findstart )
+must use the same
+.I k
+and
+.IR klen .
+
+If
+.B cdb_findnext
+returns
+.IR 1 ,
+it arranges for
+.B cdb_datapos
+to return the starting byte position of the data in the record, and for
+.B cdb_datalen
+to return the number of bytes of data in the record.
+Otherwise the results of
+.B cdb_datapos
+and
+.B cdb_datalen
+are undefined.
+
+.B cdb_find
+is the same as
+.B cdb_findstart
+followed by
+.BR cdb_findnext :
+it finds the first record under
+.IR key.
+
+.B cdb_datapos
+and
+.B cdb_datalen
+are macros pointing to the found information following
+.I key
+in the cdb and returning their length.
+.SH EXAMPLE
+#include <cdbread.h>
+
+ int fd;
+ char *data;
+ unsigned int len;
+ stralloc key = {0};
+
+ static struct cdb c;
+
+ cdb_init(&c,fd);
+
+ switch (cdb_find(&c,key.s,key.len)) {
+ case -1: return -1;
+ case 0: return 0;
+ }
+
+ len = cdb_datalen(&c);
+ data = alloc(len);
+ if (!data) return -1;
+
+ if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) {
+ alloc_free(data);
+ return -1;
+ }
+
+ cdb_free(&c);
+.SH "SEE ALSO"
+cdbmake(3)
diff --git a/man/constmap.3 b/man/constmap.3
new file mode 100644
index 0000000..e28f5f4
--- /dev/null
+++ b/man/constmap.3
@@ -0,0 +1,56 @@
+.TH qlibs:constmap 3
+.SH NAME
+constmap \- fetch matching strings from a hashed data structure in constant time
+.SH SYNTAX
+.B #include \(dqconstmap.h\(dq
+.SH SYNOPSIS
+int \fBconstmap_init\fP(struct constmap \fI*cm\fR,char \fI*string\fR,int \fIlen\fR,int \fIflagcolon\fR);
+.br
+int \fBconstmap_init_char\fP(struct constmap \fI*cm\fR,char \fI*string\fR,int \fIlen\fR,int \fIflagcolon\fR,char \fIflagchar\fR);
+.br
+char *\fBconstmap\fP(struct constmap \fI*cm\fR,char \fI*string\fR,int \fIlen\fR);
+.br
+void \fBconstmap_free\fP(\fIstruct constmap *cm\fR);
+.SH DESCRIPTION
+Reading a file perhaps with
+.I control_readfile(&cmap,"path/filename",0)
+.B constmap_init
+can be used to convert its content into a constant time search map:
+.IR constmap .
+Here, you can specify whether the entries in
+.I constmap
+are plain or key/value structured setting
+.I flagcolon
+to one and assuming the delimiter equals to a colon:
+.IR : .
+If the delimiter needs to be particulary tailored, use
+.BR constmap_init_char .
+
+Given the search
+.I string
+and providing its length
+.I len
+(without the trailing \\0)
+.B constmap
+will now retrieve the information in constant time
+returning a pointer to the search result or
+.IR 0 .
+
+The datastructure can be freed by means of
+.BR constmap_free .
+.SH EXAMPLE
+#include <constmap.h>
+
+ struct constmap cmap;
+ stralloc result = {0};
+ char *info;
+ char *search;
+
+ if (control_readfile(&cmap,"control/conf",0))
+ constmap_init(&cmap,result.s,result.len,1));
+
+ info = constmap(&cmap,search,str_len (search));
+ if (!info) return 0;
+
+.SH "SEE ALSO"
+cdbread(3), cdbmake(3)
diff --git a/man/dns.3 b/man/dns.3
new file mode 100644
index 0000000..837450c
--- /dev/null
+++ b/man/dns.3
@@ -0,0 +1,249 @@
+.TH qlibs: dnsresolv
+.SH NAME
+dns \- dns resolver routines
+.SH SYNTAX
+.B #include \(dqdnsresolv.h\(dq
+
+int \fBdns_ip4_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+.br
+int \fBdns_ip4\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR);
+
+int \fBdns_ip6_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+.br
+int \fBdns_ip6\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR);
+
+int \fBdns_mx\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR);
+.br
+int \fBdns_mx_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+
+void \fBdns_name4_domain\fP(char \fIq\fR[DNS_NAME4_DOMAIN],const char *\fIip\fR[4]);
+.br
+int \fBdns_name4\fP(stralloc *\fIout\fR,const char *\fIip\fR[4]);
+
+void \fBdns_name6_domain\fP(char \fIq\fR[DNS_NAME6_DOMAIN],const char *\fIip\fR[16]);
+.br
+int \fBdns_name6\fP(stralloc *\fIout\fR,const char *\fIip\fR[16]);
+
+int \fBdns_name\fP(stralloc *\fIout\fR,const char *\fIip\fR[16]);
+.br
+int \fBdns_name_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+
+int \fBdns_txt\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR);
+.br
+int \fBdns_txt_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+
+int \fBdns_cname\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR);
+.br
+int \fBdns_cname_packet\fP(stralloc *\fIout\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR);
+
+int \fBdns_ip4_qualify\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR,const stralloc *\fIudn\fR);
+.br
+int \fBdns_ip6_qualify\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR,const stralloc *\fIudn\fR);
+.br
+int \fBdns_ip_qualify\fP(stralloc *\fIout\fR,stralloc *\fIfqdn\fR,const stralloc *\fIudn\fR);
+.SH DESCRIPTION
+.B dns_ip[4|6]_packet
+is a low-level component of
+.BR dns_ip[4|6] ,
+designed to support asynchronous DNS lookups.
+It reads a DNS packet of length \fIlen\fR from
+\fIbuf\fR, extracts the IP(4|6) addresses from the answer section of the packet and
+puts the addresses into \fIout\fR.
+
+.B dns_ip[4|6]
+looks up 4/16-byte IPv6 addresses for the fully qualified domain name of
+\fIfqdn\fR. It puts the concatenation of the IPv[4|6] addresses into \fIout\fR and
+returns the number of received answers for \fIfqdn\fR or \fI0\fR if none are replied.
+If the domain does not exist in DNS, or has no IP addresses,
+\fIout\fR will be empty. More generally, if \fIfqdn\fR is considered by
+.B dns_ip4
+to be a dotted-decimal IPv4 address, it is provissioned as \fIout\fR
+without checking the DNS while returning \fI1\fR.
+Brackets may enclose the dotted-decimal IP address; they are ignored.
+
+.B dns_name[4|6]_packet
+is a low-level component of
+.B dns_name[4|6]
+designed to support asynchronous DNS lookups.
+It reads a DNS packet of length \fIlen\fR from \fIbuf\fR,
+
+.B dns_name[4|6]_domain
+is a low-level component of
+.BR dns_name[4|6] .
+It converts an IP address such as
+.I 1.2.3.4
+or
+.I 4321:0:1:2:3:4:567:89ab
+into a domain name such as
+.I 4.3.2.1.in-addr.arpa
+or
+.I b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa
+and places the packet-encoded domain name into \fIq\fR.
+.I q
+is zero terminated.
+.I q
+must have space for DNS_NAME[4|6]_DOMAIN bytes.
+
+.B dns_mx_packet
+is a low-level component of
+.BR dns_mx ,
+designed to support asynchronous DNS lookups.
+It reads a DNS packet of length \fIlen\fR from \fIbuf\fR,
+extracts the MX records from the answer section of the packet, puts the
+result into \fIout\fR, and returns the number of replies received
+or \fI-1\fR the same way as
+.BR dns_mx .
+
+.B dns_mx
+looks up MX records for the fully-qualified domain name in
+\fIfqdn\fR. It puts the MX records into \fIout\fR and returns the number of
+received records or \fI0\fR.
+Each MX record is a two-byte MX distance (big endian) followed by a
+\\0-terminated dot-encoded domain name. If the domain does not exist in
+DNS, or has no MX records, \fIout\fR will be empty.
+
+.B dns_txt_packet
+is a low-level component of
+.BR dns_txt ,
+designed to support
+asynchronous DNS lookups. It reads a DNS packet of length \fIlen\fR from \fIbuf\fR,
+extracts the TXT records from the answer section of the packet, puts the
+result into \fIout\fR, and returns the number of replies
+or \fI-1\fR the same way as \fBdns_txt\fR.
+
+.B dns_txt
+looks up TXT records for the fully-qualified domain name in
+\fIfqdn\fR. It puts the concatenation of the TXT records into \fIout\fR
+and returns the number of replies received.
+If the domain does not exist in DNS, or has no TXT records, \fIout\fR will be empty.
+
+.B dns_cname_packet
+is a low-level component of
+.BR dns_cname ,
+designed to support
+asynchronous DNS lookups. It reads a DNS packet of length \fIlen\fR from \fIbuf\fR,
+extracts the TXT records from the answer section of the packet, puts the
+result into \fIout\fR, and returns the number of replies received or
+\fI-1\fR the same way as \fBdns_cname\fR.
+
+.B dns_cname
+looks up the canonical name for a given
+.IR fqdn .
+
+.B dns_ip[4|6]_qualify
+feeds the name \fIudn\fR through qualification and looks up their
+4-byte/16-byte IP addresses. It puts the fully qualified domain name
+into \fIfqdn\fR and the concatenation of the IP addresses into \fIout\fR,
+while returning the number of encountered IP addresses.
+.B dns_ip[4|6]_qualify
+evaluates the environment variables
+.I $DNSREWRITEFILE
+pointing to
+.I /etc/dnsrewrite
+and
+.I $LOCALDOMAIN
+and finally reading
+.I /etc/resolv.conf
+to build the
+.I Full Qualified Domain Name (FQDN)
+using the
+.I domain suffix
+for
+.IR hostname .
+.B dns_ip_qualify
+returns
+.I out
+as
+.I IP[4|6]
+and
+.IR FQDN .
+If the domain does not exist in DNS, or has no IP addresses,
+\fIout\fR will be empty and the return code is \fI0\fR.
+
+In case
+.B dns_ip[4|6]_qualify
+is fed with an
+.I IP[4|6]
+addresses instead of domain names,
+it recognizes those not to be subject of
+.IR qualification .
+The particular names
+.IR localhost ,
+.I ip4-loopback
+and
+.I ip6-loopback
+are treated locally and mapped to
+the respective
+.I IP[4|6]
+addresses (and vice versa)
+without facilitating a DNS lookup.
+.SH "INPUT"
+For the high-level routines
+.BR dns_ip[4|6] ,
+.BR dns_ip_qualify[4|6] ,
+.BR dns_name[4|6] ,
+.BR dns_mx ,
+.BR dns_name ,
+.BR dns_txt
+and
+.BR dns_cname
+the provided input variable
+.I stralloc \*\fqdn
+needs to be un-terminated, thus the given
+string length is identitical to the number of
+.I fqdn
+characters.
+.SH "OUTPUT"
+The returned IP addresses are given as character (byte) strings
+with 4 or 16 bytes:
+.B dns_ip4
+and
+.B dns_ip4_qualifiy
+return 4 byte IPv4 addresses, where as
+.B dns_ip6
+and
+.B dns_ip
+as well as
+.B dns_ip6_qualify
+and
+.B dns_ip_qualify
+return sets of 16 byte IPv6 addresses, where
+the potential IPv4 addresses are given in their
+IPv6-mapped-IPv4 representation.
+.SH "RETURN CODES"
+The dns routines
+.BR dns_cname* ,
+.BR dns_ip* ,
+.BR dns_mx* ,
+.B dns_name*
+and
+.BR dns_txt*
+return the number of answers received, which may be
+.I 0
+and potentially
+.I -1
+in case of a memory failure. The full set of return codes:
+
+.EX
+Value | Macro | Explaination
+------+----------+-------------------------------------
+ n>0 | | n = number of answers reeceived
+ 0 | DNS_NXD | either NXDOMAIN or NODATA
+ -1 | DNS_MEM | out of memory (fatal)
+ -2 | DNS_ERR | parsing errors
+ -3 | DNS_COM | socket communicaton errror; SERVFAIL
+ -4 | DNS_INT | internal error
+ -5 | DNS_SOFT | DNS_ERR or DNS_COM
+ -6 | DNS_HARD | DNS loop problem (CNAME)
+.EE
+
+.I errno
+is set appropriately.
+In case of a failure, the respective output variables like
+\fIout\fR and \fIfqdn\fR may or may not change.
+Since a received reply may be empty, always check the length of the
+received output additionally.
+.SH "SEE ALSO"
+ip4(3),
+ip6(3),
+dnsstub(3)
diff --git a/man/dnsstub.3 b/man/dnsstub.3
new file mode 100644
index 0000000..6bce8a3
--- /dev/null
+++ b/man/dnsstub.3
@@ -0,0 +1,109 @@
+.TH qlibs: dnsstub
+.SH NAME
+dns \- stub resolver
+.SH SYNTAX
+.B #include \(dqdnsresolv.h\(dq
+
+int \fBdns_resolvconfip\fP(char \fIservers\fR[512],uint32 \fIscope\fR[32]);
+
+int \fBdns_transmit_start\fP(struct dns_transmit *\fIq\fR,const char \fIservers\fR[512],
+ int \fIflagrecursive\fR,const char *\fIq\fR,const char \fIqtype\fR[2],
+ const char \fIlocalip\fR[16]);
+.br
+int \fBdns_transmit_start6\fP(struct dns_transmit *\fIq\fR,const char \fIservers\fR[512],
+ int \fIflagrecursive\fR,const char *\fIq\fR,const char \fIqtype\fR[2],
+ const char \fIlocalip\fR[16],const uint32 \fIscopes\fR[32]);
+
+int \fBdns_sortip4\fP(char *\fIservers\fR,unsigned int \fIn\fR);
+.br
+int \fBdns_sortip6\fP(char *\fIservers\fR,unsigned int \fIn\fR);
+.SH DESCRIPTION
+.B dns_resolvconfip
+reads the name servers defined in
+.I /etc/resolv.conf
+and uses
+.B ip6_ifscan
+to fetch their IPv4/IPv6 addresses together with the scope for the LLU address.
+Up to
+.I 32
+name servers can be specified.
+
+Apart from the system-wide
+.I /etc/resolv.conf
+the IP addresses of name servers can preferrably be provided by means of the
+environment variable
+.I $DNSCACHEIP
+for each user application. The variable
+.I $DNSCACHEIP
+may include up to 32 name server IP addresses separated by white spaces:
+
+.EX
+ DNSCACHEIP="10.0.1.53 fe80::1%lo0 ::1"
+.EE
+
+.B dns_transmit_start
+and
+.B dns_transmit_start6
+use the list of name server IP's for a recursive or none-recursive
+query
+.I q
+of type
+.I qtype
+starting from IP address
+.I localip
+for which the
+.I struct dns_transmit
+provides the required book keeping information.
+.B dns_transmit_start6
+additionally is able to evaluate the given
+.I scope_id
+as information for the local interface in order
+to bind to the remote IPv6 LLU addresses. Usually
+.I scope_id
+defaults to
+.IR 0 .
+
+.B dns_sortip4
+and
+.B dns_sortip6
+randomize the list of name server IPs upon call and as result the first address
+is used to facilitate the name lookup.
+.IR FQDN .
+.SH "RETURN CODES"
+Different from the original djb implemtation, the
+following return code scheme is used:
+.TP 2
+rc > 0
+A 'positive' answer is given, thus results returned.
+.TP 2
+rc = 0
+A 'neutral' answer was provided, thus typically the
+operation succeeded, but without replies.
+.TP 2
+rc < 0
+An operational error was encountered.
+.TP 0
+Potentially, this needs to be treated specifically:
+.TP 2
+DNS_INT (rc = -4)
+Internal DNS operational error; ie. resources were not
+available.
+.TP 2
+DNS_COM (rc = -3)
+DNS communication error.
+.TP 2
+DNS_ERR (rc = -2)
+Parsing errors and others.
+.TP 2
+DNS_MEM (rc = -1)
+Memory error occured.
+.TP 0
+A 'safe' usage of return codes thus checks not only the presence
+of a return code, but rather additionally its sign.
+Negative return codes point to errors.
+.SH "SEE ALSO"
+http://cr.yp.to/djbdns/qualify.html,
+dns(3),
+ip4(3),
+ip6(3),
+socket_if(3)
diff --git a/man/env.3 b/man/env.3
new file mode 100644
index 0000000..c8d0bf2
--- /dev/null
+++ b/man/env.3
@@ -0,0 +1,68 @@
+.TH qlibs: env 3
+.SH NAME
+env \- manage variables in the environment
+.SH SYNTAX
+.B #include \(dqenv.h\(dq
+
+char **\fBenviron\fP;
+
+char *\fBenv_put\fP(char *\fINAME\fR,char *\fIvalue\fR);
+.br
+char *\fBenv_puts\fP(char *\fINAME=value\fR);
+.br
+char *\fBenv_set\fP(char *\fINAME=value\fR);
+.br
+char *\fBenv_unset\fP(char *\fINAME\fR);
+.br
+char *\fBenv_get\fP(char *\fINAME\fR);
+.br
+char *\fBenv_pick\fP();
+.br
+char *\fBenv_clear\fP();
+.SH DESCRIPTION
+The environment,
+.BR environ ,
+is a 0-terminated array of 0-terminated strings,
+called environment variables.
+Each environment variable is of the form
+.IR NAME\fB=\fIvalue .
+
+.B env_puts
+puts the string
+.I \'NAME=value\'
+into the environment.
+
+.B env_put
+assigns the new enviromment variable
+.I NAME
+with
+.IR value .
+
+.B env_set
+assigns an existing environment variable
+.I NAME
+with
+.IR value :
+.IR \'NAME=value\' .
+
+.B env_unset
+unsets an existing environment variable given as
+.IR NAME .
+
+.B env_get
+returns the assigned value of the first variable whose name is
+.IR NAME ,
+or
+.I 0
+if there is no such variable.
+
+.B env_pick
+returns any variable in the environment,
+or
+.I 0
+if the environment is empty.
+
+.B env_clear
+clears the whole envionment.
+.SH "SEE ALSO"
+environ(7)
diff --git a/man/error.3 b/man/error.3
new file mode 100644
index 0000000..b96be1f
--- /dev/null
+++ b/man/error.3
@@ -0,0 +1,75 @@
+.TH qlibs: error 3
+.SH NAME
+error \- syscall error codes and information
+.SH SYNTAX
+.B #include \(dqlogmsg.h\(dq
+
+extern int \fBerrno\fP;
+
+extern int \fBerror_intr\fP;
+.br
+extern int \fBerror_nomem\fP;
+.br
+extern int \fBerror_noent\fP;
+.br
+extern int \fBerror_txtbsy\fP;
+.br
+extern int \fBerror_io\fP;
+.br
+extern int \fBerror_exist\fP;
+.br
+extern int \fBerror_timeout\fP;
+.br
+extern int \fBerror_inprogress\fP;
+.br
+extern int \fBerror_wouldblock\fP;
+.br
+extern int \fBerror_again\fP;
+.br
+extern int \fBerror_pipe\fP;
+.br
+extern int \fBerror_perm\fP;
+.br
+extern int \fBerror_access\fP;
+
+char *\fBerror_str\fP(int \fIe\fR);
+
+int \fBerror_temp\fP(int \fIe\fR);
+UNIX syscalls provide detailed error codes in the
+.B errno
+variable.
+The
+.B error
+library provides portable names for a variety of possible
+.B errno
+values.
+
+.B error_str
+returns a printable string describing syscall error code
+.IR e .
+Normally
+.I e
+is
+.BR errno .
+
+.B error_temp
+returns
+.I 1
+if syscall error code
+.I e
+is a soft error,
+.I 0
+if it is a hard error. Normally
+.I e
+is
+.BR errno .
+
+A hard error is persistent:
+file not found, read-only file system, symbolic link loop, etc.
+
+A soft error is usually transient:
+out of memory, out of disk space, I/O error, disk quota exceeded,
+connection refused, host unreachable, etc.
+.SH "SEE ALSO"
+sysmsg(3),
+errno(2)
diff --git a/man/fd.3 b/man/fd.3
new file mode 100644
index 0000000..b22338d
--- /dev/null
+++ b/man/fd.3
@@ -0,0 +1,79 @@
+.TH qlibs: fd 3
+.SH NAME
+fd \- duplicate, move or close a file descriptor
+.SH SYNTAX
+.B #include \(dqfd.h\(dq
+
+int \fBfd_copy\fP(int \fIto\fR,int \fIfrom\fR);
+.br
+int \fBfd_move\fP(int \fIto\fR,int \fIfrom\fR);
+.br
+int \fBfd_coe\fP(int \fIfd\fR);
+.SH DESCRIPTION
+.B fd_copy
+copies
+descriptor
+.I from
+to descriptor
+.IR to .
+If
+.I to
+was already open,
+.B fd_copy
+closes it.
+.B fd_copy
+always leaves
+.I from
+intact;
+if
+.I to
+and
+.I from
+are the same number,
+.B fd_copy
+does nothing.
+.B fd_copy
+does not guarantee that
+.I to
+will remain open, if it was open, in case of error.
+
+.B fd_move
+moves
+descriptor
+.I from
+to descriptor
+.IR to .
+If
+.I to
+was already open,
+.B fd_move
+closes it.
+If the move is successful,
+.B fd_move
+closes
+.IR from .
+Exception:
+if
+.I to
+and
+.I from
+are the same number,
+.B fd_move
+does nothing.
+
+.B fd_coe
+closes
+.IR fd .
+.SH "RETURN CODES"
+.BR fd_copy ,
+.BR fd_move ,
+and
+.B fd_coe
+return
+.I 0
+on success,
+and
+.I -1
+on error.
+.SH "SEE ALSO"
+dup(2), fcntl(2)
diff --git a/man/fmt.3 b/man/fmt.3
new file mode 100644
index 0000000..ac9c985
--- /dev/null
+++ b/man/fmt.3
@@ -0,0 +1,90 @@
+.TH qlibs: fmt 3
+.SH NAME
+fmt \- ASCII representation of strings and integers
+.SH SYNTAX
+.B #include \(dqfmt.h\(dq
+
+unsigned int \fBfmt_str\fP(char *\fIdest\fR,const char *\fIsource\fR);
+.br
+unsigned int \fBfmt_strn\fP(char *\fIdest\fR,const char *\fIsource\fR,unsigned int \fImaxlen\fR);
+
+unsigned int \fBfmt_uint\fP(char *\fIdest\fR,unsigned int \fIsource\fR);
+.br
+unsigned int \fBfmt_uint0\fP(char *\fIdest\fR,unsigned int \fIsource\fR,unsigned int \fIn\fR);
+.br
+unsigned int \fBfmt_ulong\fP(char *\fIdest\fR,unsigned long \fIsource\fR);
+.br
+unsigned int \fBfmt_xlong\fP(char *\fIdest\fR,unsigned long \fIsource\fR);
+.br
+char \fBtohex\fP(char \fInum\fR);
+.br
+int \fBfromhex\fP(unsigned char \fIc\fR);
+.SH DESCRIPTION
+.B fmt_str
+copies all leading nonzero bytes from \fIsource\fR to \fIdest\fR
+and returns the number of bytes it copied.
+.B fmt_str
+does not append \\0.
+
+.B fmt_strn
+copies at most \fImaxlen\fR leading nonzero bytes from
+\fIsource\fR to \fIdest\fR and returns the number of bytes it copied.
+.B fmt_strn
+does not append \\0.
+
+.B fmt_uint
+writes an ASCII representation ('0' to '9', base 10) of
+\fIsource\fR to \fIdest\fR and returns the number of bytes written.
+.B fmt_uint
+does not append \\0.
+
+.B fmt_uint0
+writes an ASCII representation ('0' to '9', base 10) of
+\fIsource\fR to \fIdest\fR and returns the number of bytes written.
+The output is padded with '0'-bytes until it encompasses at least
+\fIn\fR bytes, but it will not be truncated if it does not fit.
+.B fmt_uint0
+does not append \\0.
+
+.B fmt_ulong
+writes an ASCII representation ('0' to '9', base 10) of
+\fIsource\fR to \fIdest\fR and returns the number of bytes written
+perhaps including a trailing \\0.
+.B fmt_ulong
+does not append \\0.
+
+.B fmt_xlong
+writes an ASCII representation ('0' to '9' and 'a' to 'f', base 16)
+of \fIsource\fR to \fIdest\fR and returns the number of bytes
+written.
+.B fmt_xlong
+does not append \\0.
+
+.B tohex
+reads the ASCII representation of a decimal \fInum\fR and returns its
+hexadecimal ASCII value; thus \'0\' -> \'0\' ... \'9\' -> \'9\',
+\'10\' -> \'a\' and finally \'15\' -> f'.
+
+.B fromhex
+reads the ACSII representation of a hexadecimal number \'0\' to \'f\'
+irrelevant of its case and returns its integer value.
+
+For convenience,
+.B fmt.h
+defines the integers
+.I FMT_LEN
+and
+.I FMT_ULONG
+to be big enough to the number of bytes it would have written.
+
+
+.SH "RETURN CODES"
+If \fIdest\fR equals FMT_LEN (i.e. is zero), all
+.B fmt_*
+routins return the number of bytes it would have written
+i.e. the number of leading nonzero bytes of \fIsource\fR
+perhaps including a \\0.
+.SH "SEE ALSO"
+byte(3),
+case(3),
+scan(3)
diff --git a/man/getln.3 b/man/getln.3
new file mode 100644
index 0000000..bb4ae7c
--- /dev/null
+++ b/man/getln.3
@@ -0,0 +1,102 @@
+.TH glibs: getln 3
+.SH NAME
+getln \ - read one line of data
+.SH SYNTAX
+.B #include \(dqgetln.h\(dq
+
+int \fBgetln\fP(&buffer_0,&sa,&match,sep);
+.br
+int \fBgetln2\fP(&buffer_0,&sa,&cont,&clen,sep);
+
+buffer \fIbuffer_0\fR;
+.br
+stralloc \fIsa\fR;
+.br
+int \fImatch\fR;
+.br
+int \fIsep\fR;
+.br
+char *\fIcont\fR;
+.br
+unsigned int \fIclen\fR;
+.SH DESCRIPTION
+.B getln
+reads a line of characters, terminated by a sep character, from
+.IR buffer_0 .
+It returns the line in
+.I sa
+and sets match to
+.IR 1 .
+If
+.B getln
+sees end-of-input before it sees
+.IR sep ,
+it returns the partial line in
+.I sa
+and sets match to
+.IR 0 .
+
+.B getln2
+reads a line of characters, terminated by a
+.I sep
+character, from
+.IR buffer_0 .
+The line is returned in two pieces. The first piece is stored in
+.IR sa .
+The second piece is
+.IR cont ,
+a pointer to
+.I clen
+characters inside the
+.I buffer_0
+buffer. The second piece must be copied somewhere else before
+.I ss
+is used again.
+If
+.B getln2
+sees end-of-input before it sees
+.IR sep ,
+it sets
+.I clen
+to
+.I 0
+and does not set
+.IR cont .
+It puts the partial line into
+.IR sa.
+.SH "RETURN CODES"
+.B getln
+normally returns
+.IR 0 .
+If it runs out of memory, or encounters an error from
+.IR ss ,
+it returns
+.IR -1 ,
+setting
+.I errno
+appropriately.
+
+.B getln2
+normally returns
+.IR 0 .
+If it runs out of memory, or encounters an error from
+.IR ss ,
+it returns
+.IR -1 ,
+setting
+.I errno
+appropriately.
+.SH NOTE
+The input buffer
+.I buffer_0
+is already pre-allocated.
+It can be used without initialization as synonym for STDIN.
+.SH CREDITS
+The
+.B getln
+and
+.B getln2
+man page were taken from Bruce Guenther and
+originally published by Dan Bernstein for qmail-1.03.
+.SH SEE ALSO
+stralloc(3)
diff --git a/man/getoptb.3 b/man/getoptb.3
new file mode 100644
index 0000000..f3e329b
--- /dev/null
+++ b/man/getoptb.3
@@ -0,0 +1,22 @@
+.TH qlibs: getoptb 3
+.SH NAME
+getoptb \- get option character from command line
+.SH SYNTAX
+.B #include \(dqgetoptb.h\(dq
+.SH DESCRIPTION
+Qlib's
+.B getopt
+is a replacement for the standard Unix
+.B getopt
+library, based on
+.B sgetopt
+and printing errors by means of
+.B buffer
+rather than
+.BR stdio .
+
+See
+.B getopt(3)
+for interface details.
+.SH "SEE ALSO"
+buffer(3)
diff --git a/man/iopause.3 b/man/iopause.3
new file mode 100644
index 0000000..c7ab9fb
--- /dev/null
+++ b/man/iopause.3
@@ -0,0 +1,87 @@
+.TH qlibs: iopause 3
+.SH NAME
+iopause \- stateful handling of events based on the poll interface or file descriptors
+.SH SYNTAX
+.B #include \(dqioause.h\(dq
+
+int \fBiopause\fP(iopause_fd *\fIx\fR,unsigned int \fIlen\fR,struct taia *\fIdeadline\f$,struct taia *\fIstamp\fR);
+.SH DESCRIPTION
+.B iopause
+checks for file descriptor readability or writeability as specified
+by \fIx\fR[0].fd, \fIx\fR[0].events, \fIx\fR[1].fd, \fIx\fR[1].events, ..., \fIx\fR[\fIlen\fR-1].fd,
+\fIx\fR[\fIlen\fR-1].events. If \fIx\fR[i].events includes the bit IOPAUSE_READ,
+.B iopause
+checks for readability of the descriptor \fIx\fR[i].fd;
+if \fIx\fR[i].events includes the bit IOPAUSE_WRITE,
+.B iopause
+checks for writability of the descriptor
+\fIx\fR[i].fd; other bits in \fIx\fR[i].events have undefined effects.
+
+.B iopause
+sets the IOPAUSE_READ bit in \fIx\fR[i].revents if it finds that \fIx\fR[i].fd
+is readabled and it sets the IOPAUSE_WRITE bit in \fIx\fR[i].revents if it finds
+that \fIx\fR[i].fd is writable.
+Beware that readability and writeability may be destroyed at any moment
+by other processes with access to the same file \fIx\fR[i].fd refers to.
+
+If there is no readability or writeability to report,
+.B iopause
+waits until \fIdeadline\fR for something to happen.
+.B iopause
+will return before \fIdeadline\fR if a
+descriptor becomes readable or writeable, or an interrupting signal
+arrives, or some system-defined amount of time passes.
+.B iopause
+sets
+.I revents
+in any case.
+
+You must put a current timestamp into \fIstamp\fR before calling
+.BR iopause .
+In case the the current timestamp is older than the previous one (ie. due to daylight-saving)
+negative values are omitted.
+
+.SH "IMPLEMENTATION NOTES"
+The current implementation of
+.B iopause
+uses the \fBpoll\fR interface if that is available.
+On some systems, \fBpoll\fR needs to dynamically allocate kernel
+memory. In case not enough memory is available,
+.B iopause
+will return immediately and will report (often incorrectly) that no descriptors are
+readable or writeable.
+
+If the \fBpoll\fR interface is not available,
+.B iopause
+uses the \fBselect\fR function. This function
+cannot see descriptor numbers past a system-defined limit, typically 256
+or 1024;
+.I iopause
+will artificially pretend that those descriptors are never readable or writeable.
+
+Future implementations of
+.B iopause
+may work around these problems on some
+systems, at the expense of chewing up all available CPU time.
+
+Both \fBpoll\fR and \fBselect\fR use relative timeouts rather than absolute deadlines.
+Some kernels round the timeout down to a multiple of 10 milliseconds; this
+can burn quite a bit of CPU time as the deadline approaches.
+.B iopause
+compensates for this by adding 20 milliseconds to the timeout.
+In case the current timestamp is older than the previous one (ie. due to daylight-saving)
+the timeout is set to 20 milliseconds.
+.SH "RETURN CODES"
+.B iopause
+reads and deploys the return codes of the
+.I poll
+and
+.I select
+call. Only positive return values shall be considered by the calling routines for a succcessful
+invocation.
+.SH CREDITS
+Parts of the description are taken from the 'libowfat' man page.
+.SH "SEE ALSO"
+select(2),
+poll(3),
+taia(3)
diff --git a/man/ip4.3 b/man/ip4.3
new file mode 100644
index 0000000..d6b5928
--- /dev/null
+++ b/man/ip4.3
@@ -0,0 +1,73 @@
+.TH qlibs: ipv4
+.SH NAME
+ipv4 \- IPv4 address evaluation and conversion
+.SH SYNTAX
+.B #include \(dqip.h\(dq
+
+unsigned int \fBip4_fmt\fP(char *\fIs\fR,char \fIip[4]\fR);
+.br
+unsigned int \fBip4_scan\fP(const char *\fIs\fR,char \fIip[4]\fR);
+.br
+unsigned int \fBip4_scanbracket\fP(char *\fIs\fR,char \fIip[4]\fR);
+.br
+unsigned int \fBip_scanbracket\fP(char *\fIip_str\fR,char *\fIs\fR);
+.br
+unsigned int \fBip4_cidr\fP(char *\fIs\fR,char \fIip[4]\fR,unsigned long *\fIplen\fR);
+.br
+unsigned int \fBip4_bytestring\fP(stralloc *\fIip4string\fR,char \fIip[4]\fR,int \fIplen\fR);
+.SH DESCRIPTION
+.B ip4_fmt
+reads the
+.I char[4]
+IPv4 address and returns a dotted-decimal IPv4 address string
+.IR 1.2.3.4 .
+
+.B ip4_scan
+reads an IPv4 address string
+.I 1.2.3.4
+and converts it to the
+.I char[4]
+IPv4 address.
+
+.B ip4_scanbracket
+reads an IPv4 address string enclosed in brackets
+.I [1.2.3.4]
+removes the brackets and calls
+.B ip4_scan
+on the result.
+
+.B ip_scanbracket
+reads an IP address string enclosed in brackets
+.I [1.2.3.4]
+or
+.IR [fe80::1] ,
+removes the brackets and calls
+.B ip4_scan
+or
+.B ip6_scan
+upon detecting an IPv6 address on the result.
+
+.B ip4_cidr
+reads the CIDR IPv4 address string
+.I 1.2.3.4/15
+determines the prefix as integer
+.I plen
+and calls
+.BR ip4_scan .
+If no prefix is identified, it returns 32.
+
+.B ip4_bytestring
+reads the IPv4 address given as
+.I char[4]
+while returning a 0-terminated 'bytestring' representation
+.I 1001001....
+up to the given prefix length
+.IR plen .
+.SH "RETURN CODES"
+The
+.B ip(4)*
+programs return the number of bytes processed.
+.B ip4_bytestring
+returns regative numbers on failure.
+.SH "SEE ALSO"
+ip6(3), socket_if(3)
diff --git a/man/ip6.3 b/man/ip6.3
new file mode 100644
index 0000000..f3f5cb1
--- /dev/null
+++ b/man/ip6.3
@@ -0,0 +1,98 @@
+.TH qlibs: ipv6
+.SH NAME
+ipv6 \- IPv6 address evaluation and conversion
+.SH SYNOPSIS
+.B #include \(dqip.h\(dq
+
+unsigned int \fBip6_fmt\fP(char *\fIs\fR,char \fIip[16]\fR);
+.br
+unsigned int \fBip6_fmt_flat\fP(char *\fIs\fR,char \fIip[16]\fR);
+.br
+unsigned int \fBip6_scan_flat\fP(const char *\fIs\fR,char \fIip[16]\fR);
+.br
+unsigned int \fBip6_scan\fP(const char *\fIs\fR,char \fIip[16]\fR);
+.br
+unsigned int \fBip6_scanbracket\fP(const char *\fIs\fR,char \fIip[16]\fR);
+.br
+unsigned int \fBip6_ifscan\fP(char *\fIs\fR,char \fIip[16]\fR,stralloc *\fIifname\fR);
+.br
+unsigned int \fBip6_cidr\fP(char *\fIs\fR,char \fIip[16]\fR,unsigned long *\fIplen\fR);
+.br
+unsigned int \fBip6_bytestring\fP(stralloc *\fIip6string\fR,char \fIip[16]\fR,int \fIplen\fR);
+.SH DESCRIPTION
+.B ip6_fmt
+reads the
+.I char[16]
+IPv6 address and returns a compactified hexadecimal IPv6 address string
+.IR fe80::fefe .
+
+.B ip6_fmt_flat
+reads the
+.I char[16]
+IPv6 address and returns all hexadecimal IPv6 address labels as string
+.IR fe80:0000:....:fefe .
+
+.B ip6_scan
+reads a compactified IPv6 address string
+.I fe80::fefe
+and converts it to the
+.I char[16]
+IPv6 address.
+
+.B ip6_scan_flat
+reads an uncompressed IPv6 address als hexadecimal string
+and returns it's
+.I char[16]
+IPv6 address.
+
+.B ip6_scanbracket
+reads a compactified IPv6 address string enclosed in brackets
+.I [fe80::fefe]
+removes the brackets and calls
+.B ip6_scan
+on the result.
+
+.B ip6_ifscan
+reads the compactified IPv6 address string appended with the
+interface_name
+.I fe80::fefe%eth0
+returns
+.I ifname
+and calls
+.B ip6_scan
+for the (stripped) IPv6 address.
+
+.B ip6_cidr
+reads the compactified CIDR IPv6 address string
+.I fe80::fefe/64
+determines the prefix as integer
+.I plen
+and calls
+.BR ip6_scan .
+If no prefix is identfied, it returns 128.
+
+.B ip6_bytestring
+reads the IPv6 address given as
+.I char[16]
+while returning a 0-terminated 'bytestring' representation
+.I 1001001....
+up to the given prefix length
+.IR plen .
+
+The macro
+.B ipv6_v4mapped
+reads the IPv6 addresses given as
+.I char[16]
+and returns
+.I 0
+in case the given IPv6 address is not
+a IPv4 mapped address.
+.SH "RETURN CODES"
+The
+.B ip(6)*
+programs return the number of bytes processed.
+.B ip6_bytestring
+returns negative numbers on failure.
+.SH "SEE ALSO"
+ip4(3),
+socket_if(3)
diff --git a/man/logmsg.3 b/man/logmsg.3
new file mode 100644
index 0000000..f819a18
--- /dev/null
+++ b/man/logmsg.3
@@ -0,0 +1,109 @@
+.TH qlibs: logmsg 3
+.SH NAME
+logmsg \- handle system errors and application log messages
+.SH SYNTAX
+.B #include \(dqlogmsg.h\(dq
+
+int logmsg(const char *who, int ecode, unsigned int classs, char *msg)
+
+\fBerr_sys\fR(w,e) logmsg(w,e,FATAL,"")
+.br
+\fBerr_sys_plus\fR(w,e,m) logmsg(w,e,FATAL,m)
+.br
+\fBerr_tmp\fR(w,e) logmsg(w,e,WARN,"")
+.br
+\fBerr_tmp_plus\fR(w,e,m) logmsg(w,e,WARN,m)
+.br
+\fBerr_int\fR(w,e,c) logmsg(w,e,c,"")
+.br
+\fBerr_int_plus\fR(w,e,c,m) logmsg(w,e,c,m)
+.br
+\fBlog_who\fR(w,m) logmsg(w,0,LOG,m)
+.br
+\fBlog_anon\fR(m) logmsg("",0,LOG,m)
+.SH DESCRIPTION
+\fBlogmsg\fR prints error, warning, or info/logging messages to stderr
+and potentially terminates the calling program, depending on the \fIclass\fR given.
+\fIwho\fR is the name of the program, \fIecode\fR is an error code,
+\fIclass\fR determines the behavior upon call and \fImsg\fR is the logging message.
+Read "error.h" to learn more about related constants.
+.SH ECODE
+\fIecode\fR is the error code and subject to be displayed in the log file and
+potentially used upon exit if the \fIclass\fR equals \fBERROR\fR, \fBFATAL\fR, or \fBDROP\fR.
+
+To avoid conflicts with syscall error codes, appplication defined error codes should be negative.
+The values \fI-15\fR, \fI-100\fR and \fI-111\fR are reserved for backward compatibility.
+.SH CLASS
+The \fIclass\fr parameter indicates how the application handles exceptions and displays the
+log message.
+.TP 4
+o
+\fBLOG\fR, \fBINFO\fR, \fBALERT\fR, \fBWARN\fR - display message and continue operation
+.TP 4
+o
+\fBDROP\fR - display warning message and continue while returning to the calling program
+.TP 4
+o
+\fBUSAGE\fR, \fBSYNTAX\fR, \fBFATAL\fR, \fBERROR\fR
+- display error message and exit application with error code
+.RE
+
+\fBINFO\fR, \fBALERT\fR, \fBWARN\fR, \fBDROP\fR, \fBUSAGE\fR, and \fBFATAL\fR as well
+as \fBERROR\fR display the respective class string like \fIwarning:\fR in the log message,
+while \fBLOG\fR shows the log message only.
+
+The class \fBFATAL\fR should be used for system error codes only, rather \fBERROR\fR
+and \fBWARN\fR shall be set in conjunction with an application error/warning.
+.SH MESSAGE
+If the custom message \fImsg\fR is given, it will be printed additionally.
+.SH FORMAT
+The log message format consists of the tokens
+\fIwho\fR: (\fIecode\fR) \fImsg\fR : \fImsg\fR.
+.I ecode
+is displayed only for classes \fBFATAL\fR, \fBERROR\fR, or \fBDROP\fR.
+.I msg
+is the system's explanation according to the variable
+.I errno
+if provided.
+.SH NOTES
+.I logmsg.c
+uses
+.I errstr.c
+routines.
+Error codes and classes are defined in
+.I error.h
+and included by
+.IR logmsg.h .
+.SH "EXIT CODE"
+\fBlogmsg\fR exits \fIecode\fR for classes \fBERROR\fR, \fBFATAL\fR, \fBSYNTAX\fR,
+and \fBUSAGE\fR terminating the application.
+.SH HISTORY
+Dan Bernstein used sets of \fIstrerr_dieY*()\fR and \fIstrerr_warnY()\fR messages
+which explicitely determine the message and behavior class.
+Other classes were occasionally defined on demand, such als \fIusage()\fR.
+
+Kai Peter introduced the \fIerrmsg\fR facility in his \fBqlibs\fR
+including a \fBsyslog\fR compliant \fIseverity\fR as second parameter.
+.SH EXAMPLES
+The macro definitions uses \fBw\fR for the calling program,
+\fBe\fR for error code, \fBc\fR for class, and \fBm\fR for message.
+
+ #include "logmsg.h"
+ #define WHO "my_prog"
+
+ err_sys(WHO,errno);
+ err_sys_plus(WHO,-111,"additional message");
+
+ err_tmp("",-100);
+ err_tmp_plus("",errno,"additional message");
+
+ log_who(WHO,"message");
+
+log_anon() is like log_who() but doesn't print the caller name.
+
+An user defined message \fBs\fR can be build from multiple arguments by using the \fIB\fR
+(build) macro:
+
+ err_sys_plus((errno),B("unable to run: ",*argv));
+.SH "SEE ALSO"
+syslog(3)
diff --git a/man/pathexec.3 b/man/pathexec.3
new file mode 100644
index 0000000..41dc978
--- /dev/null
+++ b/man/pathexec.3
@@ -0,0 +1,124 @@
+.TH qlibs: pathexec 3
+.SH NAME
+pathexec \- run a program within a given environment
+.SH SYNTAX
+.B #include \(dqpathexec.h\(dq
+
+\fBpathexec_run\fP(const char *\fIp\fR,char **\fIa\fR,char **\fIe\fR);
+.br
+\fBpathexec\fP(char *const *\fIa\fR);
+.br
+\fBpathexec_env\fP(const char *\fIs\fR,char *\fIt\fR);
+.SH DESCRIPTION
+.B pathexec_run
+searches for a program named
+.IR p .
+It replaces the current process with a copy of that program.
+The main function in that program will be given arguments
+.I a
+and environment
+.IR e .
+.B pathexec_run
+looks for
+.I p
+as specified by the
+.I $PATH
+environment variable.
+.I $PATH
+is a colon-separated list of directories
+.IR d ;
+.B pathexec_run
+tries
+.B execve
+on files named
+.IR d/p ,
+in the order that the directories appear inside
+.IR $PATH .
+An empty directory name is treated as a single dot.
+
+If
+.I $PATH
+is not set,
+.B pathexec_run
+uses the path
+.IR /bin:/usr/bin ;
+i.e., it tries
+.B execve
+on
+.IR /bin/p ,
+then
+.IR /usr/bin/p .
+
+If
+.I p
+contains a slash,
+.B pathexec_run
+ignores
+.I $PATH
+and simply runs
+.B execve
+on a file named
+.IR p .
+
+.B pathexec
+calls
+.B pathexec_run
+with program name
+.IR a[0] ,
+arguments
+.IR a ,
+and the same environment as the current process,
+modified as described below.
+.B pathexec
+has the same return behavior as
+.BR pathexec_run .
+.B pathexec_env
+modifies the environment used by
+.BR pathexec .
+It removes a variable named
+.IR s,
+if one exists. It then adds a variable named
+.I s
+with value
+.IR t,
+if the pointer
+.I t
+is nonzero. The name
+.I s
+must not contain
+.IR = .
+.SH "RETURN CODES"
+Normally
+.B pathexec_run
+does not return, because the process has been replaced.
+However, if all the
+.B execve
+attempts fail,
+.B pathexec_run
+returns, setting
+.I errno
+to the most interesting error returned by
+.BR execve .
+Furthermore,
+.B pathexec_run
+returns immediately if an
+.B execve
+attempt fails with an error other than
+.IR error_noent ,
+.IR error_acces ,
+.IR error_perm ,
+or
+.IR error_isdir .
+This list is subject to change.
+
+Normally
+.B pathexec_env
+returns
+.IR 1 .
+If it is unable to allocate memory, it returns
+.IR 0 ,
+leaving the
+.B pathexec
+environment alone.
+.SH "SEE ALSO"
+error(3)
diff --git a/man/scan.3 b/man/scan.3
new file mode 100644
index 0000000..a466daa
--- /dev/null
+++ b/man/scan.3
@@ -0,0 +1,81 @@
+.TH qlibs: scan 3
+.SH NAME
+scan \- string to integer conversion
+.SH SYNTAX
+.B #include \(dqscan.h\(dq
+
+unsigned int \fBscan_8long\fP(const char *\fIsrc\fR,unsigned long *\fIdest\fR);
+.br
+unsigned int \fBscan_uint\fP(const char *\fIsrc\fR,int *\fIdest\fR);
+.br
+unsigned int \fBscan_long\fP(const char *\fIsrc\fR,unsigned long *\fIdest\fR);
+.br
+unsigned int \fBscan_ulong\fP(const char *\fIsrc\fR,unsigned long *\fIdest\fR);
+.br
+unsigned int \fBscan_xint\fP(const char *\fIsrc\fR,int *\fIdest\fR);
+.br
+unsigned int \fBscan_xlong\fP(const char *\fIsrc\fR,unsigned long *\fIdest\fR);
+.SH DESCRIPTION
+.B scan_8long
+parses an unsigned long integer in octal ASCII representation
+from \fIsrc\fR and writes the result into \fIdest\fR. It returns the
+number of bytes read from \fIsrc\fR.
+
+.B scan_uint
+parses an unsigned integer in decimal ASCII representation
+from \fIsrc\fR and writes the result into \fIdest\fR. It returns the
+number of bytes read from \fIsrc\fR.
+
+.B scan_ulong
+parses an unsigned long integer in decimal ASCII representation
+from \fIsrc\fR and writes the result into \fIdest\fR. It returns the
+number of bytes read from \fIsrc\fR.
+Leading + or - or space (or anything outside of 0-9) is not accepted.
+The libc conventions of "023" for octal or "0x23" for hexadecimal are
+not supported.
+.B scan_ulong
+will abort the scan if the next character is not a digit, or
+if it is a digit but adding it to the number would lead to an integer
+overflow.
+.B scan_ulong
+returns the number of characters successfully scanned and
+processed from src.
+
+.B scan_long
+includes the same logic as
+.B scan_ulong
+but now on a signed long integer in decimal ASCII format while
+recognizing the leading '+' or '-' sign.
+
+.B scan_xint
+parses an unsigned integer in hexadecimal ASCII representation
+from \fIsrc\fR and writes the result into \fIdest\fR. It returns the
+number of bytes read from \fIsrc\fR.
+
+.B scan_xlong
+parses an unsigned long integer in hexadecimal ASCII
+representation from \fIsrc\fR and writes the result into \fIdest\fR. It
+returns the number of bytes read from \fIsrc\fR.
+.B scan_xlong
+understands both upper and lower case letters.
+.B scan_xlong
+does not expect or understand a "0x" prefix.
+.SH EXAMPLES
+scan_ulong("23",&i) -> i=23, return 2
+
+scan_ulong("+23",&i) -> return 0
+
+scan_ulong("-23",&i) -> return 0
+
+scan_ulong(" 23",&i) -> return 0
+
+scan_ulong("23,42",&i) -> i=23, return 2
+
+scan_ulong("023",&i) -> i=23, return 3
+
+scan_ulong("0x23",&i) -> i=0, return 1
+
+scan_ulong("4294967296",&i) -> i=429496729, return 9 // 32-bit system
+.SH "SEE ALSO"
+case(3),
+byte(3)
diff --git a/man/socket_bind.3 b/man/socket_bind.3
new file mode 100644
index 0000000..434e45c
--- /dev/null
+++ b/man/socket_bind.3
@@ -0,0 +1,117 @@
+.TH qlibs: socket_bind 3
+.SH NAME
+socket_bind \- binding a TCP/UDP socket to a local IP address, port,
+and perhaps scope_id
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_bind4\fP(int \fIs\fR,char \fIip\fR[4],uint16 \fIport\fR);
+.br
+int \fBsocket_bind4_reuse\fP(int \fIs\fR,char \fIip\fR[4],uint16 \fIport\fR);
+
+int \fBsocket_bind6\fP(int \fIs\fR,char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+.br
+int \fBsocket_bind6_reuse\fP(int \fIs\fR,char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+
+int \fBsocket_bind\fP(int \fIs\fR,char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+.br
+int \fBsocket_bind_reuse\fP(int \fIs\fR,char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+.SH DESCRIPTION
+.B socket_bind4
+sets the local IP address and TCP/UDP port of a TCP/UDP
+socket \fIs\fR to \fIip\fR and \fIport\fR respectively.
+
+.B socket_bind4_reuse
+sets the local IP address and TCP/UDP port of a
+TCP/UDP socket \fIs\fR to \fIip\fR and \fIport\fR respectively.
+Unlike
+.BR socket_bind4 ,
+this function will also tell the operating system
+that the address is to be reused soon, which turns off the normal pause
+before this IP and port can be bound again.
+
+.B socket_bind6
+sets the local IP address and TCP/UDP port of a TCP/UDP
+socket \fIs\fR to \fIip\fR, \fIport\fR and \fIscope_id\fR respectively.
+
+.B socket_bind6_reuse
+sets the local IP address and TCP/UDP port of a TCP/UDP socket \fIs\fR
+to \fIip\fR, \fIport\fR and \fIscope_id\fR respectively.
+Unlike
+.BR socket_bind6 ,
+this function will also tell the operating system
+that the address is to be reused soon, which turns off the normal pause
+before this IP and port can be bound again.
+
+.B socket_bind
+sets the local IPv4/IPv6 address and TCP/UDP port of a TCP/UDP
+socket \fIs\fR to \fIip\fR, \fIport\fR, and \fIscope_id\fR respectively.
+
+For IPv4 and IPv4-mapped IPv6 addresses
+.B socket_bind
+will use
+.B socket_bind4
+or otherwise
+.BR socket_bind6 .
+
+.B socket_bind_reuse
+sets the local IPv4/IPv6 address and TCP/UDP port of a TCP/UDP socket \fIs\fR
+to \fIip\fR, \fIport\fR, and \fIscope_id\fR respectively.
+Unlike
+.BR socket_bind ,
+this function will also tell the operating system
+that the address is to be reused soon, which turns off the normal pause
+before this IP and port can be bound again.
+
+For IPv4 and IPv4-mapped IPv6 addresses
+.B socket_bind_reuse
+will use
+.B socket_bind4_reuse
+or otherwise
+.BR socket_bind6_reuse .
+.SH "AUTOMATIC BINDING"
+If the IPv4 address is 0 or the IPv6 address is ::, the operating system
+chooses a local IP address.
+If \fIport\fR is 0, the operating system chooses a port.
+\fIscope_id\fR is usually 0, except for IPv6 LLU addresses where
+.B socket_getifidx
+can be used to determine
+.I scope_id
+from the interface name.
+.SH "RETURN CODES"
+Normally, all
+.I socket_bind*
+routines return
+.IR 0 .
+If anything goes wrong, the return code is
+.I -1
+and setting
+.I errno
+appropriately.
+.SH EXAMPLE
+ #include <socket_if.h>
+ #include <ip.h>
+
+ int \fIs\fR;
+ char \fIlcoalip\fR[16];
+ char \fIremoteip\fR[16];
+ uint16 \fIp\fR = 0;
+ uint32 \fIscope_id\fR = 0;
+
+ if (ip6_isv4mapped(ip))
+ s = socket_tcp4();
+ else
+ s = socket_tcp6();
+ if (s == -1)
+ err_tmp(111,"unable to create TCP socket: ");
+
+ socket_connect(s,remoteip,p,scope_id);
+.SH "SEE ALSO"
+socket_if(3),
+socket_connect(3),
+socket_info(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_connect.3 b/man/socket_connect.3
new file mode 100644
index 0000000..e289393
--- /dev/null
+++ b/man/socket_connect.3
@@ -0,0 +1,110 @@
+.TH qlibs: socket_connect 3
+.SH NAME
+socket_connect \- initiate or test a socket connection to a remote IPv4/IPv6 address
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_connect4\fP(int \fIs\fR,const char \fIip\fR[4],uint16 \fIport\fR);
+.br
+int \fBsocket_connect6\fP(int \fIs\fR,const char \fIip\fR[16],uint16 \fIport\fR,
+ uint32 \fIscope_id\fR);
+.br
+int \fBsocket_connect\fP(int \fIs\fR,const char \fIip\fR[16],uint16 \fIport\fR,
+ uint32 \fIscope_id\fR);
+
+int \fBsocket_connected\fP(int \fIs\fR);
+.SH DESCRIPTION
+.B socket_connect4
+attempts to make a connection from TCP or UDP socket \fIs\fR to
+TCP port \fIport\fR on IP address \fIip\fR.
+You can call
+.B socket_connect4
+without calling
+.BR socket_bind4 .
+This has the effect as first calling
+.B socket_bind4
+with IP address 0.0.0.0 and port 0.
+
+.B socket_connect6
+attempts to make a connection from TCP or UDP socket \fIs\fR to
+TCP port \fIport\fR on IP address \fIip\fR and \fIscope_id\fR.
+The meaning of \fIscope_id\fR is dependent on the implementation and
+IPv6 IP. For link-local IPv6 addresses it specifies the outgoing
+interface index. From a given interface name (e.g. "eth0")
+it's index can be retrieved with
+.BR socket_getifidx .
+\fIscope_id\fR should normally be set to 0.
+You can call
+.B socket_connect6
+without calling
+.BR socket_bind6 .
+This has the effect as first calling
+.B socket_bind6
+with IP address :: and port 0.
+
+.B socket_connect
+attempts to make a connection from TCP socket \fIs\fR to
+TCP port \fIport\fR on IP address \fIip\fR and \fIscope_id\fR
+calling
+.BR socket_connect6 .
+If however, \fIip\fR is an IPv4 or IPv4-mapped IPv6 address
+.B socket_connect4
+is called instead.
+
+Once a socket is connected, you can use the read and write
+system calls to transmit data.
+
+.B socket_connected
+can be used to verify, whether a background connection failed or
+succeeded, thus \fIs\fR became writable or not.
+.SH EXAMPLE
+ #include <socket_if.h>
+
+ int \fIs\fR;
+ char \fIlocalip\fR[16];
+ char \fIremoteip\fR[16];
+ uint16 \fIp\fR = 0;
+
+ s = socket_tcp();
+ socket_bind(s,localip,p,0);
+ socket_connect(s,remoteip,p,0);
+
+ if (socket_connected(s) != 1)
+ err_tmp(""111,fatal,"unable to setup TCP connection: ");
+.SH "RETURN CODES"
+.BR socket_connect4 ,
+.BR socket_connect6
+and
+.BR socket_connect
+may return
+.IR 0 ,
+to indicate that the connection succeeded (and succeeded immediately,
+if the socket is non-blocking)
+.IR -1 ,
+setting
+.I errno
+to error_inprogress or error_wouldblock, to indicate
+that the socket is non-blocking
+.IR -1 ,
+setting
+.I errno
+to something else, to indicate that the connection
+failed (and failed immediately, if the socket is non-blocking).
+
+.B socket_connected
+returns
+.I 1
+if \fIs\fR is a socket and a connection is established,
+.I 0
+otherwise and setting
+.I errno
+appropriately.
+.SH "SEE ALSO"
+socket_if(3),
+socket_info(3),
+socket_bind(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_if.3 b/man/socket_if.3
new file mode 100644
index 0000000..1c1ef70
--- /dev/null
+++ b/man/socket_if.3
@@ -0,0 +1,97 @@
+.TH qlibs: socket_if 3
+.SH NAME
+socket_if \- retrieve scope_id for interface name and vice versa
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+uint32 \fBsocket_getifidx\fP(const char *\fIifname\fR);
+
+const char *\fBsocket_getifname\fP(uint32 \fIscope_id\fR);
+.SH DESCRIPTION
+.B socket_getifidx
+returns the \fIscope_id\fR of an interface named as
+.I ifname
+typically ''eth0''.
+
+.B socket_getifname
+retrieves from the operating system's assigned
+.I scope_id
+the interface name
+.IR ifname .
+.SH INTERFACE_NAME VERSUS SCOPE_ID
+For IPv6 LLU addresses an additional
+.I ifname
+(interface name) has to be provided accompanying the IPv6 address:
+.IR fe80::1%eth0 .
+The operating systems rather uses
+.I scope_id
+as index for
+.IR ifname .
+
+For global IPv6 and ULA addresses
+.I ifname
+can be set to
+.IR 0 .
+Since IPv4 addresses on any interface are always unique,
+simply use
+.I 0
+for all cases.
+.SH BACKGROUND
+Qlib's socket routines provide an easy API to setup
+TCP or UDP connections over IPv4 or IPv6 networks. Together with
+Qlib's IP address parsing capabilities, a set of high-level
+socket routines allow a common IPv4/IPv6 handling.
+.SH SOCKET FILES
+.TP 5
+.B socket_bind.c
+bind to or reuse the local IPv4/IPv6 address and port
+for a socket connection
+.TP 5
+.B socket_connect.c
+attempts to setup a TCP or UDP client connection
+.TP 5
+.B socket_info.c
+get local/remote IPv4/IPv6 address of socket
+.TP 5
+.B socket_recv.c
+set up a receiving IPv4/IPv6 connection
+.TP 5
+.B socket_send.c
+send UDP datagram over a IPv4 or IPv6 connection
+.TP 5
+.B socket_setup.c
+listen to and accept an IPv4/IPv6 TCP socket connection
+.TP 5
+.B socket_tcp.c
+create a non-blocking TCP stream socket
+.TP 5
+.B socket_udp.c
+create a non-blocking UDP datagram socket
+.SH USAGE
+Most of the above files include their IPv4 and
+IPv6 counterparts together with a combined usage
+requiring in addition a
+.I scope_id
+or simply
+.IR 0 .
+IPv4 addresses are usually converted upon reading to
+IPv4-mapped IPv6 addresses using Qlib's IP address
+parsing functions.
+IPv4 and IPv6 socket calls - if required -
+need to be distinguished
+by the calling routines testing
+
+.EX
+ ip6_isv4mapped(ip)
+.EE
+
+Otherwise, the unified IPv6/IPv4 versions will be used.
+.SH "SEE ALSO"
+socket_bind(3),
+socket_connect(3),
+socket_info(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_info.3 b/man/socket_info.3
new file mode 100644
index 0000000..899a7cb
--- /dev/null
+++ b/man/socket_info.3
@@ -0,0 +1,47 @@
+.TH socket_info 3
+.SH NAME
+socket_info \- retrieving IP connection information for an existing socket
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_local\fP(int \fIs\fR,char \fIip\fR[16],
+ uint16 *\fIport\fR,uint32 *\fIscope_id\fR);
+
+int \fBsocket_remote\fP(int \fIs\fR,char \fIip\fR[16],
+ uint16 *\fIport\fR,uint32 *\fIscope_id\fR);
+.SH DESCRIPTION
+.B socket_local
+returns the local IPv6 or IPv4-mapped IPv6 address as \fIip\fR,
+port as \fIport\fR and perhaps the scope_id as \fIscope_id\fR for the UDP or TCP socket.
+
+.B socket_remote
+returns the remote IPv6 or IPv4-mapped IPv6 address as \fIip\fR,
+port as \fIport\fR and perhaps the scope_id as \fIscope_id\fR for the UDP or TCP socket.
+
+.SH "RETURN CODES"
+If something goes wrong,
+.B socket_local
+and
+.B socket_remote
+return
+.IR -1 ,
+setting
+.I errno
+appropriately.
+.SH EXAMPLE
+#include <socket_if.h>
+ int \fIs\fR;
+ char \fIip\fR[16];
+ uint16 \fIport\fR;
+
+ if (socket_remote(s,ip,&port,0) == -1)
+ err_tmp("",111,"unable to get remote address: ");
+.SH "SEE ALSO"
+socket_if(3),
+socket_bind(3),
+socket_connect(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_recv.3 b/man/socket_recv.3
new file mode 100644
index 0000000..bebef08
--- /dev/null
+++ b/man/socket_recv.3
@@ -0,0 +1,56 @@
+.TH qlibs: socket_recv 3
+.SH NAME
+socket_recv \- receive UDP datagrams over IPv4/IPv6 connections
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_recv\fP(int \fIs\fR, const char *\fIbuf\fR, unsigned int \fIlen\fR,
+ const char \fIip\fR[16], uint16 *\fIport\fR, uint32 *\fIscope_id\fR);
+.SH DESCRIPTION
+.B socket_recv
+reads \fIlen\fR bytes starting at \fIbuf\fR in a UDP datagram
+over the socket \fIs\fR while providing information about the
+remote IP address \fIip\fR and the UDP \fIport\fR and
+the perhaps \fIscope_id\fR of the receiving interface.
+
+You can call
+.B socket_recv
+without calling
+.BR socket_bind .
+This has the effect as first calling
+.B socket_bind
+with IP address :: and port 0.
+.SH RETURN VALUE
+.B socket_recv
+returns
+.IR 0 ,
+otherwise
+.I -1
+and sets
+.I errno
+appropriately.
+.SH EXAMPLE
+ #include <socket_if.h>
+ #include <ip.h>
+
+ int \fIs\fR;
+ char \fIlocalip\fR[16];
+ char \fIremoteip\fR[16];
+ uint16 \fIp\fR, \fIport\fR;
+ uint32 \fIscope_id\fR;
+ unsigned int \fIlen\fR;
+ int \fIr\fR;
+ char buf[MTUSIZE+1];
+
+ s = socket_udp();
+ socket_bind_reuse(s,localip,p,0);
+ r = socket_recv(s,buf,len,remoteip,&port,&scope_id);
+.SH SEE ALSO
+socket_if(3),
+socket_info(3),
+socket_bind(3),
+socket_connect(3)
+socket_send(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_send.3 b/man/socket_send.3
new file mode 100644
index 0000000..cf74300
--- /dev/null
+++ b/man/socket_send.3
@@ -0,0 +1,76 @@
+.TH qlibs: socket_send 3
+.SH ROUTINES
+socket_send \- sending data over a UDP socket
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_send4\fP(int \fIs\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR,
+ const char \fIip\fR[4],uint16 \fIport\fR);
+.br
+int \fBsocket_send6\fP(int \fIs\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR,
+ const char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+.br
+int \fBsocket_send\fP(int \fIs\fR,const char *\fIbuf\fR,unsigned int \fIlen\fR,
+ const char \fIip\fR[16],uint16 \fIport\fR,uint32 \fIscope_id\fR);
+.SH DESCRIPTION
+.B socket_send4
+sends \fIlen\fR bytes starting at \fIbuf\fR in a UDP
+datagram over the socket \fIs\fR to UDP port \fIport\fR on IPv4 address
+\fIip\fR.
+
+.B socket_send6
+sends \fIlen\fR bytes starting at \fIbuf\fR in a UDP datagram
+over the socket \fIs\fR to UDP port \fIport\fR on IPv6 address \fIip\fR and perhaps
+using \fIscope_id\fR as outging interface.
+
+For link-local IPv6 (LLU) addresses \fIscope_id\fR specifies the outgoing
+interface index.
+.I socket_id
+can be queried for the given name of the interface (e.g. "eth0") by means of
+.BR socket_getifidx .
+\fIscope_id\fR should normally be set to 0 except for link local IPv6 addresses
+
+.B socket_send
+sends \fIlen\fR bytes starting at \fIbuf\fR in a UDP datagram
+over the socket \fIs\fR to UDP port \fIport\fR on IP address \fIip\fR and perhaps
+using \fIscope_id\fR as outging interface.
+
+You can call
+.B socket_send*
+without calling
+.BR socket_bind* .
+This has the effect as first calling
+.B socket_bind4
+with IP address 0.0.0.0 and port 0
+or
+.B socket_bind6
+with IP address :: and port 0.
+.SH RETURN VALUE
+.B socket_send*
+returns
+.I 0
+if the datagram was sent successfully. If not,
+it returns
+.I -1
+and sets
+.I errno
+appropriately.
+.SH EXAMPLE
+ #include <socket_if.h>
+
+ int \fIs\fR;
+ char \fIip\fR[4];
+ uint16 \fIp\fR;
+
+ s = socket_udp();
+ socket_bind(s,ip,p);
+ socket_send(s,"hello, world",12,ip,p,0);
+.SH "SEE ALSO"
+socket_if(3),
+socket_info(3),
+socket_bind(3),
+socket_connect(3),
+socket_recv(3),
+socket_setup(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_setup.3 b/man/socket_setup.3
new file mode 100644
index 0000000..639b28b
--- /dev/null
+++ b/man/socket_setup.3
@@ -0,0 +1,105 @@
+.TH qlibs: socket_setup 3
+.SH NAME
+socket_setup \- listen to or accept socket for incoming TCP connections
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_listen\fP(int \fIs\fR,int \fIn\fR);
+
+int \fBsocket_accept\fP(int \fIs\fR,char \fIip\fR[16],
+ uint16 *\fIport\fR,uint32 *\fIscope_id\fR);
+
+int \fBsocket_ipoptionskill\fR(int \fIs\fR);
+
+int \fBsocket_ip6anycast(\fR(int \fIs\fR);
+
+int \fBsocket_dualstack\fR(int \fIs\fR);
+
+int \fBsocket_nodualstack\fR(int \fIs\fR);
+.SH DESCRIPTION
+.B socket_listen
+prepares TCP socket \fIs\fR to accept TCP connections.
+It allows a backlog of approximately \fIn\fR TCP SYNs.
+(On systems supporting SYN cookies, the backlog is irrelevant.)
+
+.B socket_accept
+accepts the connection. It creates a new socket
+for the connection and returns a file descriptor pointing to the new
+socket; you can use the read and write system calls to transmit data
+through that file descriptor.
+Further, it provides information about client's
+\fIip\fR address and TCP \fIport\fR number
+perhaps together with local receiving interface \fIscope_id\fR.
+
+.B socket_ipoptionskill
+is used to disable previously defined options in IPv4 or IPv6 packets
+like Source Routing prior of using this socket for data exchange.
+.B socket_ipoptionskill
+uses the
+.BR setsockopt .
+
+.B socket_ip6anycast
+enables unspecified reversed anycasting on the listening socket
+.IR s
+with IPv6 address
+.IR :: .
+Upon receiving IPv6 packets, the socket records the
+incoming IPv6 address and the receiving \fIscope_id\fR
+in order provide additional routing information.
+
+.B socket_dualstack
+and
+.B socket_nodualstack
+can be used to force or forbid dual-stack behavior
+setting the
+.B setsockopt
+variable
+.I IPV6_V6ONLY
+appropriately. In the last case, a potential servers
+needs two instances to accept incoming IPv6 and IPv6 packets.
+.SH "RETURN CODES"
+Normally
+.BR socket_listen ,
+.B socket_accept
+and
+.B socket_ipotionskill
+as well as
+.B socket_dualstack
+and
+.B socket_nodualstack
+return
+.I 0
+and if anything goes wrong it returns
+.IR -1 ,
+setting
+.I errno
+appropriately.
+.SH EXAMPLE
+ #include <socket_if.h>
+
+ int \fIs\fR, \fIt\fR;
+ int \fIr\fR;
+ char \fIip\fR[16];
+ uint16 \fIp\fR;
+
+ if ((s = socket_tcp()) == -1)
+ err_tmp("",111,"unable to create TCP socket: ");
+ r = socket_ipoptionskill(s);
+ if (socket_bind_reuse(s,(char *)V6localnet,8002,0) == -1)
+ err_tmp("",111,"unable to bind: ");
+ if (socket_listen(s,1) == -1)
+ err_tmp("",111,"unable to listen: ");
+
+ t = socket_tcp();
+ socket_bind(t,ip,p,0);
+ socket_listen(s,16);
+ socket_accept(t,ip,&p,&scope_id);
+.SH "SEE ALSO"
+socket_if(3),
+socket_bind(3),
+socket_connect(3),
+socket_info(3),
+socket_recv(3),
+socket_send(3),
+socket_tcp(3),
+socket_udp(3)
diff --git a/man/socket_tcp.3 b/man/socket_tcp.3
new file mode 100644
index 0000000..3616ed7
--- /dev/null
+++ b/man/socket_tcp.3
@@ -0,0 +1,58 @@
+.TH qlibs: socket_tcp 3
+.SH NAME
+socket_tcp \- setting up TCP sockets
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_tcp4\fP();
+.br
+int \fBsocket_tcp6\fP();
+.br
+int \fBsocket_tcp\fP();
+.SH DESCRIPTION
+.B socket_tcp4
+creates a non-blocking TCP/IPv4 stream socket and
+providing a file descriptor pointing to that socket.
+
+.B socket_tcp6
+creates a non-blocking TCP/IPv6 stream socket and
+providing a file descriptor pointing to that socket.
+
+.B socket_tcp
+creates a non-blocking IPv6 TCP/IP socket calling
+.B socket_tcp6
+unless it can't bind to IPv6 and now facilitating
+.BR socket_tcp4 .
+.SH "REMOTE CODES"
+All these routines return
+.IR 0
+except in case of failures, returning
+.I -1
+and setting
+.I errno
+appropriately, without allocating any resources.
+.SH EXAMPLE
+ #include <socket_if.h>
+
+ int \fIt\fR;
+ char \fIlocalip\fR[16];
+ char \fIremoteip\fR[16];
+ uint16 \fIp\fR;
+
+ if (ip6_isv4mapped(remoteip)) {
+ t = socket_tcp4();
+ socket_bind4(t,localip + 12,0);
+ } else {
+ t = socket_tcp6();
+ socket_bind6(t,localip,0,0);
+ }
+ socket_connect(s,remoteip,p,0);
+.SH "SEE ALSO"
+socket_if(3),
+socket_bind(3),
+socket_connect(3),
+socket_info(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_udp(3)
diff --git a/man/socket_udp.3 b/man/socket_udp.3
new file mode 100644
index 0000000..eff0290
--- /dev/null
+++ b/man/socket_udp.3
@@ -0,0 +1,58 @@
+.TH qlibs: socket_udp 3
+.SH NAME
+socket_udp \- setting up UDP datagram sockets
+.SH SYNTAX
+.B #include \(dqsocket_if.h\(dq
+
+int \fBsocket_udp4\fP();
+.br
+int \fBsocket_udp6\fP();
+.br
+int \fBsocket_udp\fP();
+.SH DESCRIPTION
+.B socket_udp4
+creates a non-blocking UDP/IPv4 datagram socket and
+providing a file descriptor pointing to that socket.
+
+.B socket_udp6
+creates a non-blocking UDP/IPv6 datagram socket and
+providing a file descriptor pointing to that socket.
+
+.B socket_udp
+creates a non-blocking IPv6 UDP socket calling
+.B socket_udp6
+unless it can't bind to IPv6 and now facilitating
+.BR socket_tcp4 .
+
+.SH "REMOTE CODES"
+All these routines return
+.IR 0
+except in case of failures, returning
+.I -1
+and setting
+.I errno
+appropriately, without allocating any resources.
+.SH EXAMPLE
+ #include <socket_if.h>
+ int \fIu\fR;
+ char \fIlocalip\fR[16];
+ char \fIremoteip\fR[16];
+ uint16 \fIp\fR; // port
+
+ if (ip6_isv4mapped(remoteip)) {
+ u = socket_udp4();
+ socket_bind4(u,localip + 12,p);
+ } else
+ u = socket_udp6();
+ socket_bind6(u,localip,p,0);
+ }
+ socket_connect(u,remoteip,p,0);
+.SH "SEE ALSO"
+socket_if(3),
+socket_bind(3),
+socket_connect(3),
+socket_info(3),
+socket_recv(3),
+socket_send(3),
+socket_setup(3),
+socket_tcp(3)
diff --git a/man/str.3 b/man/str.3
new file mode 100644
index 0000000..c8643ed
--- /dev/null
+++ b/man/str.3
@@ -0,0 +1,61 @@
+.TH qlibs: str 3
+.SH NAME
+str \- string evaluation and comparision (for allocated strings)
+.SH SYNTAX
+.B #include \(dqstr.h\(dq
+
+unsigned int \fBstr_copy\fR(char *\fIdst\fR, const char *\fIsrc\fR);
+.br
+unsigned int \fBstr_copyb\fR(char *\fIdst\fR, const char *\fIsrc\fR, unsigned int \fIlen\fR);
+.br
+unsigned int \fBstr_chr\fR(const char *\fIs\fR, int \fIc\fR);
+.br
+unsigned int \fBstr_rchr\fR(const char *\fIs\fR, int \fIc\fR);
+.br
+unsigned int \fBstr_diff\fR(const char *\fIs\fR, const char *\fIt\fR);
+.br
+unsigned int \fBstr_diffn\fR(const char *\fIs\fR, const char *\fIt\fR, unsigned int \fIlen\fR);
+.br
+unsigned int \fBstr_equal\fR(const char *\fIs\fR, const char *\fIt\fR);
+.br
+unsigned int \fBstr_len\fP(const char *\fIs\fR);
+.br
+unsigned int \fBstr_starts\fP(const char *\fIdst\fR, const char *\fIsrc\fR);
+.br
+char *\fBstr_append\fP(char *\fIdst\fR, const char *\fIs\fR);
+.SH DESCRIPTION
+\fBstr_copy\fR copies \fIsrc\fR into \fIdst\fR up to the first occurance of \\0 while including it.
+It returns the number of bytes written.
+If \fIdst\fR is smaller than \fIsrc\fR, \fBstr_copy\fR fills up \fIdst\fR
+to its allocated size and returns the number of bytes it would have be written.
+\fBstr_copyb\fR copies \fIlen\fR bytes from \fIsrc\fR into \fIdst\fR.
+
+\fBstr_chr\fR and \fBstr_rchr\fR searches for a single character in a string
+(from left-to-right or from right-to-left) and returns the position of
+the \fIfirst\fR occurrance of \fIc\fR or the length \fIlen\fR of \fIs\fR.
+
+\fBstr_len\fR determines the length of a string. It returns the position
+of the first occurance of \\0 in \fIs\fR.
+
+\fBstr_diff\fR, \fBstr_diffn\fR, and \fBstr_equal\fR compare two strings.
+\fBstr_diff\fR and \fBstr_diffn\fR returns negative, zero or positive, depending
+whether the string \fIs\fR[0], \fIs\fR[1], ..., \fIs\fR[n]=='\\0' is
+ASCII lexicographically smaller than, equal to, or greater than the string
+\fIt\fR[0], \fIt\fR[1], ..., \fIt\fR[m-1]=='\\0'. If the strings are different,
+both functions do not read bytes past the first difference.
+\fBstr_diffn\fR considers the strings equal if the first \fIn\fR characters match.
+
+\fBstr_equal\fR returns 1, if \fIs\fR and \fIt\fR match up to and including the
+first occurance of \\0 or returns 0 otherwise. It is the opposite of \fBstr_diff\fR.
+
+\fBstr_start\fR compares the two strings from the begining.
+It returns 1 if \fIt\fR is a prefix of \fIs\fR or 0 otherwise.
+
+\fB*str_append\fR appends a single byte \fIs\fR to \fIout\fR given \fIout\fR
+is allocated with enough space.
+.SH "NOTE"
+For the \fBstr_copy*\fR and \fB*str_append\fP commands \fIdst\fR
+has to have a preallocated space.
+Otherwise the result may be unexpected.
+.SH "SEE ALSO"
+byte(3), stralloc(3)
diff --git a/man/stralloc.3 b/man/stralloc.3
new file mode 100644
index 0000000..55da25d
--- /dev/null
+++ b/man/stralloc.3
@@ -0,0 +1,160 @@
+.TH qlibs stralloc 3
+.SH NAME
+stralloc \- dynamically allocated strings
+.SH SYNTAX
+.B #include \(dqstralloc.h\(dq
+
+int \fBstralloc_ready\fP(&\fIsa\fR,\fIlen\fR);
+.br
+int \fBstralloc_readyplus\fP(&\fIsa\fR,\fIlen\fR);
+
+int \fBstralloc_copy\fP(&\fIsa\fR,&\fIsa2\fR);
+.br
+int \fBstralloc_copys\fP(&\fIsa\fR,\fIbuf\fR);
+.br
+int \fBstralloc_copyb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR);
+
+int \fBstralloc_cat\fP(&\fIsa\fR,&\fIsa2\fR);
+.br
+int \fBstralloc_cats\fP(&\fIsa\fR,\fIbuf\fR);
+.br
+int \fBstralloc_catb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR);
+
+int \fBstralloc_append\fP(&\fIsa\fR,\fIbuf\fR);
+.br
+int \fBstralloc_0\fP(&\fIsa\fR);
+
+int \fBstralloc_starts\fP(&\fIsa\fR,\fIbuf\fR);
+
+stralloc \fIsa\fR = {0};
+.br
+stralloc \fIsa2\fR = {0};
+.br
+unsigned int \fIlen\fR;
+.br
+char *\fIbuf\fR;
+.SH DESCRIPTION
+A
+.B stralloc
+variable holds a string in dynamically allocated space.
+String length is limited only by memory.
+String contents are unrestricted.
+
+The
+.B stralloc
+structure has three components:
+.I sa\fB.s
+is a pointer to the string, or 0 if it is not allocated;
+.I sa\fB.len
+is the number of bytes in the string, if it is allocated;
+.I sa\fB.a
+is the number of bytes allocated for the string, if it is allocated.
+A
+.B stralloc
+variable should be initialized to {0},
+meaning unallocated.
+
+.B stralloc_ready
+makes sure that
+.I sa
+has enough space allocated for
+.I len
+characters.
+It allocates extra space if necessary.
+
+.B stralloc_readyplus
+makes sure that
+.I sa
+has enough space allocated for
+.I len
+characters more than its current length.
+If
+.I sa
+is unallocated,
+.B stralloc_readyplus
+is the same as
+.BR stralloc_ready .
+
+.B stralloc_copy
+copies
+.I sa2
+to
+.IR sa ,
+allocating space if necessary.
+Here
+.I sa2
+is an allocated
+.B stralloc
+variable.
+
+.B stralloc_copys
+copies a 0-terminated string,
+.IR buf ,
+to
+.IR sa ,
+without the 0.
+
+.B stralloc_copyb
+copies
+.I len
+characters from
+.I buf
+to
+.IR sa .
+
+.B stralloc_cat
+appends
+.I sa2
+to
+.IR sa ,
+allocating space if necessary.
+If
+.I sa
+is unallocated,
+.B stralloc_cat
+is the same as
+.BR stralloc_copy .
+
+.B stralloc_cats
+and
+.B stralloc_catb
+are analogous to
+.B stralloc_copys
+and
+.BR stralloc_copyb .
+
+.B stralloc_append
+adds a single character,
+.IR *buf ,
+to
+.IR sa ,
+allocating space if necessary.
+
+.B stralloc_0
+adds a single 0 character
+to
+.IR sa .
+
+.B stralloc_starts
+returns 1 if the 0-terminated string
+.IR buf ,
+without the 0,
+is a prefix of
+.IR sa .
+.SH "ERROR HANDLING"
+If a
+.B stralloc
+routine runs out of memory,
+it leaves
+.I sa
+alone and returns 0,
+setting
+.B errno
+appropriately.
+On success it returns 1;
+this guarantees that
+.I sa
+is allocated.
+.SH "SEE ALSO"
+alloc(3),
+error(3)
diff --git a/man/taia.3 b/man/taia.3
new file mode 100644
index 0000000..0aeb4e0
--- /dev/null
+++ b/man/taia.3
@@ -0,0 +1,91 @@
+.TH taia 3
+.SH NAME
+taia \- Temps Atomique International (Attosecond) time routines
+.SH SYNTAX
+.B #include \(dqtaia.h\(dq
+
+extern int \fBtaia_add\fP(struct taia *\fIt\fR,const struct taia *\fIa\fR,const struct taia *\fIb\fR);
+.br
+extern int \fBtaia_addsec\fP(struct taia *\fIt\fR,const struct taia *\fIs\fR,int \fIsecs\fR);
+.br
+extern int \fBtaia_approx\fP(const struct taia *\fIt\fR);
+.br
+int \fBtaia_frac\fP(const struct taia *\fIt\fR);
+.br
+extern int \fBtaia_less\fP(const struct tai *\fIa\fR,const struct tai *\fIb\fR);
+.br
+extern int \fBtaia_now\fP(struct taia *\fIt\fR);
+.br
+extern int \fBtaia_pack\fP(char *buf,const struct taia *\fIt\fR);
+.br
+extern int \fBtaia_sub\fP(struct taia *\fIt\fR,const struct taia *\fIa\fR,const struct taia *\fIb\fR);
+.br
+extern int \fBtaia_tai\fP(const struct taia *\fIt\fR,struct tai *\fIsec\fR);
+.br
+extern int \fBtaia_uint\fP(struct taia *\fIt\fR,unsigned int \fIsecs\fR);
+.br
+extern int \fBtaia_unpack\fP(const char *buf,struct taia *\fIt\fR);
+.SH DESCRIPTION
+.B taia_add
+adds \fIa\fR to \fIb\fR and writes the result to \fIt\fR.
+The inputs and output may overlap.
+
+.B taia_addsec
+adds \fIsecs\fR seconds to \fIs\fR and writes the result to \fIt\fR.
+The inputs and output may overlap.
+
+.B taia_approx
+returns a double-precision approximation of \fIt\fR.
+The result of
+.B taia_approx
+is always nonnegative.
+
+.B taia_frac
+returns a double-precision approximation to the fraction part
+of \fIt\fR. The result of
+.B taia_frac
+is always nonnegative.
+
+.B taia_less
+returns 1 if \fIa\fR is less than \fIb\fR, 0 otherwise.
+
+.B taia_now
+puts the current time into \fIt\fR. More precisely:
+.B tai_now
+puts into \fIt\fR its best guess as to the TAI64NA label
+for the 1-attosecond interval that contains the current time.
+
+This implementation of taia_now assumes that the
+.I time_t
+returned from the time function represents the number of TAI seconds since 1970-01-01
+00:00:10 TAI. This matches the convention used by the Olson tz library
+in ``right'' mode.
+
+Beware that many clocks are not set accurately, and even the best
+scientific clocks are nowhere near 1-attosecond accuracy; however, an
+inaccurate clock may still produce reasonably accurate time differences.
+
+.B taia_pack
+converts a TAI64NA label from internal format in \fIt\fR to external
+TAI64NA format in \fIbuf\fR.
+
+.B taia_sub
+subtracts \fIb\fR from \fIa\fR and writes the result to \fIt\fR.
+The inputs and output may overlap.
+
+.B taia_tai
+places into \fIsec\fR the integer part of \fIt\fR. If \fIt\fR
+contains a TAI64NA label then \fIsec\fR will contain the corresponding
+TAI64 label.
+
+.B taia_uint
+converts \fIsecs\fR into a struct taia (setting the fractional part to zero).
+
+.B taia_unpack
+converts a TAI64NA label from external TAI64NA format in
+\fIbuf\fR to internal format in \fIt\fR.
+.SH "SEE ALSO"
+time(1),
+utime(3),
+ctime(3),
+locale(1)
diff --git a/man/timeout.3 b/man/timeout.3
new file mode 100644
index 0000000..6113f27
--- /dev/null
+++ b/man/timeout.3
@@ -0,0 +1,36 @@
+.TH qlibs: timeout 3
+.SH NAME
+timeout \- reading from and writing to a file descriptor
+.SH SYNTAX
+.B #include \(dqtimeout.h\(dq
+
+int \fBtimeoutread\fP(int \fIt\fR,int \fIfd\fR,char *\fIbuf\fR,int \fIlen\fR);
+.br
+int \fBtimeoutwrite\fP(int,int,char *,int);
+.SH DESCRIPTION
+.B timeoutread
+reads from file descriptor
+.I fd
+.I len
+bytes into
+.I buf
+returning
+.I 0
+on success and
+.I -1
+in case a timeout has occured.
+.B timeoutwrite
+writes to file descriptor
+.I fd
+.I len
+bytes from
+.I buf
+returning
+.I 0
+on success and
+.I -1
+in case a timeout has occured.
+.SH "SEE ALSO"
+wait(3),
+timeoutconn(3)
+taia(3).
diff --git a/man/timeoutconn.3 b/man/timeoutconn.3
new file mode 100644
index 0000000..dad9e95
--- /dev/null
+++ b/man/timeoutconn.3
@@ -0,0 +1,52 @@
+.TH qlibs: timeoutconn 3
+.SH NAME
+timeoutconn \- set up an outoing stream socket for IPv4/IPv6
+.SH SYNTAX
+.B #include \(dqtimeoutconn.h\(dq
+
+int \fBtimeoutconn4\fP(int \fIs\fR,char \fIip[4]\fR,uint16 \fIp\fR,unsigned int \fIt\fR);
+.br
+int \fBtimeoutconn6\fP(int \fIs\fR,char \fIip[16]\fR,uint16 \fIp\fR,unsigned int \fIt\fR,uint32 \fInetif\fR);
+.br
+int \fBtimeoutconn\fP(int \fIs\fR,char \fIip[16]\fR,uint16 \fIp\fR,unsigned int \fIt\fR,uint32 \fInetif\fR);
+.SH DESCRITPION
+.B timeoutconn
+tries to establish a TCP stream socket to address
+.I ip
+on remoteport
+.I p
+and waiting for
+.I t
+seconds and on success returns the
+.I s
+socket identifier.
+
+In case
+.I addresss
+is an IPv6 LLU address, one needs to define the
+.I netif
+interface index, otherwise
+.I 0
+is the default.
+.SH INTERNALS
+.B timeoutconn
+depends on
+.B taia
+and
+.B iopuase
+to determine the timespan and perhaps
+.B ndelay
+to succeed.
+.SH RETURN CODES
+.B timeoutconn
+returns
+.I 0
+if the connection is established
+and
+.I -1
+if an error has occured.
+.SH SEE ALSO
+socket_if(3),
+timeout(3)
+taia(3),
+wait(3)
diff --git a/man/wait.3 b/man/wait.3
new file mode 100644
index 0000000..c3b6c63
--- /dev/null
+++ b/man/wait.3
@@ -0,0 +1,96 @@
+.TH qlibs: wait 3
+.SH NAME
+wait \- check child process status
+.SH SYNTAX
+.B #include \(dqwait.h\(dq
+
+int \fBwait_nohang\fP(&\fIwstat\fR);
+.br
+int \fBwait_stop\fP(&\fIwstat\fR);
+.br
+int \fBwait_stopnohang\fP(&\fIwstat\fR);
+.br
+int \fBwait_pid\fP(&\fIwstat\fR,\fIpid\fR);
+
+int \fBwait_exitcode\fP(\fIwstat\fR);
+.br
+int \fBwait_crashed\fP(\fIwstat\fR);
+.br
+int \fBwait_stopped\fP(\fIwstat\fR);
+.br
+int \fBwait_stopsig\fP(\fIwstat\fR);
+
+int \fIpid\fR;
+.br
+int \fIwstat\fR;
+.SH DESCRIPTION
+.B wait_nohang
+looks for zombies (child processes that have exited).
+If it sees a zombie,
+it eliminates the zombie,
+puts the zombie's exit status into
+.IR wstat ,
+and returns the zombie's process ID.
+If there are several zombies,
+.B wait_nohang
+picks one.
+If there are children but no zombies,
+.B wait_nohang
+returns
+.IR 0 .
+If there are no children,
+.B wait_nohang
+returns
+.IR -1 ,
+setting
+.B errno
+appropriately.
+
+.B wait_stopnohang
+is similar to
+.BR wait_nohang ,
+but it also looks for children that have stopped.
+
+.B wait_stop
+is similar to
+.BR wait_stopnohang ,
+but if there are children it will pause waiting for one of them
+to stop or exit.
+
+.B wait_pid
+waits for child process
+.I pid
+to exit.
+It eliminates any zombie that shows up in the meantime,
+discarding the exit status.
+
+.B wait_stop
+and
+.B wait_pid
+retry upon
+.BR error_intr .
+.SH "STATUS PARSING"
+If the child stopped,
+.B wait_stopped
+is nonzero;
+.B wait_stopsig
+is the signal that caused the child to stop.
+
+If the child exited by crashing,
+.B wait_stopped
+is zero;
+.B wait_crashed
+is nonzero.
+
+If the child exited normally,
+.B wait_stopped
+is zero;
+.B wait_crashed
+is zero;
+and
+.B wait_exitcode
+is the child's exit code.
+.SH "SEE ALSO"
+pathexec(3),
+wait(2),
+error(3)
diff --git a/man/x.html b/man/x.html
new file mode 100644
index 0000000..224edc1
--- /dev/null
+++ b/man/x.html
@@ -0,0 +1,99 @@
+<HTML>
+<BODY>
+<PRE>
+<!-- Manpage converted by man2html 3.0.1 -->
+SYNTAX
+ #include "logmsg.h"
+
+ int logmsg(const char *who, int ecode, unsigned int classs, char *msg)
+
+ err_sys(w,e) logmsg(w,e,FATAL,"")
+ err_sys_plus(w,e,m) logmsg(w,e,FATAL,m)
+ err_tmp(w,e) logmsg(w,e,WARN,"")
+ err_tmp_plus(w,e,m) logmsg(w,e,WARN,m)
+ err_int(w,e,c) logmsg(w,e,c,"")
+ err_int_plus(w,e,c,m) logmsg(w,e,c,m)
+ log_who(w,m) logmsg(w,0,LOG,m)
+ log_anon(m) logmsg("",0,LOG,m)
+
+DESCRIPTION
+ logmsg prints error, warning, or info/logging messages to stderr and
+ potentially terminates the calling program, depending on the class
+ given. who is the name of the program, ecode is an error code, class
+ determines the behavior upon call and msg is the logging message. Read
+ "error.h" to learn more about related constants.
+
+ECODE
+ ecode is the error code and subject to be displayed in the log file and
+ potentially used upon exit if the class equals ERROR, FATAL, or DROP.
+
+ To avoid conflicts with syscall error codes, appplication defined error
+ codes should be negative. The values -15, -100 and -111 are reserved
+ for backward compatibility.
+
+CLASS
+ The class parameter indicates how the application handles exceptions
+ and displays the log message.
+
+ o LOG, INFO, ALERT, WARN - display message and continue operation
+
+ o DROP - display warning message and continue while returning to the
+ calling program
+
+ o USAGE, SYNTAX, FATAL, ERROR - display error message and exit appli‐
+ cation with error code
+
+ INFO, ALERT, WARN, DROP, USAGE, and FATAL as well as ERROR display the
+ respective class string like warning: in the log message, while LOG
+ shows the log message only.
+
+ The class FATAL should be used for system error codes only, rather ER‐
+ ROR and WARN shall be set in conjunction with an application er‐
+ ror/warning.
+
+MESSAGE
+ If the custom message msg is given, it will be printed additionally.
+
+ Dan Bernstein used sets of strerr_dieY*() and strerr_warnY() messages
+ which explicitely determine the message and behavior class. Other
+ classes were occasionally defined on demand, such als usage().
+
+ Kai Peter introduced the errmsg facility in his qlibs including a sys‐
+ log compliant severity as second parameter.
+
+EXAMPLES
+ The macro definitions uses w for the calling program, e for error
+ code, c for class, and m for message.
+
+ #include "logmsg.h"
+ #define WHO "my_prog"
+
+ err_sys(WHO,errno);
+ err_sys_plus(WHO,-111,"additional message");
+
+ err_tmp("",-100);
+ err_tmp_plus("",errno,"additional message");
+
+ log_who(WHO,"message");
+
+ log_anon() is like log_who() but doesn't print the caller name.
+
+ An user defined message s can be build from multiple arguments by using
+ the B (build) macro:
+
+ err_sys_plus((errno),B("unable to run: ",*argv));
+
+SEE ALSO
+ <B>syslog(3)</B>
+
+
+
+ 3 qlibs:(logmsg)
+</PRE>
+<HR>
+<ADDRESS>
+Man(1) output converted with
+<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a>
+</ADDRESS>
+</BODY>
+</HTML>