MISCLIB is a modest collection of various short useful functions. As I think about it, I try to sweep various reusable functions in my many ongoing projects into this library. Needless to say, I'm significantly behind in that task. The major components of MISCLIB are: MISCLIB_VERSION - an integer which stores the minor and major versions of MISCLIB in its least-significant and least-significant-but-one bytes. printf ("version %d.%d\n",(MISCLIB_VERSION>>8)&255,MISCLIB_VERSION&255); .. will print the correct version (eg, "version 1.1"). memalloc A function pointer of type "void *(*alloc_ft)(unsigned int)". It is initialized to point at malloc(). This is a useful standard place to "overload" the memory allocation function, so that if at some point in the development of an application you want to change the allocator you are using, you can simply insert a statement assigning memalloc a new value. memfree A function pointer of type "void *(*free_ft)(void*)". It is initialized to point at free(). The purpose of this global variable is Analagous to that of memalloc (above). void *smalloc ( unsigned int n ); smalloc is "smart malloc", a memory allocation function which wraps around malloc(), allows the user to register three "panic" functions, and holds a chunk of heap in reserve against malloc() failure. In the normal case, smalloc(n) will simply call malloc(n), check the result, and return a pointer to the malloc'd memory on success. If malloc() fails then smalloc() will free() the reserved chunk (if has not been freed already) and then it will call malloc() again. If the second malloc() succeeds, then smalloc() will call the "panic1()" function and return a pointer to the malloc'd memory. If the second malloc() does not succeed, then smalloc() will call the "panic2()" function and return NULL. If the first malloc() fails and the reserved chunk is not available for being free'd, then smalloc() will call the "panic3()" function and return NULL. The hope is that in the case of memory exhaustion, smalloc() will be able to free up enough dynamic memory from the reserved chunk for the panic functions to perform some degree of damage recovery or make a report. The panic functions are of type "void *(*sm_ft)(void)". I'm toying with the idea of having an "sfree()" function which wraps free(), and checks to see if the reserved chunk is empty or not so that instead of free'ing the passed memory buffer it could just point the reservation pointer at it. But I'm not sure if that would be reliable enough to be worthwhile. extern int smalloc_error; smalloc_error contains the error status of the last smalloc() call. Error values in v1.1 (subject to change in future versions) are: 0 - no error; everything is okay. 1 - smalloc_init() (qv) failed to allocate a reserved memory chunk. 2 - smalloc(n) was called with n < 1; returning NULL. 3 - in smalloc(): malloc() failed, no reserved memory, calling panic3(). 4 - in smalloc(): malloc() failed twice, despite freeing reserved memory, calling panic2(). 5 - in smalloc(): malloc() failed the first time, but succeeded after free'ing reserved memory, calling panic1(). smalloc_init ( int res_sz, sm_ft *panic1, sm_ft *panic2, sm_ft *panic3 ) Prepares global state for using smalloc() in the application. Allocates a reserved memory chunk (if one hasn't already been allocated by previous call to smalloc_init()), assigns the panic function pointers from the functions given, and assigns the address of smalloc() to the "memalloc" global function pointer. NOTE: If one of the panic functions is NULL, then smalloc() will simply not call it. "res_sz" indicates the size in chars of the reserved memory region. If it is 0 or negative, then the size will be SMALLOC_DEFAULT_RESERVE_SIZE (1MB in v1.1, unless overridden at compile time, eg "make -DSMALLOC_DEFAULT_RESERVE_SIZE='(0x1000)'"). Other miscellaneous functions: char *padstr ( char *str, char pad, int w, char *buf ); padstr() will add enough characters to the left of the given string to make its length equal to "w". It writes the new string out to "buf" and returns a pointer to "buf", eg: char buf[20]; printf ( "%s\n", padstr(" bottles of beer", '1', 18, buf )); will print: 11 bottles of beer This is useful when you have a bunch of variable-length strings to print out one after another, and you want them right-column justified. char *padnum ( int num, int w, char *buf ); char *padhex ( int num, int w, int ucase, char *buf ); These are just wrappers around padstr() and make it handy to turn integers into strings with a fixed length. padnum() will take the number and return a string after padding it to the defined length with spaces (' '). padhex() will do the same, but return the number in hexadecimal and pad it with zeros ('0'). The "ucase" parameter to padhex determines whether the digits will be lowercase (0) or uppercase (!0). char *strndup( char *p, int limit ); char *memdup ( void *p, int n ); void scrub_free ( char *p, int k ); void scrub_free_str ( char *p ); strndup() is just like libc's standard strdup(), except that it allows you to define a maximum length for the string, after which the string will be truncated. It uses memalloc() to allocate memory. memdup() is, again, like strdup(), but instead of duplicating a NULL terminated string, it will duplicate an arbitrary block of data. This is useful when data structures need to be dup'd which might have zeros somewhere inside them. It uses memalloc() to allocate memory. scrub_free() is a wrapper around free() (actually memfree()) that will overwrite the given memory with 0's before freeing it. It is for the security-minded. The integer argument is the length of the memory region pointed to by "p". scrub_free_str() is like scrub_free(), but takes a NULL-terminated string for an argument. int fdpoll ( int fd ); fdpoll() tries to determine how many bytes can be read from file fd without blocking by using the FIONREAD function of ioctl(). If there is an error, it returns the return code of ioctl(). Otherwise it returns the number of bytes that may be read from fd. This is useful, for instance, when detecting whether the user has pressed a key, or if data is available on a socket or pipe without the need for blocking on IO. if ( ( n = fdpoll ( 0 ) ) > 0 ) printf ("The user has pressed %d keys\n",n);