Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Contact Us
Online Help
Domain Status
Man Pages

Virtual Servers

Topology Map

Server Agreement
Year 2038

USA Flag



Man Pages

Manual Reference Pages  -  UKCPROG (3)


ukcprog - Library of utilities for C programmers




In source code,

#include <ukcprog.h>

and link with

cc ... -lukcprog


This is a UKC library, available for the UNIX and VMS operating systems, and for MS-DOS. The source code is freely available so if you want to make a source release of your application you can include a copy of the source of this library as well.


The ukcprog library contains generally useful low level routines. The ukcprog.h header file contains prototypes for the routines as well as defining some useful macros and types.

#ifdef __STDC__
#define PROTO(a)        a
typedef void *voidptr;
#define PROTO(a)        ()
#define const
#define volatile
#define signed
typedef char *voidptr;

The definitions of const, volatile and signed allow these ANSI C keywords to be used in code which must be portable to pre-ANSI C compilers.

The voidptr typedef is similarly there to help with code for pre-ANSI compilers which do not support the void *’ type. Functions which are documented here as returning void *’ return char *’ when compiling with a non-ANSI C compiler.

The PROTO macro is useful for declaring function prototypes for use with ANSI C while still allowing the code to be compiled with K&R compilers. It is used thus:

int myfunc PROTO((int arg1, char *arg2));

With an ANSI C compiler this expands to

int myfunc (int arg1, char *arg2);

whereas a pre-ANSI compiler sees:

int myfunc ();

Note the double brackets; these are necessary to make all the parameters a single argument to the PROTO macro.

#ifndef FALSE
#define FALSE   0
#ifndef TRUE
#define TRUE    1
#ifndef bool
#define bool int

These define the commonly used TRUE and FALSE macros to their usual values. The definitions are protected in case these are already defined. The bool macro is intended to be used to declared variables that are conceptually boolean. A #define is used rather than a typedef because there might already be a typedef for bool.

#ifdef __STDC__
#define CAT(a,b)        a ## b
#define _IDENT(a) a
#define CAT(a,b) _IDENT(a)b
#endif /* !__STDC__ */

The CAT macro can be used to glue two tokens together in the same way as the ANSI C ## operator. CAT also works with many (but not all) pre-ANSI C preprocessors.

void panic(const char *message)

typedef void (*panic_handler_t)(const char *message); panic_handler_t install_panic_handler(panic_hander_t handler)

By default panic() produces a message on stderr of the form

fatal internal error: something (aborting)...

It then calls abort(3) to produce a core dump. Alternative ‘panic handlers’ can be installed using install_panic_handler() which returns the previous handler. Panic handlers can perform tidy-up tasks, such as removing temporary files or calling chdir(2) to arrange for the core to land in a safe place. If a panic handler is called and returns then the default action is carried out.

void *e_malloc(size_t size)
void *e_realloc(void *old, size_t size)
char *strsave(const char *str)

e_malloc() and e_realloc() are error-checking versions of the corresponding routines in the standard C library. They call panic() if the request fails. e_realloc() behaves according to the ANSI specification for realloc(); that is, if old is NULL it behaves like malloc() and if size is 0, it behaves like free(). strsave() allocates some memory using e_malloc(), copies str into it, and returns a pointer to the copy.

char *fpgetline(FILE *fp)

fpgetline() reads characters from the standard IO stream fp until a newline character or EOF is encountered. fpgetline() returns NULL if EOF or an error occurred before any characters were read; otherwise it returns a pointer to the NUL terminated line. fpgetline() never adds a newline to the buffer. The user can check for a missing final newline in a file by checking the EOF flag of the stream pointer when fpgetline() returns a non-NULL pointer.

When fpgetline() returns NULL the caller should check with ferror(3) whether the cause was EOF or an error reading the stream fp.

fpgetline() returns a pointer to a static buffer that is resized as necessary to handle long lines. The caller can modify the contents of the buffer but must not free it or realloc it. The buffer is valid only until the next call of fpgetline().

char *config_trim_line(char *line)

config_trim_line() trims comments and white space in place from a line. First it scans for the first #’ character in the line. If there is one it is removed along with any following characters. Then leading and trailing whitespace characters (as defined by isspace(3)) are removed. config_trim_line() returns a pointer to the trimmed line (which will point into the line that it was given).

A typical use of this routine is to skip blank lines and comments from a configuration file.

typedef void (*errf_ofunc_t)(const char *string);

void errf(const char *fmt, ...) char *strf(const char *fmt, ...)

errf_ofunc_t errf_set_ofunc(errf_ofunc_t func) const char *errf_set_prefix(const char *prefix) const char *errf_get_prefix(void) void_errf_set_progname(const char *progname) const char *errf_get_progname(void) char *formf(char *buffer, int buffer_size, const char *format, va_list args) void errf_usage(const char *usage)

These routines form the basis of a generalised error handling system. errf() formats an error message, much like printf(3), but then passes the formatted text to the ‘current output function’. The default output function appends a newline to the message and sends it to stderr. An alternative output function can be installed with errf_set_ofunc(); it returns the old one which can be re-installed as required. The default output function can optionally prefix the message with a fixed string; this can be inserted with errf_set_prefix(). A pointer to the current prefix is returned by errf_get_prefix(). By convention, this prefix is derived from the name of the program. errf_set_progname() is a convenience routine which, when passed argv[0], munges it in an operating system specific way to produce the program name and sets the prefix to something that looks ‘nice’. A pointer to the program name (after munging) can be obtained by errf_get_progname(). A usage line can be sent to the current output function by errf_usage(); it prefixes

Usage: progname

to its argument, and exits with status 1.

strf() formats a string in the same way as errf(), but returns a pointer to a buffer obtained from malloc(3) that contains the result.

formf() is used in the internal implementation of errf() and strf() and logf() (see below) and is not for the faint-hearted. It is made visible because it is useful if you need to implement other errf()-style functions. In addition to the normal format conversions, formf() provides %m’ which inserts an error message corresponding to the current value of errno into the output string.

int logf_set_ofile PROTO((const char *filename, const char *prefix));
void logf(int level, const char *fmt, ...)
int logf_set_level PROTO((int level));
void logf_errf_ofunc PROTO((const char *str));

These routines are an alternative to syslog (3) for applications that need to log messages to a specified file. logf() handles the fmt format string and arguments in the same same way as errf(). If there has been no prior call to logf_set_ofile() (see below) the message is displayed on stderr, prefixed with the current date and time. If the output is going to a file, logf() tries to ensure that messages from multiple processes to a single log file are interleaved correctly.

The level argument specifies the class of the message; it is one of LG_DEBUG, LG_INFO, or LG_ERR (which are in increasing numerical order). Messages at a level less than the current log level are discarded. The default log level is LG_INFO; it can be set using logf_set_level(), which also returns the previous log level. The log levels LG_ALL and LG_LOG are valid only in calls to logf_set_level(); LG_ALL means log all messages and LG_LOG means log only messages relating to logf() itself.

logf_set_ofile() sets the output file for logf() messages. If the log file does not exist logf_set_ofile() attempts to create it; otherwise it is opened for writing (without discarding any existing contents). If the attempt to create or open the file fails, logf_set_ofile() gives an error message and returns -1, otherwise it returns zero. If the prefix argument is not NULL, the string specified is prepended to all future log messages. logf_set_ofile() makes a copy of the string so it need not be preserved after the call.

logf_errf_ofunc() logs the message str at level LG_ERR. It can be passed as an output function to errf_set_ofunc() to arrange that all error messages are sent to a log file.

ssplit() splits a string into a vector of words, treating occurrences in the string of any of the characters in the delimiters string as word separators.

If the delimiters string starts with a NUL character then multiple adjacent delimiters and leading delimiters generate zero length fields. Otherwise, leading delimiter characters are skipped and multiple adjacent delimiters are treated as a single delimiter. Thus

char **words = ssplit(line, " \t");

will to a shell-like split of a command line into words, and

char **fields = ssplit(pwline, "\0:");

would be good for splitting lines from the password file.

ssplit() returns a NULL terminated vector of words. The space for this vector and the pointed to words is allocated with a (single) call to e_malloc(). ssplit() thus never returns NULL; it aborts the program by calling panic() if memory runs out.

The vector returned by ssplit() should be freed when it is finished with by passing it to free().

int get_host_addr(const char *hostname, struct in_addr *p_addr)

get_host_addr() looks up the IP address of hostname using gethostbyaddr(3). If the lookup succeeds it sets *p_addr to the IP address of the host in network byte order. If the lookup fails it gives an error message with errf() and returns -1. If hostname consists of four decimal numbers separated by dots then get_host_addr parses this as an IP quad and does not call gethostbyname.

int get_service_port(const char *servname, int *p_port)

get_service_port looks up the port number of the TCP service servname using getservbyname(3). If it succeeds it sets *p_port to the port number in network byte order. Otherwise it gives an error message with errf() and returns -1. If servname is an ASCII decimal number then get_service_port() returns that number (again in network byte order).

ebuf_t *ebuf_create(bool errors_are_fatal);
void ebuf_reset(ebuf_t *eb);
ebuf_t *ebuf_start(ebuf_t *eb, bool errors_are_fatal);
int ebuf_add(ebuf_t *eb, const char *buf, int count);
char *ebuf_get(ebuf_t *eb, int *p_len);
void ebuf_free(ebuf_t *eb);

These routines implement variable sized contiguous buffers to which data can be appended at any time. ebuf_create() creates a new zero length buffer. The errors_are_fatal parameter controls the handling of errors; if it is TRUE then all of the routines will call panic() on failure.

ebuf_add() appends count bytes of memory pointed at by data to the buffer eb (which must have been created using ebuf_create()). ebuf_add() returns zero on success. On failure it panics or returns -1 (depending on the setting of errors_are_fatal in the call of ebuf_create()).

ebuf_get() returns a pointer to the current contents of eb; if the p_len parameter is not NULL the current length of the buffer in bytes is stored there. The returned buffer and length are only valid up to the next call of ebuf_add(), ebuf_reset() or ebuf_free().

ebuf_reset() frees the data associated with eb and resets the length to zero. Furthur calls of ebuf_add() can be used to add fresh data to eb. ebuf_free() frees and destroys eb.

ebuf_start() is a convenience routine which either creates or resets a buffer. If eb is NULL it calls ebuf_create() with the supplied value of errors_are_fatal. If eb is not NULL then it is passed to ebuf_reset(). The routine is intended to be used like for static buffers in the following way:

void foo(void)
        static ebuf_t *eb = NULL;
        eb = ebuf_start(eb, TRUE);

The first time the function is called the buffer is created; on subsequent calls it is reset.

alloc_pool_t *alloc_create_pool(void)

void *alloc(alloc_pool_t *ap, int nbytes) void *alloc_ck(alloc_pool_t *ap, int nbytes)

alloc_create_pool() creates a memory allocation ‘pool’ and returns a handle referring to it. alloc() allocates memory like malloc(3) but from the specified pool rather from the general malloc arena. alloc() calls e_malloc() to obtain memory in reasonably large chunks when necessary. This means that it never returns NULL; the program is aborted via panic() if there is insufficient memory to satisfy the request. The alternative interface alloc_ck() returns NULL if it runs out of memory; it is otherwise identical to alloc(). Memory obtained with alloc() cannot be freed individually; only entire pools can be freed.

void alloc_free_pool(alloc_pool_t *ap)
void alloc_reset_pool(alloc_pool_t *ap)

alloc_free_pool() frees an alloc pool, releasing all memory allocated from it with alloc(). The pool is no longer valid after this call. alloc_reset_pool() conceptually frees all the memory associated with a pool but does not return it via free(). The pool remains valid and subsequent calls to alloc() allocate memory from the existing memory associated with the pool if possible.

These routines are suitable for applications which make lots of small allocations for a data structure which is to be freed in one go. alloc() is much faster than malloc() as it does not do the bookkeeping to support individual freeing of allocated memory. It also has no space overhead other than that necessary to correctly align objects in memory.

alloc_create_pool() is a lightweight routine - it involves a single call to malloc() plus some assignments to initialise the pool header structure. It is thus reasonable to use the alloc() routines in situations where there are only going to be a few tens of calls to alloc().

bool alloc_set_default_debug_flag(bool val)
bool alloc_set_debug_flag(alloc_pool_t *ap, bool val)

By default all memory obtained with alloc() and related routines is initialised to the repeated byte 0x53. When memory is freed (with alloc_free_pool(), alloc_reset_pool() or alloc_release()) it is set to the repeated byte 0x42. This is intended to trap erroneous use of uninitialised data and data that has been freed - newly allocated memory contains obvious garbage and freed memory is immediately stamped on.

Of course these safety features cost speed, so they can be turned off globally or per-pool. alloc_set_debug_flag() sets the debugging flag for a pool; memory will be initialised to garbage and stamped on when freed only of the flag is non-zero. alloc_set_default_debug_flag() sets the value of the flag used for pools created from then on with alloc_create_pool(). Both routines return the previous value of the flag they set.

char *allocstr(alloc_pool_t *ap, int nbytes)
char *allocstr_ck(alloc_pool_t *ap, int nbytes)

allocstr() is like alloc() except that it assumes that no alignment is required. It is thus suitable only for allocating space for strings. allocstr() is implemented such that interspersed calls to alloc() and allocstr() will pack both the strings and the other objects tightly in memory with no space wasted on alignment. allocstr() never returns NULL - it panics like alloc() if there is no memory. allocstr_ck() is the same as allocstr() except that it returns NULL if there is no memory.

char *alloc_strdup(alloc_pool_t *ap, const char *s)

alloc_strdup() is a convenience routine that returns a pointer to a copy of a string allocated using allocstr(). Note that it will never return NULL as it uses allocstr() rather than allocstr_ck().

alloc_mark_t *alloc_mark(alloc_pool_t *ap)
void alloc_release(alloc_pool_t *ap, alloc_mark_t *am)

alloc_mark() returns an opaque handle that ‘remembers’ the current position in an alloc pool. A subsequent call to alloc_release() conceptually frees all memory allocated from the pool since the corresponding call of alloc_mark(). Subsequent calls to alloc() et al will reuse the freed memory. A call to alloc_release() renders invalid any marks that were returned after the alloc_mark() call that returned the mark being passed to alloc_release().

const char *ukcprog_version(void)

ukcprog_version() returns a string giving the current version number of the library.


This library treads rather freely on the name space.


Godfrey Paul
Mark Russell

Computing Laboratory, University of Kent at Canterbury.

Search for    or go to Top of page |  Section 3 |  Main Index

UKC Local UKCPROG (3) February 1991

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with manServer 1.07.