Libslack is a library of general utilities designed to make UNIX/C programming a bit easier on the eye. It is a seemingly random collection of modules and functions that I find commonly useful. It was originally implemented as part of the daemon program (although some of the code dates back much further).
It's a small library with lots of functionality, accurately documented and thoroughly tested. Good library naming conventions are not rigorously observed on the principle that common operations should always be easy to write and code should always be easy to read.
Libslack is freely available under the GNU General Public License.
Program Framework
The "framework" parts of libslack are bound to be the most objectionable. Nobody likes frameworks. Don't worry, there isn't much to it. If you don't like it, pretend it's not there.
Libslack provides the ability for programs to identify
themselves, perform command line option processing in a single line of
code and produce "standard" GNU style --help
,
--version
and usage messages. Debug and verbose messaging
is also provided and is enabled by the use of "standard"
--debug
and --verbose
command line options.
Messages (including error, debug and verbose messages) are provided with clean call syntax and flexible semantics. Messages can be directed to log files, file descriptors, syslog or multiplexed to any of the above (and to anywhere else (e.g. dialog boxes) if you implement your own message handlers) without complicating the call syntax.
ISO C imposes extreme restrictions on signal handlers. POSIX imposes less extreme but still annoying restrictions. Libslack contains functions that provide a level of abstraction between the signal handlers that you write and the real (ISO C compliant) signal handlers. This allows you to write unrestricted signal handlers.
Coarse grained persistence of simple configuration information is provided by the use of Java style properties files in "well-known" locations.
Daemon Services
Libslack provides functions that make writing daemons
trivial. It includes functions to become a daemon and to optionally
create a locked pid file to ensure that only a single instance of a
named daemon is ever active at the same time. The daemon function
behaves appropriately if the client process is started by
init(8) or inetd(8). There are also functions to
streamline the parsing of simple configuration files (like those
commonly found in the /etc
directory). There are also
functions that help you write more secure daemons (i.e. revoke
setuid/setgid privileges, prevent core file generation, change user
and group, test the safety of a given file path). There are also
functions to check if a named daemon is running and to stop it.
Network Services
Libslack provides functions to simplify the implementation of network servers and clients (TCP, UDP, unicast and multicast) and the (text or binary) application protocols that they use. Network servers and clients can be setup in a single line of code. There is transparent support for IPv4, IPv6 and UNIX domain socket addresses. There is support for reliability over UDP. Text protocols are implemented by sequences of expect and send functions. Binary protocol packets can be packed and unpacked (using functions similar to pack() and unpack() in Perl but network/storage friendly). There's also a function to send mail.
Agent Oriented Programming
Libslack provides a generic agent oriented programming model in the form of the Agent data type. Like objects, agents can react to external stimuli. Unlike objects, agents can can also take independent actions. This is performed by multiplexing I/O events on arbitrary file descriptors using poll() or select() and also multiplexing timers for scheduling actions. Connecting and disconnecting file descriptors is done in constant time. Scheduling and cancelling actions is done in constant time. Timer maintenance is performed in constant average time. This means that agents are scalable with respect to the number of outstanding timers and can support thousands of scheduled actions. A single agent may be used like a simple event loop, or multiple agents can be connected to each other in arbitrary networks across multiple threads, processes and/or hosts. A single agent isn't scalable with respect to the number of connected file descriptors but multiple agents can be combined to achieve much higher scalability. They're useful for networked applications, distributed systems and simulations.
Data Types
Libslack provides a generic growable pointer array data type called List, a generic growable hash table data type called Map and a decent String data type that comes with heaps of functions (many lifted from Perl). There are also abstract singly and doubly linked list data types with optional, "growable" freelists.
Decoupled Thread Safety
Libslack provides the Locker data type which decouples thread synchronisation strategies from client code. This allows code to be written that delegates the choice of synchronisation strategy to the client. This enables run time selection of locking strategies which means it's even possible to let the end user specify which locking strategy to use. It supports mutual exclusion locks, readers/writer locks and no locking. There are also debug versions that print messages to standard output to help clients locate deadlocks. See https://raf.org/papers/mt-disciplined.html.
Coprocesses and Pseudo Terminals
Libslack provides functions for creating pseudo terminals portably and for creating coprocesses that use either pipes or a pseudo terminal for communication with the client process.
Miscellaneous
Libslack contains convenience/shorthand functions for random things such as reading a line of text with any line ending (UNIX, DOS or Macintosh), fifo and file control, retrieving POSIX.1 limits, parsing syslog facility/priority pairs, dynamic allocation of multi-dimensional arrays, memory pools, secure memory, secure memory pools, There's also a heap sort function. And there are also implementations of GNU getopt_long(), strlcat(), strlcpy(), snprintf(), vsnprintf(), vsscanf(), asprinf() and vasprintf() for systems that don't have them.
Low-Level API
Although there is a lot of functionality in libslack, the
API itself is as low-level as possible. There are no gratuitous data
structures that wrap around perfectly acceptable data structures
that are provided by the system. For instance, the networking
functions do not return some home grown Socket object. They
return file descriptors just like underlying system calls. The
coprocess API is similar in spirit to popen(3) and
pclose(3). The fgetline(3) function interoperates
perfectly with standard I/O. Errors are returned via
errno
just like system calls and some standard library
functions. You may not like errno
if you write threaded
programs but I figured that until errno
goes away, it's
best to accept it and find a way to benefit from it. Unavoidably,
the string module does wrap an object around perfectly good char
pointers but the underlying char pointer is always accessible and
many of the string functions have versions that work on ordinary C
strings.
The purpose of this design is Laziness. It means I don't have to wrap every net related system call or standard string function in an extra function and you don't have to learn a load of new identifiers for functionality that you already know how to access. The same goes for error codes. I don't want to re-invent them and you don't need to re-learn them. It also means that libslack functions can be more easily incorporated into existing programs to enhance their functionality without huge code rewrites and without the need for a steep learning curve.
Accurate Documentation
Every module has a manpage that explains every function in detail. The function signatures in the manual entries are systematically checked against the source code to make sure that they never get out of sync.
There are plenty of examples in the manual entries. Most of them are systematically compiled and executed to make sure that they never get out of sync with the source code.
The actual text of the manual entries can't be systematically checked but it does get proofread regularly. If you find any errors of any kind in the documentation, please let me know.
All of the documentation takes the form of manual entries because they are faster and more accessible than anything else.
Thorough Testing
Libslack is thoroughly tested. This doesn't mean that there are no bugs but it does mean that there is a large list of bugs that it doesn't have. Excluding the snprintf module, there are nearly 2,800 tests. Including the snprintf module, there are nearly 150,000 tests. These tests also serve as extra examples.
For more information read the manual entries in the Documentation section.
Currently, libslack is only known to compile and work on:
It is written in ISO C using POSIX almost exclusively except for some BSD functions that appear on most systems (e.g. sockets). So it shouldn't be difficult to get it working on other (recent) systems that support ISO C, POSIX and XPG4.
There is a README file, libslack overview manpage, a manpage for each module in libslack and a manpage for the libslack-config utility. There is also the paper MT-Disciplined - decoupling thread safety.
README |
- | Description |
INSTALL |
- | Installation, binary packages, requirements, platform notes |
COPYING |
- | Copyright information |
LICENSE |
- | GNU General Public Licence Version 2 |
REFERENCES |
- | References |
CHANGELOG |
- | History |
libslack(3) |
- | an overview of libslack |
libslack-config(1) |
- | administration utility for libslack |
agent(3) |
- | agent oriented programming (header, source) |
coproc(3) |
- | coprocesses using pipes or pseudo terminals (header, source) |
daemon(3) |
- | becoming a daemon (header, source) |
err(3) |
- | message/error/debug/verbosity/alert messaging (header, source) |
fio(3) |
- | fifo and file control and some I/O (header, source) |
getopt(3) |
- | GNU getopt_long() for systems that don't have it (header, source) |
hsort(3) |
- | heap sort (by Stephen Russell) (header, source) |
lim(3) |
- | POSIX.1 limits convenience functions (header, source) |
link(3) |
- | abstract linked lists with optional growable free lists (header, source) |
list(3) |
- | list (growable pointer array) data type (header, source) |
locker(3) |
- | abstract locking and reader/writer lock implementation (header, source) |
map(3) |
- | map (hash table) data type (header, source) |
mem(3) |
- | memory helper functions, secure memory, memory pools (header, source) |
msg(3) |
- | message handling and syslog helper functions (header, source) |
net(3) |
- | network functions (clients/servers, expect/send, pack/unpack, mail) (header, source) |
prog(3) |
- | program framework and flexible command line option handling (header, source) |
prop(3) |
- | program properties files (header, source) |
pseudo(3) |
- | pseudo terminals (by Tatu Ylonen) (header, source) |
sig(3) |
- | ISO C compliant signal handling (header, source) |
snprintf(3) |
- | safe sprintf() for systems that don't have it (header, source) |
str(3) |
- | string data type (tr, regex, regsub, fmt, trim, lc, uc, ...) (header, source) |
vsscanf(3) |
- | sscanf() with va_list argument for systems that don't have it (header, source) |
Latest: |
libslack-0.7.5.tar.gz
|
(SHA256 10561805042cf6c28476af110b886c4b695b4f38a119390acbb63996170b1cac )
|
libslack-0.7.5-html.tar.gz
|
(SHA256 ef5ee2ff8a37586bdde5cadf4698d167576a026d9c0321f969322ebf8d4bb65d )
|
|
Previous: |
libslack-0.7.4.tar.gz
|
(SHA256 094f2ae8d45cbcd678bfba60e47fabceed27fb00dc77c25a63235de9cafc0da6 )
|
libslack-0.7.4-html.tar.gz
|
(SHA256 567aa0325d9669178f0aedfe4b2e4487d72d752ccbd231c76a99c1d1ca65a6b4 )
|
|
libslack-0.7.3.tar.gz
|
(SHA256 b61ece8b36b902a9a8a9b94dd5e64dffafc49de3d1851ea3c0194b579bedd77f )
|
|
libslack-0.7.3-html.tar.gz
|
(SHA256 33b679f5873310964194987972141fc3eab66f615880666516d79b5a4f565177 )
|
|
libslack-0.7.2.tar.gz
|
(SHA256 68d098137eeb5dc3adb01020663e8f38c8e52e1d16bfd7033ec6f5e43ebded2b )
|
|
libslack-0.7.2-html.tar.gz
|
(SHA256 a64849763af6cca8b659c797b5696b6566075947c511391afb773adb4e24e54c )
|
|
libslack-0.7.1.tar.gz
|
(SHA256 d776c8ef8ed98952c7621d83072f912e5735ea593c00acab79020853a79efc81 )
|
|
libslack-0.7.1-html.tar.gz
|
(SHA256 3a03a8637b99b061d5e40b98476fced02bb5e7416505786c27fa71a6187cf4c9 )
|
|
libslack-0.7.tar.gz
|
(SHA256 8af7b78d0d28f92816b68a6525d48652198467f1644321ac9e5cf706dc0c6d80 )
|
|
libslack-0.7-html.tar.gz
|
(SHA256 0c9ba9bd2067673b8f7b76ae4bb795530db01a0cad28f08e1479e20f03d6c0ab )
|
|
libslack-0.6.tar.gz
|
(SHA256 23c373d360bbe6d0b99ed8f801a20ad7c7444f749b81e9670a59f73c8fbec304 )
|
|
libslack-0.6.html.tar.gz
|
(SHA256 1fc08579d86fe22d4514b875e1c47bd120dbd8f67f257ea7fb16eceda1cd32ef )
|
|
libslack-0.6-1.src.rpm
|
(SHA256 9e45eef69228594fd328336749051a354622105911636cd310ddb21d132e3fe2 )
|
|
libslack-0.6-1.x86_64.rpm
|
(SHA256 27cb7135369aea17538a0b6ab4a5977bd0ca3d51f4c5f5df337f13d7de464eee )
|
|
libslack-0.6-1.i686.rpm
|
(SHA256 2e1ff7bdd0fb09644ad17be4a72d17f47158b7391f2a4266d0fc328e2b9cf7d5 )
|
|
libslack-0.6-openbsd-amd64.tgz
|
(SHA256 cb92645845762c1ac7c9b99e75bcdaa3232c4a7bd82369a3f3d94aa290261bc5 )
|
|
libslack-0.6-openbsd-i386.tgz
|
(SHA256 f93ab0f2f96eb4aebae184526c9ea6fc4b70fb7da21a071628a4ee3157b7546a )
|
|
libslack-0.6-freebsd-amd64.tbz
|
(SHA256 5b72bde11d3d5b87f9f0c68811d64a1040010ba9affa79a90ff901f6807c4651 )
|
|
libslack-0.6-freebsd-i386.tbz
|
(SHA256 fa1b7120ad33a02bfa2a1c225fc31e9b3359dfcd0747d0f0c546ce939d13410c )
|
|
libslack-0.6-netbsd-amd64.tgz
|
(SHA256 cf6888448ecac4585b6b552a04b7ca1dbc368ee22f22e3ffc75caf6813c069b3 )
|
|
libslack-0.6-netbsd-i386.tgz
|
(SHA256 9f966388b69c71dba1f06c37ae58ea7bf8c6f23db44b4756826705ffafd92a6b )
|
|
libslack-0.6-macosx-universal.tar.gz
|
(SHA256 6317b244d1847a970b52988e9d19941596304a859855eff53877559af6c8adf8 )
|
|
libslack-0.6-macosx-x86_64.tar.gz
|
(SHA256 82c20f44337265b1a261e93aa23f21dbb65750a58fa39a6f1395f8b6ca6e6594 )
|
|
libslack-0.6-macosx-i386.tar.gz
|
(SHA256 15a122341e9096791eee779bdf67daff48a67295f240daddd578c991447e51da )
|
|
libslack-0.6-macosx-powerpc.tar.gz
|
(SHA256 986065da4bb549032009440faf5f5cd7c0ef833efd5444a539c61e2fd94a0150 )
|
|
libslack-0.6-macosx-10.4-powerpc.tar.gz
|
(SHA256 a2be5611e7a5b2619b2f01fb0d5038543bcf9c55feb113f23cd3c3559dec5f36 )
|
|
libslack-0.6-solaris-amd64.pkg.gz
|
(SHA256 7d52468160ee9e45a115b04d8de4da46cf1a6e8b2425e242c4730a7fc3c1a859 )
|
|
libslack-0.6-solaris-i386.pkg.gz
|
(SHA256 afb459b15c365112efae35517d81be6e9c93d7d5814de6d3baeecc83bb03f061 )
|
|
libslack-0.5.2.tar.gz
|
(SHA256 4b7795bf2522ffeb854ce7564a4faa3c02920de7cb281a7d119b2d04bceffe59 )
|
|
libslack-0.5.2.html.tar.gz
|
(SHA256 ffcd8feda9d5a455a435b8c033e2be75a7cae141ad8a0bd93ee72ee216ba120d )
|
|
libslack-0.5.2-1.src.rpm
|
(SHA256 7f850be0a4a2e77a986cb96ac180c2b7891044931f7cb7d1023e798817a65158 )
|
|
libslack-0.5.2-1.i386.rpm
|
(SHA256 f5ffba307804cdba118c596e6c6fb654a6806f2f287edbfe56a3802573c5860b )
|
|
libslack-0.5.2-obsd-i386.tar.gz
|
(SHA256 d082a19c2c563ecd1c53770441c1fcd7bcc983bb0e8f89343eb480eaf1f96705 )
|
|
libslack-0.5.2-fbsd-i386.tar.gz
|
(SHA256 9db81afd3ed9088d6a60ce5da7661815be6c9921748ce006ec418df72034ca3b )
|
|
libslack-0.5.2-macosx-powerpc.tar.gz
|
(SHA256 532cc21f7780cd5ba2dce649f2cbd61e2466eaa0efb6480bd3ad8f701d8f6de8 )
|
|
libslack-0.5.2.sun4u.pkg.gz
|
(SHA256 db35e0040ccf232b47dc47a91ee45f232514d6cd5c9153e108d6fa93b0bb1454 )
|
|
libslack-0.5.2.i86pc.pkg.gz
|
(SHA256 f9454cac533e4f29c7d744bf2774a3e21ac40973ae35aebfd488c7f8d4e1f5ee )
|
|
libslack-0.5.1.tar.gz
|
(SHA256 0f87152735a020279134ac552753bbaec1111e71cbad1b635f348fa01794c0b7 )
|
|
libslack-0.5.1.html.tar.gz
|
(SHA256 acdebf53074e5fc4562fead74247e252b9675f63d48cfabe1a0b4c0b901a3439 )
|
|
libslack-0.5.1-1.src.rpm
|
(SHA256 14ab525d0f24bc784de5cdee93c8ea9805a23acce1b554136e1d0f2d2e499cf8 )
|
|
libslack-0.5.1-1.i386.rpm
|
(SHA256 c467bef577167cd1949d41e395b79c5afc618b346569326d823d75deacfdb738 )
|
|
libslack-0.5.1-obsd-i386.tar.gz
|
(SHA256 47d74448ebc33f49d414228ce84e8014963331aa66139c1a9222b1f9499802ff )
|
|
libslack-0.5.1-fbsd-i386.tar.gz
|
(SHA256 f2f2477a14151cb0b71a8bc1c0f49ec112e26e62be4d2d54d0b92916b16e2d25 )
|
|
libslack-0.5.1.sun4u.pkg.gz
|
(SHA256 af983596b93289e08c8c5da4bd7a4f38ed7c0c574ddbf6a5c90d827483fbcc89 )
|
|
libslack-0.5.tar.gz
|
(SHA256 19b7f7027a45994284aa5ca8325dd16fd424b0e7e4a4f6d5b1ca019c69f21cc2 )
|
|
libslack-0.5.html.tar.gz
|
(SHA256 edf04b78b1bc273ffe5edbdb2af2cc164f84a8d400e79ea8fcf4e9072d1446d9 )
|
|
libslack_0.5_i386.deb
|
(SHA256 c72775e9073b92eb482b298cbc1da1ae50e0000a88f2dc75e1db22e0dcecfdfa )
|
|
libslack-0.5-1.i386.rpm
|
(SHA256 e7f4ef9a11031f28586f0bf0d13bb01b7e0c0d6a0d75bdc3561a9e4dcd6de701 )
|
|
libslack-0.5-1.src.rpm
|
(SHA256 79d58becefe9de00ca94e2a6956ab7fb934ee1d2dc52cdc6bc7ea5986ed8ff44 )
|
|
libslack-0.5-obsd-i386.tar.gz
|
(SHA256 8515b63b5b15cc05da27252c122bba08b411cbb4088357fda604424c3538d5ce )
|
|
libslack-0.5.sun4u.pkg.gz
|
(SHA256 c4af55f3fb96e561520eec26cce44d0c974ca0188ec435a08249873726794b31 )
|
|
libslack-0.4.tar.gz
|
(SHA256 c02235740f1da0e68f1b3900048b377f2b6057b369f440c42c30f73f6b0e35f7 )
|
|
libslack-0.4.html.tar.gz
|
(SHA256 382889b689af58219c6fb08ef2538b1e4ea4a709a38b96ea9d570e4f2070cd70 )
|
|
libslack_0.4_i386.deb
|
(SHA256 67c8a052641eb58882c92a954cf995c772f079fbbbdda1a7d242e1497ebc7f39 )
|
|
libslack-0.4-1.i386.rpm
|
(SHA256 45160b68ee0d2c5c97b9c042579d868be13e7fcab25251d3b3d3001de5d831bd )
|
|
libslack-0.4-1.src.rpm
|
(SHA256 25ea426bad7325e5ee58fb0999c3f8a7708dd6c47cf3d3a299c0a33563fdc3e1 )
|
|
libslack-0.4.sun4u.pkg.gz
|
(SHA256 8715c76066d865bbc1ba98f7d1ce2669a0c8cfbc0402ab2205d91dc025c78792 )
|
|
libslack-0.3.tar.gz
|
(SHA256 a41f58fc9289ff1841b9f33c4081ab21170b16c301e573a9357f6a06a964211b )
|
|
libslack-0.2
|
(only available as part of daemon-0.2.tar.gz )
|
|
libslack-0.1
|
(only available as part of daemon-0.1.tar.gz )
|