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 http://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 manpages are systematically checked against the source code to make sure that they never get out of sync.
There are plenty of examples in the manpages. 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 manpages 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 manpages because manpages 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, Requirements, Copying, History, References, TODO |
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.6.tar.gz
|
(MD5 0e22e1d38865be2d94372027e5c42b58)
|
libslack-0.6.html.tar.gz
|
(MD5 8687e661c8e3cf591bc33231a9aff553)
|
|
libslack-0.6-1.src.rpm
|
(MD5 c8beb25f8318d1533a9ea12dda7ba0ec)
|
|
libslack-0.6-1.x86_64.rpm
|
(MD5 27744fd69bceca8b0cc4bc0fadd1beb3)
|
|
libslack-0.6-1.i686.rpm
|
(MD5 a9b1e1537479ef07f2694b1ab7243b95)
|
|
libslack-0.6-openbsd-amd64.tgz
|
(MD5 15a435e4323741cacf5bcb01e7b8e02e)
|
|
libslack-0.6-openbsd-i386.tgz
|
(MD5 ab948f0299f2af547b0e52fd5007117d)
|
|
libslack-0.6-freebsd-amd64.tbz
|
(MD5 4534b9c6561d70f2beecea8da7874cfa)
|
|
libslack-0.6-freebsd-i386.tbz
|
(MD5 e4648201679e2cee51c07d95a128bc2a)
|
|
libslack-0.6-netbsd-amd64.tgz
|
(MD5 f97a65cb9d329953c22587703e453f5b)
|
|
libslack-0.6-netbsd-i386.tgz
|
(MD5 1ab96a2b9d4b901368f728e92e58df5f)
|
|
libslack-0.6-macosx-universal.tar.gz
|
(MD5 f724768a9097e14555de1ce829faed8a)
|
|
libslack-0.6-macosx-x86_64.tar.gz
|
(MD5 6966b0481f99f5b80f214a7dcb1644a2)
|
|
libslack-0.6-macosx-i386.tar.gz
|
(MD5 2ed680edefe1b06d6fffb79b72fde0a3)
|
|
libslack-0.6-macosx-powerpc.tar.gz
|
(MD5 5d95ebbaa7c2412db762fcad87a44ce8)
|
|
libslack-0.6-macosx-10.4-powerpc.tar.gz
|
(MD5 d938a42e3387f156d31175a35412658d)
|
|
libslack-0.6-solaris-amd64.pkg.gz
|
(MD5 044d3722ccc73948803edb13167c07bc)
|
|
libslack-0.6-solaris-i386.pkg.gz
|
(MD5 16d5a585bc598102c8c6d7e7cb1bde33)
|
|
| Previous: |
libslack-0.5.2.tar.gz
|
(MD5 9942170b2fba9482ec01e80bafd6adcd)
|
libslack-0.5.2.html.tar.gz
|
(MD5 42da7a3fe9be3ec468dc68715178380a)
|
|
libslack-0.5.2-1.src.rpm
|
(MD5 cb5baafc3a26f28ce9f5b4333cdf0660)
|
|
libslack-0.5.2-1.i386.rpm
|
(MD5 20d7a620ae1cd2f0e58d1c47b3caf676)
|
|
libslack-0.5.2-obsd-i386.tar.gz
|
(MD5 b05528427b6cd1f94f42ca676436dabc)
|
|
libslack-0.5.2-fbsd-i386.tar.gz
|
(MD5 b20d42897184f2ad35688bf73d83bb6a)
|
|
libslack-0.5.2-macosx-powerpc.tar.gz
|
(MD5 cff8885d5e771136b9efa5095baeba9c)
|
|
libslack-0.5.2.sun4u.pkg.gz
|
(MD5 294d4efa672957c0e6bb740b357d8a0d)
|
|
libslack-0.5.2.i86pc.pkg.gz
|
(MD5 2dd948e8580ab8973b7be1ec73108161)
|
|
libslack-0.5.1.tar.gz
|
(MD5 3e9a56f5c72815fa0429edbed422eaf0)
|
|
libslack-0.5.1.html.tar.gz
|
(MD5 48e40b0f9b75a7f7bd5e33d9a1bb497d)
|
|
libslack-0.5.1-1.src.rpm
|
(MD5 9421146784e53f654f0bc5f42116ab8d)
|
|
libslack-0.5.1-1.i386.rpm
|
(MD5 637e5df1bec8729a670f00543402e6b0)
|
|
libslack-0.5.1-obsd-i386.tar.gz
|
(MD5 b3cc970fa6adf22df8e7e7c48fd63c8d)
|
|
libslack-0.5.1-fbsd-i386.tar.gz
|
(MD5 8f61384e6d773acb26cd64eb4baa20e6)
|
|
libslack-0.5.1.sun4u.pkg.gz
|
(MD5 9d4980b993deec7e2ed66b7a78b5c9d4)
|
|
libslack-0.5.tar.gz
|
(MD5 f2ff301ea1c41ebd383bd8a2858bf146)
|
|
libslack-0.5.html.tar.gz
|
(MD5 36aa343a20d31187e0dae762c2b663ad)
|
|
libslack_0.5_i386.deb
|
(MD5 37cc5434066e0ecde72a2f629c91838e)
|
|
libslack-0.5-1.i386.rpm
|
(MD5 e2596c899ad08c0d25ed5e6227e89d67)
|
|
libslack-0.5-1.src.rpm
|
(MD5 4680e74571e68f1d7d73bc9b67ec759e)
|
|
libslack-0.5-obsd-i386.tar.gz
|
(MD5 7d4724376d7ad2e11f9d4cc34362786e)
|
|
libslack-0.5.sun4u.pkg.gz
|
(MD5 87f865886f36b39d836e74f29b62a0ce)
|
|
libslack-0.4.tar.gz
|
(MD5 899867f5b2a8e8210af9b4e2e99f0ae3)
|
|
libslack-0.4.html.tar.gz
|
(MD5 6c2382bf72e6e70b642cfb208a2c2a84)
|
|
libslack_0.4_i386.deb
|
(MD5 7cedbf96e22bd622863f92ea9f9f1bc6)
|
|
libslack-0.4-1.i386.rpm
|
(MD5 a782a9f79abb514e48a49ba6289bbe70)
|
|
libslack-0.4-1.src.rpm
|
(MD5 ab362ae5f3a4b8264a3e26ac42be16bc)
|
|
libslack-0.4.sun4u.pkg.gz
|
(MD5 5b5d8cb4f3beb0fddd2683f315e55575)
|
|
libslack-0.3.tar.gz
|
(MD5 9972edf942e7e98b0d1709ed55c4d11e)
|
|
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)
|
If you'd like to be kept up to date with libslack releases or have questions or suggestions, you can join one or more of the following mailing lists (@libslack.org).
| slack-announce | (Announcements) | |
| slack-users | (User forum) | |
| slack-dev | (Development forum) |
To subscribe to any of these mailing lists, send a mail message to listname-request@libslack.org with subscribe as the message body.
|
Or you can send a mail message to majordomo@libslack.org with subscribe listname in the message body. This way, you can include multiple subscribe commands to subscribe to multiple lists at the same time.
|
A digest version of each mailing list is also available. Subscribe to digests as above but append -digest to the listname.
|
Or
|
Note that these are all extremely low volume mailing lists so there's not much use for the digest lists.