/* MLH/MH library of special calls - general, Mike Harrelson */ /* version 3.1 revision 9-9-08*/ /* Copyright (C) 1996-2008 Mike Harrelson The MLH Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The MLH Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is often shipped with GNU software, and is generally kept in a file called COPYING or LICENSE. If you do not have a copy of the license, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ /* Descriptions: {parameter names are denoted by __ } Functions denoted by {*} are absent from libmh.[ch] ::::::::::::::: :::::::::::::::String Functions::::::::::::::: ::::::::::::::: int lib_strtoint(char *val, short *stat) lib_strtoint() converts a string in _val_ to an integer and returns it. The function returns 0 if the value in _val_ is not an integer. If _val_ is zero length, it is assumed to be zero. If _val_ is not an integer, _stat_ is returned as -1, else _stat_ returns as 1. A NULL pointer can be passed instead of a pointer to _stat_ if no conversion status is desired or needed. NOTE: see also atoi(3), strtol(3), atol(3), and strtoul(3) in the standard C library. This function is provided solely for API reasons. ::::::::::::::: char *lib_inttostr(int inval, char *outval) lib_inttostr() converts an int in _inval_ to a string and stores it in _outval_. The pointer to _outval_ is returned if successful. ::::::::::::::: double lib_strtofloat(char *input, int *stat) lib_strtofloat() takes a string representation of a floating point number and converts it to a double float. A leading space is ignored. The function understands -/+ signs at the beginning of the string as positive or negative indicators. The function does NOT understand scientific or engineering expontial notation. If _input_ does not contain a valid floating point number then 0.0 is returned and _stat_ is set to -1, else _stat_ is 0. If the caller is not interested in the status, then NULL can be passed for _stat_. NOTE: see also atof(3) and strtod(3) in the standard C library. ::::::::::::::: char *lib_floattostr(double in, char *out) lib_floattostr() converts a floating point number _in_ to a string to be stored in _out_. The function returns a pointer to _out_. NULL is returned if _out_ is NULL. NOTE: see also gcvt(3) and related functions in the standard C library. ::::::::::::::: char *lib_all_tolower(char *string) char *lib_all_toupper(char *string) lib_all_tolower() converts all characters in _string_ to lowercase while lib_all_toupper() converts all characters in _string_ to uppercase. Both functions return a pointer to _string_. ::::::::::::::: int lib_strip(char *string, char *pattern, short not) lib_strip() strips characters that are or are not in _pattern_ from _string_. The _not_ flag specifies what type of stripping is done. If _not_ is nonzero, then any character in _string_ that is NOT found in _pattern_ will be stripped from _string_. Otherwise any character in _string_ that IS found in _pattern_ will be stripped from _string_. The function returns the number of characters stripped. ::::::::::::::: int lib_bstrip(char *string, int start, int howmany) lib_bstrip() blindly strips a block of characters in _string_. The number of characters to be stripped is in _howmany_. The starting point of the strip is _start_. The function returns the number of characters stripped or -1 if _start_ or _howmany_ are negative values. ::::::::::::::: int lib_strip_nonalphanum(char *string, char stripnums, char *adds) lib_strip_nonalphanum() strips out all characters in _string_ that are not alphabetic or numeric. If _stripnums_ is nonzero then numerical characters will be stripped also. _adds_ contains additional characters that should NOT be stripped. The function returns the length of the resulting string. ::::::::::::::: int lib_chomp(char *string) lib_chomp() truncates a string on a carriage return or linefeed. The function returns 1 if successful or 0 if nothing was done. If _string_ is NULL then -1 is returned. ::::::::::::::: char *lib_chop(char *string, int size) lib_chop() cuts _size_ characters off the end of _string_ and returns a pointer to _string_. NULL is returned if _size_ is invalid. If _size_ is larger than the length of _string_, then _string_ is trunicated to length zero. ::::::::::::::: char *lib_getsubstr(char *string, short start, short end, char *sub) lib_getsubstr() stores a substring from _string_ in _sub_. The starting and ending locations of the substring in _string_ are defined by _start_ and _end_ respectively. A null character is attached to the end of _sub_. The function returns NULL if any parameters are invalid, else a pointer to _sub_ is returned. ::::::::::::::: char *lib_strsub(char *string, char *replacement, short start) lib_strsub() substitutes _replacement_ in _string_ starting at _start_. If any parameters are invalid, NULL is returned. Otherwise, a pointer to _string_ is returned. Note, no overflow checking is done. ::::::::::::::: char *lib_insertstr(char *string, char *insertion, short where) lib_insertstr() inserts _insertion_ into _string_ at location _where_. If any parameters are invalid or out of bounds, NULL is returned. Otherwise a pointer to _string_ is returned. Note, no overflow checking is done. ::::::::::::::: char *lib_insertfiller(char *string, char filler, short size) lib_insertfiller() inserts the character in _filler_ at the beginning of _string_ until its length is the absolute value of _size_. If _size_ is a negative value, then the insertion is at the end of the line instead of at the beginning. For example, if the following code was executed: char string[16]="22"; lib_insertfiller(string,'0',4); 'string' would contain "0022" instead of "22". If _size_ had been -4 instead of 4, then 'string' would read as "2200" instead. If the string already contains at least _size_ characters, then nothing is inserted. The function returns a pointer to _string_. Note, no overflow checking is done. ::::::::::::::: char *lib_replacestr(char *string, char *old, char *new) char *lib_sreplacestr(char *string, char *old, char *new, short which) lib_replacestr() replaces ALL instances of a string _old_ in _string_ with the string _new_. The function returns a pointer to a new string with the replacement(s). The new string is allocated with malloc() and should be free()'d when no longer needed to avoid memory leaks. _string_ is not modified by lib_replacestr(). lib_sreplacestr(), unlike lib_replacestr() only replaces a specific instance of _old_ within _string_ with _new_. If the specific instance of _old_ does not exist, NULL is returned. Otherwise a pointer to _string_ is returned. Which instance of _old_ to be replaced is determined by the value of _which_. If _which_ is 0, no instances are replaced and the function returns a pointer to _string_. If _which_ is negative, then the instance of _old_ to be replaced is from the END of the string and is determined by the absolute value of _which_. If _which_ is positive, then the instance of _old_ to be replaced from the BEGINNING of the string is determined by the value of _which_. NOTE: No buffer overflow checking is done by lib_sreplacestr(). _string_ must be large enough to hold the replacement string. ::::::::::::::: char *lib_revstr(char *string) lib_revstr() reverses the order of the characters in _string_. The function returns a pointer to _string_. ::::::::::::::: int lib_countstr(char *string, char *pattern) lib_countstr() returns a count of how many instances of _pattern_ exist within _string_. If _pattern_ is empty, then -1 is returned. ::::::::::::::: char *lib_dsprintf(int *size, const char *format, ...) lib_dsprintf() is like sprintf except that the memory to hold the string is allocated according to the size of the string to avoid buffer overflow. _format_ holds the format information for the string (see printf() and friends). Not all formats recognized by printf() are implemented but the most commons are (see below). If not NULL, _size_ will hold the amount of memory allocted. The function returns a pointer to the allocated string. The string should be free()'ed when no longer needed to avoid memory leaks. NULL is returned on any errors. The following is an example: char *buff, dog[5]="chow"; int age=5, size, fd; buff=lib_dsprintf(&size,"My dog is a %s and is %d years old.\n",dog,age); fd=open("myfile",O_WRONLY | O_APPEND | O_CREAT); write(fd,buff,size); close(fd); free(buff); NOTE: Most, but not all of the formats recognized by printf() are implemented. Width and precision are recognized on all numerical formats. Width is recognized for %s formats. The following is a list of implemented formats: %s, %c, %d, %ld, %f, %p, %x, %X, %e, %E, %g, %G, %u. ::::::::::::::: char lib_strcap(char *line, char capch, short which) lib_strcap() caps (nul terminates) a string on a specified occurance of the character in _capch_. The string to be modified is passed in as _line_. The parameter _which_ specifies which instance of the character the line is to be terminated on. If _which_ is positive, counting is done from the beginning of the string. Else, if it is negative, counting is done from the end of the string towards the start of the string. The function returns 1 if successful or 0 if nothing was done. If _line_ is NULL then -1 is returned. NOTE: values of 0 or 1 for _which_ are identical in behavior. ::::::::::::::: int lib_strip_whitespace(char *line, char how) lib_strip_whitespace() takes a string stored in _line_ and strips out leading and/or trailing whitespace. If _how_ is positive, then leading whitespace is stripped away. If _how_ is negative, then trailing whitespace is stripped away. If _how_ is 0, then both leading and trailing whitespace are removed. The rest of the string is repositioned to fill the space of vacated leading whitespace. The nul terminator is substituted at the beginnging of trailing whitespace. The function returns how many characters were stripped out or -1 if _line_ is NULL. ::::::::::::::: int lib_strip_8bit(unsigned char *line) lib_strip_8bit() strips out characters whose high bit is 1 (128). The function returns the number of characters stripped out. Characters in the string are repositioned to fill any vacated space. -1 is returned if _line_ is NULL. ::::::::::::::: int lib_strip_unprintable(char *line) lib_strip_unprintable() strips out any characters that do not have a visible or precisely defined print or do not take up exactly one character position when printed. Generally, only characters in the range of 32 (space) to 126 (tilde) can be classified accordingly (in ASCII). The function returns the number of characters stripped or -1 if _line_ is NULL. The remaining characters are repositioned to fill the space that was vacated. ::::::::::::::: int lib_stripendchars(char *line, char begin, char end) lib_stripendchars() examines a string in _line_. If it begins with the character in _begin_ then that leading character is stripped out of the string. If _line_ ends with _end_ then that trailing character is stripped from the end of the string. For example, if _line_ is "(1+2)" and _begin_ is "(" and _end_ is ")", then the function will strip the leading and trailing characters returning "1+2" in _line_. Only the leading and trailing characters are affected, not embedded characters. The function returns 1 if the leading character was stripped, 2 if the trailing character was stripped, 3 if both were stripped, 0 if neither were stripped (no match), or -1 if _line_ is NULL. If _end_ or _begin_ contain nul characters, then they are ignored. ::::::::::::::: char *lib_stringhex_conv(char *line) lib_stringhex_conv() converts a string with embedded ASCII hex values denoted by '%' into the equivalent ASCII values. The resulting string is shorter than or equal in length to the original string. Unknown or incomplete hex values are left alone. For example: Every%20good%20boy%20does%20fine%2E would be converted to: Every good boy does fine. The function returns a pointer to _line_. The case of the hex values is ignored. NOTE: an embedded %00 would cause the string to normally be truncated, but the entire string is processed nonetheless. ::::::::::::::: char *lib_2hex_transform(unsigned char *instring, short sflag, char *outstr) lib_2hex_transform() converts any nonprintable characters in _instring_ including spaces, tabs, newlines, and carriage returns to %## hex equivalents. If _sflag_ is nonzero, then spaces will be converted as well. Any character whose ASCII value is less than 32 (33 if _sflag_ is set) or greater than 125 is considered unprintable. A sample conversion is: "I love hexidecimal.\n" with _sflag_ set to 1 converts to: "I%20love%20hexidecimal.%0A" If _outstr_ is NULL, then memory will be allocated to hold the transformed string. Otherwise, the result is stored in _outstr_ Range checking is not done if _outstr_ is set, but no more than 3X the length of _instring_ will be needed. The function returns a pointer to the resultant string. If allocated, the resultant string should be freed when no longer needed. NULL is returned if an error occurs or parameters are invalid. ::::::::::::::: unsigned char *lib_quote_convert(unsigned char *instring, char *pattern) lib_quote_convert() converts all characters in _pattern_ that are within double quotes in _instring_ to 8-bit equivalents by setting the 8th bit to 1. There should NOT be any 8-bit characters in _instring_ (at least inside the quotes) when the function is called. If _pattern_ is NULL then all 8-bit characters within quotes have their high bit dropped thus effectively undoing the operation. If _pattern_ is empty but not NULL, then whitespace is assumed (space, tab, newline, carriage return). The result is stored in _instring_. The function returns a pointer to _instring_ or NULL if an error occurs. NOTE: double quotes cannot be in _pattern_ as that is the delimiter. ::::::::::::::: int lib_grep(char *pattern, char *teststr, char cflag, char eflag) lib_grep() searches through _teststr_ and determines whether or not it matches the specifications layout in _pattern_. If a match is found, then 1 is returned, else 0 is returned. -1 is returned on any other error. If _cflag_ is 0, then matching will be case sensitive, otherwise, case differences will be ignored (slower). _pattern_ contains a formatted string containing exact characters or "wildcard" characters. An example: _pattern_ = "mx-*.txt.?" matches a _teststr_ containing "mx-blah.txt.1". If _eflag_ is 0, then only '*' and '?' are recognized as wild card characters. If non-zero, then an additional set of wildcards are also recognized. The complete set of wildcards are below: * = matches anything including an empty string ? = matches any single character ---------- # = matches any single digit (and '#' itself) % = matches any single digit (and '%' itself) - same as '#' @ = matches any single alphabetic character (and '@' itself) & = matches any single alphanumeric character (and '&' itself) $ = matches any single whitespace characters (and '$' itself) whitespace includes spaces, tabs, newlines, and carriage returns Additional examples follow: _pattern_="*dog*" matches _teststr_="My dog" _pattern_="*boy does?*" matches _teststr_="Every good boy does fine." but does NOT match _teststr_="Every good boy does" _pattern_="She is # * old." matches _teststr_="She is 3 years old." AND matches _teststr_="She is 1 year old." NOTE: the wildcards also match themselves which may or may not be desired. ::::::::::::::: char *lib_get_match_str(char *text, char *pattern, char cflag, char *lastpos, unsigned char chomp) lib_get_match_str() is a variation on lib_grep() where a copy of a matched pattern within a given string is returned. Unlike lib_grep(), the pattern only needs to exist within the string, not match the entire string exactly. _text_ holds the string to be tested. _pattern_ contains a formated string to be matched against. The special wildcards that can be used for _pattern_ are the same as for lib_grep() {see above} with its _eflag_ set. If _cflag_ is 0, then the matching is case sensitive. Otherwise, case will be ignored for alphabetic characters. Upon successful match, _lastpos_, if not NULL, will hold a pointer to the first position in _text_ after the matched string. If a match is found, then the function returns a pointer to an allocated string to hold the matched string. That memory should be released with a call to free() when no longer needed. NULL is returned if no match is found, or an error occurs. The function only returns to the first matched instance. Additional calls using the information from _lastpos_ can be used to retrieve additional matches. The _chomp_ flag allows the first or last character of the pattern to act as a special delimiter (assuming '*' isn't used for either). If _chomp_ is 1 then the last character in the pattern is treated as a special delimiter and omited. If _chomp_ is 2 then the first character is omitted. If _chomp_ is 3, then both are treated as special delimiters and omitted. ::::::::::::::: char *lib_case_strstr(char *bstr, char *tstr) lib_case_strstr() is a version os strstr(3c) that is case in-sensitive. It searches _bstr_ for any instance of _tstr_. If it finds one it returns a pointer to the first ocurrance of _tstr_ in _bstr_. If it is not found, then NULL is returned. NULL is also returned if an error ocurrs. {See also strstr(3c).} ::::::::::::::: char *lib_replace_char(char *string, char what, char with) lib_replace_char() replaces all instances in _string_ of the character specified by _what_ with the character given by _with_. The function returns a pointer to _string_. ::::::::::::::: int lib_fstrcmp(char *str1, char *str2, char igncase) lib_fstrcmp() does a "fuzzy" string comparison between two strings stored in _str1_ and _str2_. Leading and trailing white space is ignored as well as duplicate white space within the strings. If _igncase_ is nonzero, then the comparison is not case sensitive. Like strcmp(3c), the function returns 0 if the two strings match. 1 is returned if they do not match, and -1 is returned if an error ocurred. White space is defined as a space, tab, newline, carriage return, or a vertical tab. ::::::::::::::: :::::::::::::::Input Functions::::::::::::::: ::::::::::::::: int lib_getastr(char *text, char *strbuf, int size) int lib_gethstr(char *text, char *strbuf, int size) lib_getastr() gets a fixed size string and stores it in _strbuf_. The parameter _size_ holds the maximum number of chars to get NOT including the terminating null. The function returns the number of characters read or -1 if an error occurred. The string in _text_ is printed before input is read. If _size_ equals 0, _strbuf_ is trunicated to length zero, no characters are read, and _text_ isn't printed. lib_gethstr() is identical to lib_getastr() except that a '*' is printed instead of the typed character for the purpose of hiding the input. ::::::::::::::: int lib_getvstr(char *text, char *strbuf, int size, char *pattern) lib_getvstr() is like lib_getastr() except it allows the program to limit what charactes the user can enter. _pattern_ holds a string of characters that will be allowed as input. lib_getvstr() will only work with a terminal and not with redirected I/O as lib_getastr() can. Invalid characters will not even be echoed to the terminal screen. The input string is stored in _strbuf_. _size_ specifies the maximum number of characters to be read (including the terminating null). _text_ is printed before any input is read. If size is less than 2, then _strbuf_ is truncated to zero length, _text_ is not printed, and zero is returned. Any characters entered beyond _size_ are considered invalid and will not be echoed, even if they are in _pattern_. The linefeed indicating the end of input is NOT echoed to the terminal. ::::::::::::::: char *lib_dfgets(FILE *fp, int worksize, short extra, int *ssize) lib_dfgets() is like fgets except that the string to hold the input data is dynamically allocated to avoid buffer overflows or data loss. Input data is read from the FILE pointer _fp_. The parameter _worksize_ determines the initial size of the input buffer being used to read in data. Larger _worksize_ values can significantly improve performance when _worksize_ is large enough to hold a line of input the majority of the time. _worksize_ must be at least 1. lib_dfgets() reads characters from _fp_ until an EOF is encountered or a newline is read. The newline is included in the allocated string. The function returns a pointer to the newly created string or NULL if an error occurs. Strings returned from lib_dfgets() should be free()'ed to avoid memory leaks. The parameter, _extra_, can be used to allocate more space than what is just required to hold the string. _extra_ is in bytes and must be non-negative. If _ssize_ is not NULL, then the total number of characters will be stored in it. If an error occurred, then _ssize_ is untouched. ::::::::::::::: char lib_getvch(char *pattern, char not, char echo) lib_getvch() reads characters from STDIN until a valid input character is pressed. Valid or invalid characters are stored in _pattern_. If _not_ is 0, then any character entered that is in _pattern_ is valid input. If _not_ is not 0, then any character NOT in _pattern_ is valid input. Invalid characters are not echoed to the screen. The function returns as soon as a valid character is entered on the terminal. Line buffering is turned off. If _echo_ is 0, then the first valid character pressed will not be echoed to the screen, otherwise the first valid character entered will be echoed to the screen. The function returns the character entered. ::::::::::::::: char lib_getvchar(char *pattern, char not) lib_getvchar() is a line-buffered version of lib_getvch(). Echo is implied. _pattern_ contains valid (or invalid) characters that can be read as input. If _not_ is 0 then _pattern_ contains a list of valid characters for input. If _not_ is nonzero, then _pattern_ contains a list of invalid characters. Only a valid character is echoed. Only one valid character at a time is allowed to be entered. The function returns the entered character. ::::::::::::::: char lib_getch(void) char lib_getche(void) lib_getch() and lib_getche() get a character from STDIN and return it. They disable line buffering so that when a key is pressed, the function returns immediately. lib_getch() does not echo the character to the the screen while lib_getche() will echo the character to the screen. ::::::::::::::: short lib_keypressed(int interval) lib_keypressed() scans the keyboard for a keypress. If a printable key is being pressed the function returns 1. If no key is being pressed, lib_keypressed() returns 0. lib_keypressed() can be expensive if called often since it will wait at least 0.1 seconds to try to catch a keypress. The _interval_ determines how long the function will scan for a keypress. _interval_ is measured in tenths of a second (0.10 seconds). It does not return 1 if input is waiting in the stdin buffer, but only on a keypress. It returns -1 if an error occurs. It can "miss" keypresses entered in between calls to the function. If _interval_ is less than 1, then it defaults to 1. ::::::::::::::: char lib_readkey(void) lib_readkey() is a nonblocking form of lib_getche(). If a key has been pressed. The function returns the ascii value of the pressed key, else it returns 0. NOTE: The function ignores and discards any buffered data in stdin as it reads directly from the STDIN file descriptor. ::::::::::::::: int lib_noecho(void) int lib_echo(void) lib_noecho() turns off echo to standard input. lib_echo() turns on echo to standard input (the default). Both functions return 1 on success or -1 on error. ::::::::::::::: int lib_linebufferctl(char flag) lib_linebufferctl() allows the user to turn line buffering on terminal input off and on. If _flag_ is nonzero, then line buffering on terminal input is disabled. This allows characters typed to be made immediately available for reading rather than waiting for the ENTER/RETURN key to make the input available. If _flag_ is negative, then terminal echo is turned off as well. If _flag_ is 0, then the terminal is returned to its previous state. The function returns 1 if successfully set to a non-buffered state, 0 if successfully restored, or -1 if an error occurred. *WARNING*: the state of the terminal can be put into an undefined state if the function is called initially with a _flag_ set to 0. The function uses static data to save the state of the terminal. A call to the function with _flag_ set to 0 should only be made after a previous call with _flag_ set to a nonzero value. Also, two consecutive calls to the function with _flag_ set to a nonzero value will cause the initial state of the terminal to be lost. If the user wishes to change the echo status, then the terminal should be restored (with _flag_ set to 0) first, then the function should be called again with _flag_ set to the new value. ::::::::::::::: int lib_rwpoll(int fd, int wait) lib_rwpoll() checks a file descriptor to see if it can be read from or written to without blocking. _fd_ is a valid socket or pipe descriptor. _wait_ is the time (in milliseconds) to poll for before returning a status. If _wait_ is negative, then infinity is assumed. The return value sets bits depending on the results from poll(2). If the 1 bit is set, then the descriptor can be read without blocking. If the 2 bit is set, then the descriptor can be written to without blocking. If a polling error occurred, then the 4 bit is set. The bits are logically ORed together. For all other errors, -1 is returned. NOTE: if the function was interrupted by a signal, then -2 is returned. ::::::::::::::: int lib_readpoll(int fd, int wait) lib_readpoll() checks a file descriptor, _fd_, to see if any data can be read from it without blocking. If the file descriptor has waiting data that can be read, then 1 is returned. If not, 0 is returned. If _fd_ is invalid or is not readable, then -1 is returned. The _wait_ parameter allows the caller to set the timeout for the function. If _wait_ is negative then the function will wait forever until an event occurs. Otherwise the function will wait up to _wait_ milliseconds for an event to occur. A value of 0 for _wait_ causes the function to return immediately. The function will return -2 if the poll call was interrupted by a signal (and not restarted) or -1 for any other errors. ::::::::::::::: int lib_readpoll2(int fd1, int fd2, int wait) lib_readpoll2() checks two file descriptors to see if either (or both) has any data that can read without blocking. If either are invalid or not readable, then -1 is returned. If _wait_ is nonzero, then the function will block up to _wait_ milliseconds or until read data (for either) is available. If 0, then the function will return immediately with the read status of both. A negative value for _wait_ causes the function to wait forever until one or both descriptors is readable. If only the first file descriptor, _fd1_, has data that can be read without blocking then a 1 is returned. If only the second, _fd2_, has readable data, then 2 is returned. If both have readable data, then 3 is returned. If neither has any data that can be read without blocking, then 0 is returned. 0 should never be returned if _wait_ is negative. The function returns -2 if the call was interrupted by a signal (and not restarted) or -1 on any other errors. ::::::::::::::: int lib_mknonblockfd(int fd) lib_mknonblockfd() puts a pipe/socket descriptor, _fd_, into nonblocking mode. If the descriptor is already in nonblocking mode, then 0 is returned. 1 is returned if the operation was successful. If _fd_ is invalid or an error occurs, then -1 is returned. ::::::::::::::: int lib_mkblockfd(int fd) lib_mkblockfd() takes a pipe/socket descriptor, _fd_, out of nonblocking mode. If the descriptor was not in nonblocking mode, then 0 is returned. 1 is returned if the operation was successful. If _fd_ is invalid or an error occurs, then -1 is returned. ::::::::::::::: :::::::::::::::File Functions::::::::::::::: ::::::::::::::: FILE *lib_fopenlock(char *path, char *mode, char wait) lib_fopenlock() opens the file named in _path_ with the modes in _mode_ and tries to place a kernel advisory lock on the file. If _wait_ is 1 then the function will wait until it can lock the file if it is already locked. If _wait_ is 0, the function will return immediately with an error if the file is locked. NULL is returned for all errors, else, a FILE pointer is returned. Modes (_mode_) can be "r","r+","w","w+","a", or "a+". A file opened with mode "r" is locked with a shared read lock. All other modes are locked with exclusive write locks. NOTE: Unlike fopen(), lib_fopenlock() will create a file that doesn't exist if mode "r+" is used. ::::::::::::::: int lib_fcloselock(FILE *fp) lib_fcloselock() unlocks and closes a file previously opened with lib_fopenlock(). If the FILE pointer _fp_ is invalid, a -1 is returned, else 1 is returned. ::::::::::::::: int lib_sflock(char *lockfile, int timeout) lib_sflock() attempts to create a semafore file (in reality, a symlink) called _lockfile_. If the semafore file already exists, then the function will keep trying every fifth of a second until it has tried for _timeout_ seconds. If _timeout_ is 0, the function returns immediately upon the first failure. If the lock file is made successfully, the PID, hostname, and current time (in epoch seconds) is written as the file contents (symlink info). The function returns a lock descriptor upon success, or 0 if the file is locked. -1 is returned for any other errors. The lock descriptor is a checksum of the lockfile's contents and is used in lib_sfunlock() to verify that the lock file being removed matches the lock descriptor originally returned (see below). ::::::::::::::: int lib_sfunlock(char *lockfile, int lockval) lib_sfunlock() removes a semafore file _lockfile_. The function returns 1 on success or -1 on error. If _lockval_ does not match the contents of the lock file, then -1 is returned. The function will also fail if the calling process does not have permission to delete the file. Note, that it is possible to spoof the lock descriptor in _lockval_ since it may not be a unique value. It only exists to enable some level of checking whether _lockfile_ is actually a semafore lock file (or the same lock file). Unlink() can be used to forcibly remove the file. ::::::::::::::: int lib_getsflockinfo(char *lockfile, char *infostr, int size) lib_getsflockinfo() tests to see if a semafore file lock called _lockfile_ exists and retrieves PID, hostname, and timestamp information from the lock file contents. If the file does not exist, 0 is returned, else the current lock descriptor of the lock file is returned. -1 is returned on any other errors. The lock file information is stored in _infostr_. _size_ specifies the size of _infostr_ in order to avoid overflowing the buffer. The information stored in _infostr_ is of the form PID:HOSTNAME:TIME. PID is the pid of the process that created the lock file. HOSTNAME is the hostname of the machine from which the lock file was created. TIME is the time the lock file was created. TIME reflects the time in seconds from the epoch of the host from which the lock file was created. HOSTNAME becomes variable only on shared filesystems such as NFS. ::::::::::::::: int lib_getumask(void) lib_getumask() returns the current umask as an integer coded octal. Normally umasks are stored in octal, so that a umask 022 in octal is returned as 18 in decimal by umask(2). lib_getumask() would code it as twenty-two instead of 18. Each octal digit is made into an integer digit. ::::::::::::::: int lib_setumask(int um) lib_setumask() sets the umask of a process as _um_. _um_ is a new umask stored as integer coded octal (see lib_getumask() ). Each integer digit is made into an octal digit. For example, integer 22 becomes octal 022. The function returns 1 if the change was successful, 0 if the umask was identical to the changed value, and -1 if _um_ was not a valid umask. ::::::::::::::: int lib_log(char *logfile, char *logdata, ...) lib_log() logs the data in _logdata_ as text in _logfile_. The data is appended to the existing logfile and a newline is added to the end of _logdata_. The function returns -1 if an error occurs, otherwise it returns the number of characters written out. _logdata_ uses the same format as printf(). Not all formats recognized by printf() are implemented (see NOTE: under lib_dsprintf() ). ::::::::::::::: int lib_dlog(int ld, char *procname, char *message) lib_dlog() is similar lib_log() except that a time stamp is prepended to the message text along with the process "name" and PID. Also, the log file is assumed to already be open for appending, and its file descriptor stored in _ld_. The function, if successful, returns the number of bytes written or -1 if an error occurred. See lib_timestamp() for the format of the prepended text. ::::::::::::::: long long lib_fcopy(char *source, char *dest, char lock) lib_fcopy() copies the file _source_ to _dest_. If the destination file does not already exist, then it is created and has the same permissions as the source file. If _lock is nonzero, lib_fcopy() tests and sets an advisory lock on both files. If _lock_ is 0, then any existing advisory locks on the files are ignored and no advisory locks are set. The owner and group of the new file are those of the calling process. The function returns -2 if a locking error occurs or -1 on any other errors or invalid parameters. Otherwise the number of bytes copied is returned. If _source_ and _dest_ are the same file, the size of the file is returned but no copying is done. Note: lib_fcopy() understands sparse files and copies accordingly such that if the source file is a sparse file, then the destination file will also be a sparse file when the function completes. ::::::::::::::: long lib_ftrans(FILE *from, FILE *to) lib_ftrans() transfers all data in one open file to another open file creating a mirror of the original. Both files must exist. _from_ and _to_ are FILE pointers to the two open files. Data is transferred from the file pointed to by _from_ to the file pointed to by _to_. Any data already in the file pointed to by _to_ is lost. The function flushes and rewinds both streams before and after doing the transfer. The function returns the number of bytes transferred if successful. Otherwise -1 is returned if an error occurs or _from_ and _to_ are invalid or do not represent files. Neither _from_ nor _to_ are closed after the operation. ::::::::::::::: long lib_fdtrans(int from, int to) lib_fdtrans() is identical to lib_ftrans() except that it uses the file descriptors _to_ and _from_ instead of FILE pointers. The function lseeks to the beginning of both files before and after the operation. Any previous data in _to_ is lost. See lib_ftrans() for more info. ::::::::::::::: int lib_append(char *from, char *to, char lock, char truncat) lib_append() appends the file _from_ to file _to_. If _lock_ is nonzero, then an advisory lock is placed on both files while the operation is going on. If _truncat_ is nonzero, then _from_ will be truncated to zero length when the function completes. If _to_ does not exist, then it is created. The function returns 1 if successful, else it returns -1. ::::::::::::::: int lib_fappend(int from, int to) lib_fappend() appends the data in the open file represented by _from_ to the open file represented by _to_. The files are NOT closed when the operation is completed. The function returns 1 on success or -1 on error. -1 is also returned if the file descriptors _from_ or _to_ are not valid open files on seekable devices. The file position of _to_ is positioned at the end of the file, and _from_ is positioned at the beginning of the file when the operation is completed. ::::::::::::::: int lib_flock(int fd, char locktype, int wait) lib_flock() places an advisory lock on an entire open file. _fd_ is a file descriptor of an open file. _locktype_ determines what kind of lock is to be placed on the file. The following values are valid for _locktype_: 0 = unlock, 1 = read/shared lock, 2 = write/exclusive lock. Multiple read locks can be in place, but only one write lock can be active at a time and cannot coexist with a read lock. If _wait_ is 0, then the function returns immediately whether a lock was established or not. If _wait_ is nonzero, then the function will block until a lock can be established. The function returns -1 if _locktype_ is out of range. If _fd_ does not point to an open file or a lock could not be established, then -1 is returned and errno is set. A value other than -1 is returned on success. ::::::::::::::: char *lib_getfilename(char *path) lib_getfilename() retrieves the actual filename from a full or relative path. For example, if _path_ = '/usr/local/etc/blah.conf', then the function would return a pointer to 'blah.conf' within _path_. If there is no valid filename then NULL is returned. NOTE: paths ending with '/' are assumed to be directories and not files, so NULL would be returned. See also lib_last_path_element() below. ::::::::::::::: char *lib_last_path_element(char *path, char *element) lib_last_path_element() returns the last element in a given file system path. Any leading or trailing slash is not included unless the root directory ('/') is the last (and only) element. The element string is stored in _element_. The function returns a pointer to _element_ or NULL if either paramenter is NULL. No bounds checking is done, so _element_ needs to be at least the same size as _path_. ::::::::::::::: char *lib_getpathdir(char *path, char *dirpath) lib_getpathdir() returns the directory only portion of a path (minus the last element). The trailing slash (if any) is not included. The resulting string is stored in _dirpath_. If either parameter is NULL, then NULL is returned. No bounds checking is done, so _dirpath_ needs to be at least the same size as _path_. Multiple leading and integrated slashes are NOT condensed. ::::::::::::::: int lib_condense_path(char *path, char trflag) lib_condense_path() takes a given path and condenses multiple consecutive slashes into single slashes. _path_ holds the original path when passed in. The result of the function is then stored in _path_ overwriting the original path string. If _trflag_ is nonzero then a trailing slash will be kept (if present), otherwise a trailing slash is considered redundant and is stripped off. The function returns the length of the new path or -1 if _path_ is _NULL. ::::::::::::::: int lib_get_file_ext(char *file, char *ext) lib_get_file_ext() retrieves from the end of the filename in _file_ a trailing extension delimited by '.' The extension is stored in _ext_. For example, if _file_ contains the string 'foo.jpg', then 'jpg' is stored in _ext_. The delimiting '.' is not included. If the only '.' delimiter is the first character in the filename, then it is not treated as a delimiter. If there is no delimited extension, then _ext_ holds an empty string. NOTE: no overflow checking is done. As a result, _ext_ should be at least the same size as _file_. The function returns the length of the extension stored in _ext_. ::::::::::::::: int lib_match_inode(char *path1, char *path2) lib_match_inode() takes two given paths in _path1_ and _path2_ and compares them to see if they are the exact file system object (eg. hardlinked together). If they are the same then 1 is returned. If they both exist, but are not the same object, then 0 is returned. If one or both do not exist, or an error occurred, then -1 is returned. ::::::::::::::: int lib_match_fs(char *path1, char *path2) lib_match_fs() takes two given paths in _path1_ and _path2_ and compares them to see if they are on the same file system device. If they are, then 1 is returned. If they both exist, but are NOT on the same file system device, then 0 is returned. If one or both do not exist, or an error occurred, then -1 is returned. ::::::::::::::: int lib_getfiletype(char *path) lib_getfiletype() determines the type of file referred to by _path_. If an error occurs or the object does not exist, then -1 is returned. If the object does exist, then the following return types are possible: 1 regular file 2 directory 3 symlink 4 block device 5 char device 6 named pipe 7 socket 0 unknown, but it DOES exist Only standard Unix types are checked for. Anything else returns zero. ::::::::::::::: int lib_compare_filenodes(char *path1, char *path2) lib_compare_filenodes() compares the inode attributes of two files specified by _path1_ and _path2_. Both file objects must exist. Seven attributes are compared: file type, permissions, UID, GID, size, modification time, and if they are syminks, what they point to. If any attributes are not equal, a corresponding bit is set in the return value. The bits are as follows: 1 : file types 2 : permissions 4 : UID 8 : GID 16 : sizes (in bytes) 32 : modifcation times (mtime only, atime is ignored) 64 : symlink pointer (only if both are symlinks) The bits are logically ORed together. If all attributes are equal, then the return value is 0. Otherwise the result of all of the bits ORed together is returned. For example, if the UID and file sizes are different, then (4 | 16 = 20) 20 is returned. The function returns -1 if an error occurs. Note: if both objects are symlinks, then the mod times are ignored. ::::::::::::::: int lib_compare_filecontent(char *path1, char *path2) lib_compare_filecontent() compares the contents of two regular files pointed to by _path1_ and _path2_. If their contents are equal, then 0 is returned. Otherwise, an 1 is returned. If an error occurs, then a -1 is returned. Note: symlinks are followed in that the file pointed to is compared. ::::::::::::::: int lib_is_sparsefile(char *path) lib_is_sparsefile() determines whether or not _path_ is a sparse file or not. If _path_ is a sparsefile, then 1 is returned, else 0 is returned. A -1 is returned if an error occurs. Notes: a symlink is followed in that the file pointed to is checked. ::::::::::::::: int lib_fcat(char *filename, int output) lib_fcat() opens a file and sends its entire contents to a file descriptor pointed to by _output_. Upon completion, the function returns the number of bytes read/written out. If an error occurs at any point, -1 is returned. If the total number of bytes read/written exceeds what an integer data type can hold, then 0 is returned. ::::::::::::::: int lib_diffstat(char *path, struct stat *inbuf, struct stat *outbuf) lib_diffstat() takes the results of a previous call to stat()/lstat() and compares it with the currecnt stat of the object specified by _path_. _inbuf_ contains the results of an earlier call to stat()/lstat(). _outbuf_, if not NULL, will store the results of the new comparison. The function returns a 1 if there is a change, 0 if not. -1 is returned if an error occurs. The function checks mtime, size, ctime, mode, inode, uid, gid, blocks, and device. ::::::::::::::: long lib_getfilesize(char *path, unsigned int *blocks) lib_getfilesize() retrieves the size of a regular file pointed to by _path_. If _blocks_ is not NULL, the number of 512 byte logical disk blocks is stored in it. The function returns the number of bytes for the file size or -1 if an error occurs. NOTE: special compile time flags may be required for argefile operations. ::::::::::::::: int lib_getfilesize2(char *filename, int *remainder) lib_getfilesize2() is similar to lib_getfilesize() but instead returns the file size in Kbytes instead of bytes. The number of leftover bytes is put in _remainder_ if it is not NULL. -1 is returned if an error occurs. _filename_ holds a pointer to the filesystem object to be checked. NOTE: special compile time flags may be required for largefile operations. ::::::::::::::: int lib_getfileguid(char *path, int *gid) lib_getfileguid() looks up the owner for a file system object pointed to by _path_. If _gid_ is not NULL, then the group owner is stored in it. The function returns the user ID (numerical) of the file or -1 if an error occurs. ::::::::::::::: int lib_getfileperms(char *path) lib_getfileperms() returns the specified inode mode+permissions. It is the equivalent of calling lstat() and returning the stat.st_mode value. _path_ points to the filesystem object. -1 is returned if an error occurs. ::::::::::::::: int lib_isfileopen(char *file) lib_isfileopen() checks to see if any processes have the file pointed to by _file_ open. The function returns 0 if not or 1 if yes. If the file does not exist or an error occurs, then -1 is returned. NOTE: this function is only known to work on Linux and Solaris (with /proc mounted). On other operating 0 or -1 may be returned. ::::::::::::::: :::::::::::::::IPC/Network Functions::::::::::::::: ::::::::::::::: int lib_open_tcp_connection(char *host, int port) lib_open_tcp_connection() establishes a connection to _host_ on port _port_ and attaches a socket to the connection. If a successful connection is made, then a valid socket descriptor is returned. If port is invalid, _host_ is not a valid IP address or host name or is NULL, then -1 is retuned. If the socket could not be created, then -2 is returned. If the connection was refused, then -3 is returned. The socket created is of domain AF_INET and type SOCK_STREAM with protocol 0. Note: this function may not be thread-safe if _host_ is NOT an IP address. {*} ::::::::::::::: int lib_init_tcp_connection(char *host, int port, int *status) lib_init_tcp_connection() initiates a TCP connection asynchronously. It returns a valid socket descriptor even though the connection has not yet completed. Upon return, _status_ holds either a 1 or a 0 depending on the progress the connection has made. _status_ will have a 1 if the connection is in progress or 0 if it is completed. _host_ contains either an IP address or a hostname that we are connecting to. _port_ specifies the TCP port to connect to on the remote host. If a connection error occurs, then a -1 is returned. If an error occurs while resolving _host_, then -2 is returned. NOTE: though the function is nonblocking, if a DNS lookup for _host_ hangs, then the function will block until a response or timeout is received. Use of the IP address instead of a hostname will avoid that problem. Also note that the socket descriptor returned is in a nonblocking state. ::::::::::::::: int lib_make_tcp_socket(int port, short backlog, long ip) lib_make_tcp_socket() creates a server side socket that binds to _port_ to await incoming connections. _backlog_ determines how many connection can be queued for processing. The lib_acceptconnect() must be used to actually handle each incoming connection/request. Ports below 1000 can only be bound to by a priviledged user. _ip_ determines which IP address on the machine to bind to. If _ip_ is zero, then all interfaces/IP addresses are bound to. The function returns a valid socket descriptor upon success or -1 if any parameters are invalid. If the socket for the connection could not be created then -2 is retuned. If the socket could not bind to the IP/port then -3 is returned. NOTE: the C library function, inet_addr(3N), can be used to convert an IP address string of the form "a.b.c.d" to its numerical representation which can then be passed in _ip_ (which should be in network byte order). {*} ::::::::::::::: int lib_acceptconnect(int sd, int *nsd, char nowait) lib_acceptconnect() will check for an incoming connection on the port associated with _sd_ ( _sd_ was previously returned from lib_makesocket() or lib_makeusock(), see above and below). If successful, the function will store a unique socket descriptor for the connection in _nsd_. Otherwise, -1 is assigned to _nsd_. If _nowait_ is nonzero, the function will return immediately whether a connection was made or not. If _nowait_ is zero, the function will sleep until an incoming connection is made. The function returns 1 if a connection was made, 0 if no connection was made and _nowait_ was nonzero, or -1 if an error occurred. The function will return -2 if it was interrupted by a signal (and not restarted). NOTE: If the server forks a child to handle the request, the server(parent) should close the new socket after the fork(), and the child should close the original socket descriptor, _sd_, unless they are both needed by each. {*} ::::::::::::::: int lib_gethostinfo(int sd, char *ipaddress, char *hostname) lib_gethostinfo() returns the ipaddress and, if possible, the host name associated with that IP address, of an open socket descriptor _sd_. If _sd_ is not a valid socket descriptor, -1 is returned and _ipaddress_ and _hostname_ are untouched. If _sd_ is a valid socket descriptor, the IP address of the client/server at other end of the socket is stored in _ipaddress_. If a host name can be associated with that IP address, it is stored in _hostname_, else _hostname_ will contain the IP address. The function returns 0 if no host name exists and 1 if a host name does exist. If _hostname_ is NULL, then it will be ignored and 0 is returned. {*} ::::::::::::::: int lib_make_udp_socket(unsigned long ip, int port) lib_make_udp_socket() creates a local UDP socket on the server and binds to it. _ip_ contains the local IP address (interface) for the socket. If _ip_ is 0, then the socket is visible to all addresses/interfaces. _port_ specifies which local port the socket is to be bound to. The function returns the new socket descriptor if successful. If _ip_ or _port_ are invalid then -1 is returned. If the socket could not be created then -2 returned. If the socket could not bind to the IP/port then -3 is returned. NOTE: the C library function, inet_addr(3N), can be used to convert an IP address string of the form "a.b.c.d" to its numerical representation which can then be passed in _ip_ (which should be in network byte order). {*} ::::::::::::::: int lib_make_udp_addr(struct sockaddr_in *sock, unsigned long ip, int port) lib_make_udp_addr() populates an existing struct sockaddr_in for use in UDP operations. _sock_ is a pointer to an existing struct sockaddr_in variable which is to be populated. _ip_ holds the IP address/interface of the machine to be connected to. _port_ holds the network port of the machine to be connected to. The function returns 1 if successful, or -1 on error leaving _sock_ untouched. ::::::::::::::: int lib_open_unix_socket(char *name) lib_open_unix_socket() opens a UNIX type socket connection to the socket identified by _name_. If the _name_ is invalid then -1 is returned. If a new socket could not be created then -2 is returned. If the specified socket could not be opened, then -3 is returned. Otherwise a valid socket descriptor is returned. The socket connection is of domain AF_UNIX and type SOCK_STREAM with protocol 0. {*} ::::::::::::::: int lib_make_unix_sock(char *name, int backlog) lib_make_unix_sock() creates a UNIX type socket identified by _name_ and binds to it. _backlog_ specifies the connection queue size. lib_acceptconnect() must be used to actually handle each incoming connection/request. The function returns a valid new socket descriptor on success. If _name_ is invalid then -1 is returned. If the socket could not be created, then -2 is returned. If the socket could not bind to the file system object given by _name_, then -3 is retuned. NOTE: on some OSes, _name_ may be limited in length, hence the function limits it to 13 characters. {*} ::::::::::::::: int lib_nslookup(char *hostname, char *ipaddress) lib_nslookup() resolves the IP address of _hostname_ and stores it in _ipaddress_ if _ipaddress_ is not NULL. If _hostname_ has more than one IP address, the IP returned is randomly selected and placed in _ipaddress_ and the rest are ignored. The number of IP addresses found is returned if successful. If _hostname_ has no valid IP address associated with it (eg. a domain name only), then 0 is returned. If _hostname_ does not exist then -2 is returned. If there is no response from a nameserver, then -3 is returned. If there is some other DNS error, then -4 is returned. For any other error, or if _hostname_ is NULL or is of zero length then -1 is returned. {*} ::::::::::::::: int lib_dnslookup(char *hostname, struct ip_type *ip) lib_dnslookup() resolves the IP addresses of _hostname_ and stores them in _ip_. The number of IP addresses found is returned if successful. If _hostname_ is not valid, then -2 is returned. If the nameserver does not respond then -3 is returned. For an unrecoverable DNS error, -4 is returned. For all other errors, -1 is returned. lib_dnslookup() can be used to get all IP addresses associated with _hostname_ whereas lib_nslookup() will only retrieve one of the IP addresses returned. struct ip_type is defined by: struct ip_type { char address[32][16]; <-array of IP addresses (32 addrs X 16 bytes) short size; <-number of IP addresses in array }; {*} ::::::::::::::: int lib_revnslookup(char *ipaddress, char *hostname) lib_revnslookup() takes an IP address in _ipaddress_ and looks up the host name associated with that IP address via reverse DNS lookup. If no host name can be found, 0 is returned and _hostname_ is truncated to zero length. Otherwise, if one is found, the function returns 1 and the host name is stored in _hostname_. If _ipaddress_ is not a valid IP address or an error occurs then -1 is returned. This function ignores aliases and returns only the primary host name. {*} ::::::::::::::: int lib_check_cidr(char *ipaddress, char *cidr) lib_check_cidr() takes an IP address in standard a.b.c.d notation and a CIDR string in the form of x.y.z.t/nn and does a bitwise comparison to see if the network ID matches. The function returns 1 if they match or 0 if they don't. If an error ocurrs at any point, then -1 is returned. ::::::::::::::: int lib_check_ipblock(char *ip, char *range) lib_check_ipblock() is similar to lib_check_cidr(), but does string compare matching to verify the block. It's functionality for IP addresses is largely obsolete as lib_check_cidr() provides the needed functionality for numerical addresses. _ip_ is a pointer to an IP address. _range_ is a pointer to an IP address or substring of such (eg. '192.168.54'). A match occurs if the sets of octets match (eg. '192.168.54.12' matches the above example while '192.168.100.34' does not as the third octet is different). The function returns 1 if a match is found, or 0 if not. If any imput parameters are invalid then a -1 is returned. ::::::::::::::: int lib_check_fqdn_match(char *hostname, char *domain) lib_check_fqdn_match() attempts to match a fully qualified hostname to a given domainname. If _hostname_ and _domain_ match exactly then 1 is returned. If a partial successful match can be made, then 2 is returned. An example of a successful partial match is a _hostname_ value of 'www.blah.com' and a _domain_ value of 'blah.com' or 'com'. The function deals with parameters up to 127 characters in length. Anything longer is considered invalid. 0 is returned if no match can be made. -1 is returned if any parameters are invalid. ::::::::::::::: int lib_hostlookup(char *hostname, char *hostfile, char *ipout) lib_hostlookup() looks up the IP addresss of _hostname_ in the file specified by _hostfile_. The result, if found, is stored in _ipout_. The format for the file in _hostfile_ is the same as for /etc/hosts: IP FQDN [alias1, alias2, ...] The function stores the IP address in _ipout_ in dot-notation format. The function returns 1 if found, 0 if not. -1 is returned if an error occurs. DNS is not consulted. If _ipout_ is NULL, then it is ignored. ::::::::::::::: int lib_rhostlookup(char *ipin, char *hostfile, char *hn) lib_rhostlookup() looks up the FQDN of a given IP addresses put in _ipin_. A resulting match is stored in _hn_. _hostfile_ contains the filename of a hosts file in the same format as /etc/hosts {see lib_hostlookup()}. If a match is found, then 1 is returned. If none is found then 0 is returned. If any errors occur then -1 is retunred. DNS is not consulted. If _hn_ is NULL, then it is ignored. ::::::::::::::: int lib_dns_query(char *fn, short type, char *nip, struct dns_rec *rrec, short retry, short retran) lib_dns_query() is a low-level function wrapper to perform several types of DNS queries. _fn_ holds an dot-notated IP address, a hostname, or a domain name, depending on the query type. _type_ defines what type of query to be performed. It's values can be one of: 0 : A (A record) 1 : PTR (reverse) 2 : CNAME (aliases) 3 : NS (nameserver record) 4 : MX (mail exchange) The _nip_ parameter, if not NULL, holds a dot-notated IP address of a valid nameserver to be queried against. If NULL, the default nameservers will be used instead. _rrec_ holds the reply to the query. It's structure is defined as: struct dns_rec { unsigned char ip[32][96]; //response records unsigned short wt[32]; //weights, if returning MX records short icount; //count of records in dns_rec.ip short itype; //type of responses int ttl; //reserved for TTL, not currently used }; The function, if successful, fills in the members of the above struct. The values for rrec->itupe are defined in resolv.h to be T_A, T_PTR, T_CNAME, T_NS, and T_MX, etc. The last two parameters, _retry_ and _retrans_ allow the caller to specify how long to wait to do retransmits and how many times to retry the query against the specified nameserver(s). These two parameters are used to limit the timeout value. The results of a successful query are stored in _rrec->ip as strings_ and must be checked with inet_addr() if an IP address is expected. The function returns the number of available records on success or -1 if an error occurs. ::::::::::::::: :::::::::::::::Date & Time Functions::::::::::::::: ::::::::::::::: char lib_gettime(int *hour, int *min, int *sec, char nomil) lib_gettime() gets the current time and stores the hour, minute, and seconds in _hour_, _min_, and _sec_ respectively. IF the flag _nomil_ is 0, then the the time returned will be in military time, otherwise, if nonzero, it will be in civilian time. The function returns 'a' or 'p' depending on whether it is AM or PM. Military time is expressed as hours 0-23. Civilian time expressed as hours 1-12 am/pm. The 'a' or 'p' return value is the only way to determine whether it is morning or afternoon if civilian time is selected in _nomil_. The function returns '\0' if an error occurs. If _hour_, _min_, or _sec_ is NULL then that parameter will be ignored. ::::::::::::::: char *lib_getdate(int *mon, int *day, int *year, char *dayofwk, char *month, int offset) lib_getdate() gets the current date and stores the month, day, and year in _mon_, _day_, and _year_ respectively. The current day of the week is stored in _dayofwk_. The day of the week is stored as the full name (eg. Monday, instead of Mon). The year is stored as the full year (eg. 1997, not 97). A pointer to _dayofwk_ is returned by the function. The name of the month is returned in _month_ and is specified as its full name. The parameter _offset_ can be used to change what the function thinks is the "current date." The _offset_ is in days. For instance, an _offset_ of -1 would cause the function to return a date one day ago from the real current date (or yesterday's date), while a 1 would return tommorrow's date. An offset of zero should be used if the real current date is desired. If a field is NULL then no value will be stored in it and will be ignored. This is useful if the caller is only interested in part of the date, not all of it. The range of months in _mon_ is 1 througth 12 (not 0 to 11). ::::::::::::::: char *lib_timestamp(char *title, char *buffer) lib_timestamp() returns a string with the current time stamp and PID of the process. _title_ is a header to be included with the PID (usually the name of the process). The result is stored in _buffer_. The format is: DoW MMM DD HH:MM:SS YYYY: _title_[PID]: Eg.: "Thu Jan 26 13:43:12 1999: mydaemon[12345]: " The function returns NULL if an error occurrs. Otherwise, a pointer to _buffer_ is returned. No string overflow checking is done. The time stamp returned by lib_timestamp can be used to complete or enhance log entries. See also lib_dlog(). ::::::::::::::: char *lib_value_to_month(int mon, char *month, char shsized) lib_convert_month() takes a month value in _monval_ and converts it to its character equivalent. _monval_ is of the range 1 to 12. A value of 1 will convert to "January" and 12 to "December". If _shsized_ is nonzero then the conversion will be truncated to 3 characters (eg. "January" becomes "Jan"). The converted month is stored in _month_. If successful, the function returns a pointer to _month_. If _monval_ is out of range or _month_ is NULL, then NULL is returned. ::::::::::::::: int lib_month_to_value(char *month) lib_month_to_value() performs the reverse of lib_value_to_month(). It takes a string in _month_ representing a valid month (eg. "January" or "Jan") and converts it to its numerical equivalent. The function returns the value of the month in the range 1 to 12 with 1 being "January", 2 being "February", etc. If _month_ is not a valid month then -1 is returned. The function will consider a string with only the first 3 characters of the month as being valid. Only the first 3 letters or the whole name is checked. Case is ignored. ::::::::::::::: char *lib_value_to_dayofwk(int day, char *dayofwk, char shsized) lib_value_to_dayofwk() takes a value in _day_ of the range 1 to 7 and converts it into its string name equivalent. A value of 1 will map to "Sunday" and 7 will map to "Saturday", etc. If _shsized_ is nonzero then the string will be truncated to 3 characters (eg. "Friday" becomes "Fri"). The converted day is stored in _dayofwk_. If successful, the function returns a pointer to _dayofwk_. If _day_ is out of range or _dayofwk_ is NULL, then NULL is returned. ::::::::::::::: int lib_dayofwk_to_value(char *day) lib_dayofwk_to_value() performs the reverse of lib_value_to_dayofwk(). It takes a string in _day_ representing a valid day (eg. "Saturday" or "Sat") and converts it to its numerical equivalent. The function returns the value of the day in the range of 1 to 7 with 1 being "Sunday", 2 being "Monday", etc. If _day_ is not a valid day of the week then -1 is returned. The function will consider a string with only the first 3 characters of the day name as being valid. Only the first 3 letters or the whole name is checked. Case is ignored. ::::::::::::::: long lib_days_from_epoch(int year, int month, int dayofmonth) lib_days_from_epoch() takes a date and calculates the number of days since January 1, 1970 (the Unix Epoch) to that date. _month_ holds the month and must be in the range of 1 to 12. _dayofmonth_ holds the day of the month and must be in the range of 1 to 31 (depending on the month). _year_ must be a value between either 70 and 137 (years since 1900) or 1970 and 2037. The function returns the number of days since the Epoch at that date or -1 if any of the values is out of range. ::::::::::::::: unsigned int lib_seconds2units(unsigned int s, int *w, int *d, int *h, int *m) lib_seconds2units() takes a given number of seconds in _s_ and calculates how many weeks, days, hours, and/or minutes that value represents. If any of the unit paramters (_w_, _d_, _h_, or _m_) are NULL, then that unit will not be tabulated in the total. Once higher units are tabulated, the remaining seconds are used to tabulate lower units. The function returns the number of seconds remaining. For example: If _s_ is 3800, the function will set _w_, _d_ to 0, _h_ to 1, _m_ to 3, and return 20; If _m_ is NULL however, it is ignored and 200 will be returned for remaining seconds (60*3 + 20). ::::::::::::::: char *lib_print_datetime(char *buff) lib_print_datetime() returns the current date and time using the standard ctime(3c) format (eg. 'Thu Jan 26 13:43:12 1999'). If _buff_ is not null, then the the string is also stored int it and _buff_ is returned by the function. Otherwise, an internal buffer is returned. The function is not thread safe if the internal buffer is used. ::::::::::::::: :::::::::::::::Unix Processes Functions::::::::::::::: ::::::::::::::: void lib_die(int exitval, char *diestr, ...) lib_die() prints the string in _diestr_ and terminates the process with the value _exitval_ passed to exit(). _diestr_ uses the same format as printf() but not all formats are recognized (see lib_dsprintf() for more info). A linefeed is added to the end of the string automatically. ::::::::::::::: int lib_exitstat(int pid) lib_exitstat() waits for the exit status from a child that has exited. If the child has not terminated or terminated abnormally, a -1 is returned. The value in _pid_ should be the process ID of a child process. If _pid_ is less than 2, then the function will return on a change of status for any child process it owns, whether terminated or not. The returned value is an unsigned 8 bit value unless an error occurred. For example, if the child exited with a value of -1, then a 255 is returned (two's complement). ::::::::::::::: void lib_do_nothing(int nothing) lib_do_nothing() does absolutely nothing. It can be used especially in signal handlers when an irrelevant signal is received but nothing needs to be done. ::::::::::::::: int lib_timer(int start) lib_timer() acts as a stop watch. If _start_ equals 0, the function returns a starting value. That same value can be passed back to the function again to get the amount of elapsed time since initially called. _start_ is in clock cycles and the function returns centiseconds if _start_ is nonzero. If _start_ is negative, then the absolute value of _start_ is added to the elapsed time (as a function of clock ticks). 1 centisecond equals 0.01 seconds (or 1 jiffy). NOTE: The return value, when _start_ is 0, is a unit of clock ticks. This value may vary from one system to another. However, the function will always return a value in centiseconds if _start_ is nonzero. See sysconf(3) for a means of getting the clock tick value for a system. ::::::::::::::: int lib_checkpid(int pid) lib_checkpid() checks the status of _pid_ to see if it is a valid process ID. If _pid_ exists, but is not owned by the effective UID of the calling process, then a 0 is returned. If _pid_ is owned by the effective UID of the calling process, then a 1 is returned. -1 is returned if _pid_ does not match any existing process ID. NOTE: This function may not work properly for the root user since root has access to information on any process, whether it owns it or not. It can, however, still be used to determine if _pid_ exists or not via the return value. ::::::::::::::: int lib_daemonize(int exitval) lib_daemonize() causes a process to fork and go into the background if on a controlling terminal. If successful, the parent will exit and only the daemonized child will return. Otherwise a -1 is returned to the parent. If successful, the PID of the child is returned by the function and the parent exits with the return value in _exitval_. ::::::::::::::: int lib_read_pidfile(char *path) lib_read_pidfile() reads a PID out of a standard pid file. These files are frequently stored in /var/tmp or /var/run (for system processes). The file's contents are just the PID (stored in text format). Upon success, the function returns the PID. -1 is returned if an error ocurrs. ::::::::::::::: int lib_makepidfile(char *path, int overwr) lib_makepidfile() creates a pid file and writes the current PID of the calling process as the contents of the file. The PID content is terminated by a newline. If _overwr_ is nonzero, then any existing pid file is overwritten. Otherwise, nothing is done and -2 is returned. -1 is returned for all other errors. If successful, the function returns 1. ::::::::::::::: int lib_free(void **ptr) lib_free() takes a pointer to a pointer and and calls free() and the contents. The content of _ptr_ is set to NULL. The function returns 1 if free() was called or 0 if the content of _ptr_ was already NULL. If _ptr_ itself is NULL, then -1 is returned. An example call: char *aptr; aptr=strdup("example"); ... lib_free(&aptr); The content of _aptr_ should now be NULL instead of what was returned by the strdup() call. NOTE: The prototype specifies a void* type to quiet the compiler so that a typecast is not required. ::::::::::::::: int lib_freeall(void *ptr, ...) lib_freeall() is a multivariable version of lib_free(). It takes multiple arguments, each a pointer to an allocated memory block. Once freed, the pointer values are set to NULL. The last argument passed must be the NULL pointer itself. If any variable pointer values are already NULL, they will be ignored. The function returns 0 on completion. ::::::::::::::: :::::::::::::::Math Functions:::::::::::::: ::::::::::::::: double lib_random_float(long mix) lib_random_float() returns a random number in the range of 0 to 1. The seed for the random number is partially generated from the system time clock. If _mix_ is nonzero, then it is XOR'd with the generated seed before the generator is seeded. ::::::::::::::: unsigned char lib_random_byte(long mix) lib_random_byte() generates a random byte in the range of 0 to 255 and returns it. The seed for the random number is generated partially from the system time clock. If _mix_ is nonzero, then it is XOR'd with the generated seed before the generator is seeded. ::::::::::::::: long lib_random_long(long mix) lib_random_log() returns a random 32-bit signed number The seed for the random number is partially generated from the system time clock. If _mix_ is nonzero, then it is XOR'd with the generated seed before the generator is seeded. ::::::::::::::: long lib_pwr(int x, int y) lib_pwr() calculates and returns x^y. If _y_= 0 then 1 is always returned regardless of the value of _x_. If _y_< 0 and/or _x_= 0 then 0 is returned. Be careful of overflow. If x^y is greater than MAXINT, then unknown results can occur. _x_ can be negative. ::::::::::::::: int lib_octaltodec(char *in) lib_octaltodec() takes a string _in_ which contains an octal number (eg. "022") and converts it into decimal. The converted decimal is returned as an integer. If _in_ does not contain a valid octal number or it is greater than five digits, then a -1 is returned. This routine is mainly useful for dealing with file permission modes. ::::::::::::::: int lib_dectoctal(int x) lib_dectoctal() takes a value in _x_ and converts it into a decimal coded octal number and returns it. If _x_ is greater than 32767 or is less than zero then a -1 is returned. This routine is mainly useful for dealing with file permission modes as is lib_octaltodec(). ::::::::::::::: char *lib_delimitint(int val, char *intstr) lib_delimitint() takes an integer value (32 bit assumed) and produces a string containing the number with commas delimiting every three digits. For example: 12345678 produces 12,345,678 _val_ holds the value of the integer. The resultant string is stored in _intstr_. The function returns a pointer to _intstr_. To prevent buffer overflows, _intstr_ should be at least 16 bytes long. NOTE: In some countries, a decimal '.' is used instead of a comma, and commas are used as the radix. This function assumes North America (US/Canada) usage. ::::::::::::::: long lib_round(double x, double *f) lib_round() rounds a value in _x_ to the nearest integer value. If _f_ is not NULL, then the fractional part of x is stored in it. The function returns the rounded value. Since the function returns an integer value, only values of _x_ in the range of 0 to 2147483647 are considered. A -1 is returned if _x_ is out of range. {See also rint(3M)}. ::::::::::::::: int lib_setbit(unsigned int *bits, char which, unsigned char what) lib_setbit() sets or clears a particular bit in _bits_. which is assumed to be 32 bits total. _which_ specifies which bit to set or clear. If _what_ is nonzero then the bit will be set. Otherwise it will be cleared if _what_ is zero. The function returns 1 on success or -1 if _bits_ or _which_ is invalid. NOTE: bit values are numbered 0 to 31. ::::::::::::::: int lib_getbit(unsigned int bits, char which) lib_getbit() retrieves the bit value for a single bit from _bits_. _which_ specifies which bit to check. It's range is 0 to 31. The function returns the value of the bit (0 or 1) or -1 if _which_ is out of range. ::::::::::::::: unsigned int lib_nextpowerof2(unsigned int val) lib_nextpowerof2() returns the next power of 2 greater than or equal to the value stored in _val_. If _val_ was 60 then the function would return 64 (2^6) while if _val_ was 16, then 16 (2^4) would be returned. ::::::::::::::: int lib_prime(unsigned long x) lib_prime() determines whether a number _x_ is prime or not. If it is prime, then 1 is returned. If not, 0 is returned. If _x_ is 0 or negative then -1 is returned. {*} ::::::::::::::: unsigned long lib_nextprime(unsigned long x) lib_nextprime() takes an integer _x_ and returns it if it is prime or it returns the next prime number after _x_ if _x_ is not prime. The function returns -1 if _x_ is less than 1 or if the next prime number is too large to fit in a long integer datatype. {*} ::::::::::::::: :::::::::::::::Hash Functions::::::::::::::: ::::::::::::::: struct hashtable *lib_create_hashtable(int tablesize, char hashfunc) lib_create_hashtable() creates an empty hash table. _tablesize_ specifies how many hash buckets should be in the hash table. Each bucket will be a linked list of entries that hash/map to that bucket. Larger values for _tablesize_ should be used for higher numbers of entries. The function returns a pointer to the hash table struct. If memory cannot be allocated or if _tablesize_ is less than 1 then NULL is returned. The user should never need to access the members of struct hashtable directly. struct hashtable is defined in libmh.h. The memory for the hash table is malloc()'d and should be freed using lib_delete_hashtable() {see below}. All accesses to the hash table should be made through the hash functions {below} to avoid any memory leaks. _hashfunc_ determines which hashing algorithm is used. Currently in 3.1+ there are seven functions. _hashfunc_ can be one of several functions, numbered 1 - 7. If _hashfunc_ is less than 1, then 1 is used; if it is greater than 7, then 7 is used. NOTE: The hash functions hash differently depending on the keys. Function 1 usually hashes better than the others under most circumstances. Your mileage may vary. Different functions may hash certain key sets better than the others. ::::::::::::::: int lib_delete_hashtable(struct hashtable *table) lib_delete_hashtable() deletes all entries in a hash table and frees all the memory used by it. _table_ is a pointer to a hash table previously returned by lib_create_hashtable(). The function returns 1 on success or -1 on failure. NOTE: Memory leaks can occur if the pointer _table_ is reused without first calling this function. ::::::::::::::: int lib_add_hashrecord(struct hashtable *tbl, char *key, void *data, int dsize, int type) lib_add_hashrecord() adds an entry to the hash table _tbl_. _key_ is the unique identifier for the entry and is a string with a length of at least 1 and must be unique. _data_ is a pointer to the data that is to be stored in the hash table and can be NULL. _dsize_ holds the size of the data (in bytes) pointed to by _data_. If _dsize_ is 0 then _data_ will be treated as a pointer and stored directly in the hash entry. Otherwise, _dsize_ bytes are allocated to hold a copy of the data pointed to by _data_. _tbl_ is a pointer to a hash table previously created by lib_create_hashtable(). The function returns 1 if the entry was successfully added. A 0 is returned and the entry is not added if an entry with an identical key already exists in the table. -1 is returned if _tbl_ or _dsize_ is invalid or the memory to hold a copy of the data could not be allocated. _type_ is a user defined value that denotes the type of data being stored. It's value is completely arbitrary and is returned as part of lib_get_hashrecord() {see below}. NOTE: if _data_ is NULL then _dsize_ must equal 0 else -1 is returned. ::::::::::::::: int lib_delete_hashrecord(struct hashtable *table, char *key) lib_delete_hashrecord() deletes an entry in the hash table _table_. _table_ is a pointer to a hash table previously created with lib_create_hashtable(). _key_ is the unique string identifier for the entry to be deleted. The memory that held the deleted entry is freed. The function returns 1 on success or 0 if no entry is found whose key matches _key_. -1 is returned if _table_ is NULL. ::::::::::::::: int lib_get_hashrecord(struct hashtable *tbl, char *key, void **data, int *size, int *type) lib_get_hashrecord() retrieves the data for an entry in the hash table pointed to by _tbl_. _key_ contains the unique string identifier for the entry to be retrieved. The function returns 1 if an item matching _key_ exists in the table or 0 if not. A pointer to the data stored in the hash entry is stored in _data_ if _data_ is not NULL. If _tbl_ is NULL then -1 is returned. If _size_ is not NULL then the size of the data structure in the hash entry will be stored in it. If _type_ is not NULL, then the user defined type value is returned in it. NOTE: This function stores in _data_ a pointer to the actual data stored in the hash table, NOT a copy of it. Any changes made to the data the pointer points to will change the data in the hash table. A local copy of the returned data should be made if the contents of the hash table must be preserved. ::::::::::::::: int lib_edit_hashrecord(struct hashtable *tbl, char *key, void *data, int dsize, int type) lib_edit_hashrecord() replaces an entry already in the hash table _tbl_ with new data. _tbl_ is a pointer to a hash table previously created by lib_create_hashtable(). _key_ is the unique string identifier for the entry. _data_ is a pointer to the new data to be stored in the table. The old entry is removed and its memory freed if not a pointer. _dsize_ holds the size of the new data in bytes. If _dsize_ is zero, then _data_ is treated as a pointer and stored directly in the hash entry . Memory to hold any new data is allocated based on _dsize_. The function returns 1 if successful or 0 if no entry matching _key_ could be found. -1 is returned and the entry is unmodified if _tbl_ or _dsize_ is invalid or the memory to hold the new data could not be allocated. _type_ is a user defined value to denote the type of data pointed to by _data_. It's value is completely arbitrary. NOTE: If _data_ is NULL then _dsize_ must equal 0 or else -1 is returned by the function. ::::::::::::::: int lib_get_hashcount(struct hashtable *table, int *bcoll, int *used, int *bucks, int *alg) lib_gethashcount() returns a count of the number of entries currently stored in _table_. A -1 is returned if _table_ is NULL and not a valid pointer to a hash table previously created by lib_create_hashtable(). If _bcolls_ is not NULL then the number of in bucket collisions is stored in it. If _used_ is not NULL then the number of hash buckets being used is stored in it. If _bucks_ is not NULL, the total number of hash buckets is stored in it. If _alg_ is not NULL then the value of the current hashing algorithm is stored in it. ::::::::::::::: int lib_get_bucketcount(struct hashtable *table, char *key, int *loc) lib_get_bucketcount() Returns the number of items in an existing hash bucket that the key specified by _key_ would map to. _table_ points to a valid hash table. The function returns the number of items found or -1 is there is an invalid parameter. Note that _key_ does not have to exist as an item in the table. If _key_ does exist in the hash bucket and _loc_ is not NULL, then the item position in the bucket chain is stored in _loc_ (0 being the first spot). ::::::::::::::: int lib_get_hashlinear_ptrs(struct hashtable *table, void **first, void **last) lib_get_hashlinear_ptrs() is used to retrieve pointers to the first and last records that were put into a hash table. Those pointers can be used to retrieve records from a hash table in the order (or reversed order) that they were put into the table using lib_get_hashlinear_rec() {see below}. _table_ is a pointer to a hash table previously created with lib_create_hashtable(). _first_ and _last_ are pointers to pointers that will hold pointers to the first and last entries in the hash table. The function returns 1 if successful, 0 if the table is empty, or -1 is _table_ is not valid. If _first_ or _last_ is NULL, then that parameter is ignored. ::::::::::::::: void *lib_get_hashlinear_rec(void *which, void **prev, void **next, int *dsize, char **key, int *type) lib_get_hashlinear_rec() returns a pointer to the data in the hash table entry pointed to by _which_. The size of the data is stored in the location pointed to by _dsize_. _dsize_ is ignored if it is NULL. _prev_ and _next_ are pointers to pointers in which pointers to the previous and next hash table entries are stored. If _prev_ or _next_ is NULL then that parameter is ignored. A copy of the key for the record will be stored in _key_ if it is not NULL. Memory to hold the copy is malloc()'d and should be free()'d when no longer needed to avoid memory leaks. If memory could not be allocated for _key_ then it will point to NULL. If _type_ is not NULL, then the user defined type is return in it. The function returns NULL if any other error occurs or the hash entry contains no stored data. ::::::::::::::: struct hashtable *lib_rehashtable(struct hashtable *table, int tablesize, char hashfunc) lib_rehashtable() takes an existing hash table and rehashes it into a new hash table. _table_ is a pointer to an existing hash table previously created with lib_create_hashtable(). _tablesize_ is the number of hash buckets the new table will have. If _tablesize_ is 0, then the hash size of _table_ is used by default. NULL is returned if _tablesize_ is negative. The function returns a pointer to the new hash table if successful. Otherwise it returns NULL if _table_ is invalid or memory to hold the new table could not be allocated. _hashfunc_ sets which hashing algorithm is used (see lib_create_hashtable). The only difference between it and the one passed to lib_create_hashtable() is if _hashfunc_ is 0, then the same hashing algorithm from _table_ is used in the new table, rather than defaulting to 1. This function is useful if an existing hash table is too full or too empty and a new one with more a appropriate hash size or hash function needs to created. ::::::::::::::: int lib_reposition_item(struct hashtable *table, char *key, int pos) lib_reposition_item() takes an item in a hash table pointed to by _table_ and repositions it at the beginning of a bucket chain or at the end. _key_ is the unique identifier that points to the item. if _pos_ is negative, then the item is placed at the end of the bucket chain. Else if non-negative, then it is placed at the beginning. The latter can improve lookup times if an item is referenced frequently and the hash bucket has many items in it. Function returns 1 if successful, 0 if item pointed to by _key_ is not found, or -1 if an parameters are invalid. ::::::::::::::: int lib_rekey_hashitem(struct hashtable *table, char *key, char *newkey) lib_rekey_hashitem() changes the key for an item in a hash table without the item being removed and re-added. _table_ points to a valid hash table. _key_ points to an existing item in the hash table. _newkey_ is the replacement key. The function returns 1 if successful or -1 if _table_ is invalid, _key_ does not exist, or _newkey_ already exists in the hash table. ::::::::::::::: int lib_move_hashrecord(struct hashtable *src, struct hashtable *dst, char *key) lib_move_hashrecord() transfers a hashtable item referenced by the key pointed to in _key_ from hashtable _src_ to another hashtable _dst_. If _key_ already exists in _dst_ then 0 is returned and nothing done. If successful, the function returns 1. -1 is returned if any errors occur. Any pointers to the data stored in the hashtable is preserved across the move. ::::::::::::::: int lib_freeall_hashtable(struct hashtable *ht, ...) lib_freeall_hashtable() takes multiple pointers to hashtables and completely frees the memory up for each one as if each was deleted via lib_delete_hashtable(). If any pointers point to NULL then they are ignored. The last argument must be the NULL pointer itself. After successful completion, each pointer will be pointing to NULL. The function does not verify that each pointer points to a valid hashtable beyond simply checking for a NULL pointer. The function returns 0 on success or -1 if an error occurred. ::::::::::::::: int lib_dlist2hashtable(struct hashtable *table, struct dlist_type *dlist) lib_dlist2hashtable() takes items in a dynamic list, _dlist_, and stores them as keys in a hash table pointed to by _table_. Duplicate items in _dlist_ are ignored. A NULL pointer is used as the data for each hash key. The function returns the number of items in the hash table, or -1 if an error ocurred. The hash table is not cleared beforehand. The contents of _dlist_ are unchanged. ::::::::::::::: :::::::::::::::Screen Functions::::::::::::::: ::::::::::::::: void lib_sclear(int out) void lib_shome(int out) lib_sclear() clears the terminal screen and sets the cursor in the top left. lib_shome() places the cursor in the top left but does not clear the screen. _out_ specifies a file descriptor to use as STDOUT or -1 to use the default. Note: These functions may not work properly on all terminal types. Currently, xterm, vt100, and vt102 appear to work correctly. ::::::::::::::: void lib_screen_reset(int out) lib_screen_reset() attempts to restore a screen/terminal to sane settings including text mode. It clears the screen afterwards. It should work for terminals emulating vt100, vt102, or xterm (and possibly others) using UNIX style TTYs. _out_ specifies a file descriptor to use as STDOUT or -1 to use the default. ::::::::::::::: void lib_beep(int out) lib_beep() makes a beep sound (ASCII 7) when called assuming the terminal type supports it. _out_ specifies a file descriptor to use as STDOUT or -1 to use the default STDOUT. ::::::::::::::: :::::::::::::::Dynamic List Functions::::::::::::::: ::::::::::::::: struct dlist_type* lib_create_dlist(int size) lib_create_dlist() dynamically allocates memory for a new dynamic list struct and returns a pointer to it. _size_ inidicates the initial number of items to be allocated for and should serve as a best guess hint. Upon completion, the entire dynamic list is initialized and ready for use. If no memory is available or _size_ is invalid, then NULL is returned. When the dynamic list is no longer needed, it should be freed with a call to lib_destroy_dlist() {see below}. The definition of struct dlist_type is: struct dlist_type { int size; --> number of items currently in the list int maxlistsize; --> maximum number of items the list can hold char **item; --> pointer to an array of pointers to list items }; The function allocates memory for _dlist_->item[] based on _size_. _dlist_->size is initialized to 0 and _dlist_->maxlistsize is set to _size_. _dlist_->maxlistsize only specifies the maximum number of item positions currently allocated. It is not fixed as more space will be allocated if the number of items exceeds the current value. To free just the items on the list, use lib_clear_dlist() {see below}. ::::::::::::::: int lib_destroy_dlist(struct dlist_type *dl) lib_destroy_dlist() destroys and frees all of the contents of a dynamic list previously created with lib_create_dlist(). All of the items in the dynamic list are freed as are the memory allocations for the list structures themselves. If successful, 1 is returned. If this dynamic list was not created by lib_create_dlist() or is invalid then a -1 is returned. ::::::::::::::: int lib_clear_dlist(struct dlist_type *dlist) lib_clear_dlist() clears all the items from a dynamic list. The memory for the items in the list are freed. The function returns 1 on success or -1 on an error. The function must be called before the list can be reused otherwise new elements will be added to the existing items. NOTE: If _dlist_->size is ever set to 0 directly then a memory leak can be created. Both lib_clear_dlist() and lib_destroy_dlist() used that struct member to free up items in the list. Care should be taken when using members of struct dlist_type directly without going through a dynamic list function. Also, this function only clears the individual list items, not the dlist_type structure members themselves (see lib_free_dlist() below). If _dlist_ is not intended to be used again, then lib_destroy_dlist() should be used to free its used memory. ::::::::::::::: int lib_dsplit(char *string, struct dlist_type *list, char *separator) lib_dsplit() strictly parses through an input string and separates out items separated by the string _separator_. The parsed items are stored in the dynamic list structure _list_. The function is exactly like lib_split() except that it uses a dynamic list _list_ of type struct dlist_type instead of struct list_type. The number of items is NOT limited by the size passed to lib_create_dlist() as more space will be allocated if needed. The function returns the number of items in the dynamic list. See also lib_split(). ::::::::::::::: char *lib_dfsplit(char *s, struct dlist_type *i, char *start, char *end, char inc) lib_dfsplit() is exactly like lib_fsplit() except that it uses a dynamic list _i_ of type struct dlist_type instead of struct list_type. The function appends to the list _i_, the first occurance of a string in _s_ that begins with _start_ and ends with _end_. The isolated string is placed at the end of the list stored in _i_. The function returns a pointer to the first position beyond the ending separator. NULL is returned if _start_ does not appear in the string or if _i_ is full. If _end_ is not found, then the end of the string is used instead and a pointer to the terminating nul is returned. The parameter _inc_ determines if the separator is to be included in the parsed output. if _inc_ is zero, then the separators will not be included in the list items parsed out. If _inc_ is nonzero, separators will be included. If _start_ is of zero length then the starting separator is assumed to have already been encountered. That is, the first character of _s_ will automatically be the first character of the isolated string. If _end_ is of zero length, then the entire remainder of the string is included. See also lib_fsplit(). ::::::::::::::: char *lib_dlist_join(char *string, struct dlist_type *i, char *separator) lib_dlist_join() is exactly like lib_join() except that it uses a dynamic list _i_ of type struct dlist_type instead of a static list of fixed size. The function takes a list of items and joins them all together into a single combined string with a separator between each item. Items to be joined together are taken from _i_ and each is separated by the string in _separator_. The result is stored in _string_ (if _string_ is not NULL). The function returns a pointer to the combined string. If _string_ is NULL, then space is dynamically allocated to hold the result and must be later freed when no longer needed by calling free() to avoid memory leaks. A pointer to the dynamically allocated string is then returned in that case by the function. NOTE: if _string_ is not NULL, no overflow checking is done to make sure that the result is larger than what _string_ can hold. See also lib_join(). ::::::::::::::: int lib_dparse(char *string, struct dlist_type *list, char *seps, char strict) lib_dparse() is exactly like lib_parse() except that parsed items are stored in a dynamic list pointed to by _list_. The function parses through a string, _string_, and pulls out items separated by ANY character in _seps_. If _strict_ is 0, then multiple consecutive instances of a separator are ignored. Otherwise consecutive separators are assumed to separate empty strings. If the length of _seps_ is zero, then white space is assumed. White spaces are either tabs, spaces, carriage returns, or newlines. The function returns the number of items in the list. See also lib_parse(). ::::::::::::::: int lib_nuparse(char *string, char *format, struct dlist_type *dlist, char *m) lib_nuparse() is a more powerful variant of lib_dfsplit() that can combine all parsing processing into a single call verses multiple successive calls. _string_ contains a line of data to be parsed. _dlist_ is the dynamic list that will store the parsed contents. _format_ contains the parsing retreival pattern that will be used. _m_ contains the two match character elements for identifying matches within _format_. If _m_ is empty or NULL then the two default characters, '*' and '?' are used ("*?"). The first character ('*') specifies a match to be added to _dlist_. The second character ('?') specifies a match that will not be included, but is required to fit the formatting. The format string specifies the general layout of the input string. As an example, the Apache log line: 66.167.193.143 - - [09/Aug/2005:16:33:13 -0400] "GET /webct/public/home.pl HTTP/1.1" 200 5707 0 can be parsed with the following format string: "* ? ? [*] \"*\" * * *" The resulting _dlist_ will contain: 66.167.193.143 09/Aug/2005:16:33:13 -0400 GET /webct/public/home.pl HTTP/1.1 200 5707 0 the two '?' characters cause the matching '-'s to be excluded. Static characters should be included in the format field. Any spurious data in the input string not matching the format will be ignored. However, the entire pattern itself must be found within _string_ or else nothing is added to the dynamic list. The function returns the number of entries in _dlist_ or -1 if an error occurs. Both characters in _m_ must be different and cannot be whitespace. Mulitple white spaces in the input string are ignored. Muliple back-to-back match characters or white spaces in the format string will result in an error. ::::::::::::::: int lib_dlist_replace(struct dlist_type *dlist, int which, char *new) lib_dlist_replace() replaces an item in a dynamic list _dlist_ with a new entry. The memory for the old entry is freed and memory for the new is allocated. _dlist_ is a pointer to a dynamic list initialized by lib_create_dlist(). _which_ specifies which item in the list is to be replaced. _new_ is a pointer to a string containing the new data. The function returns the number of items in the list if successful or -1 on error. Errors can occur if memory could not be allocated to hold a copy of data pointed to by _new_ or if _which_ is invalid. ::::::::::::::: int lib_dlist_add(struct dlist_type *dlist, char *new) lib_dlist_add() adds a new item to the end of a dynamic list. _dlist_ is a pointer that points to a dynamic list initialized by lib_create_dlist(). _new_ is a pointer that points to a string to be added to the list. Memory is allocated to hold a copy of the data pointed to by _new_. The function returns the number of items in the list if successful or -1 on an error. ::::::::::::::: int lib_dlist_delete(struct dlist_type *i, int which) lib_dlist_delete() deletes an item from a dynamic list pointed to by _i_. _which_ specifies which item is to be deleted. All items after the one that is deleted are moved up one position to fill up the space. The fuction returns the number of items still in the list or -1 if an error occurred. ::::::::::::::: int lib_dlist_insert(struct dlist_type *i, char *what, int where) lib_dlist_insert() inserts an item into a list at an arbitrary position. _i_ is a pointer to a dynamic list. _where_ is the position in the list that the new string is to be stored. _what_ is a pointer to the new string. Any item at that location and after it, is moved back one position in the list. The function returns the number of items in the list if successful or -1 if an error occurred. ::::::::::::::: int lib_dlist_getdir(struct dlist_type *dl, char *dir, char dotflag) lib_dlist_getdir() retrieves a listing of entries in a specified directory. The entries are stored in a dynamic list structure pointed to by _dl_. _dir_ specifies which directory to get the file list from. If it is of zero length, then the current directory is assumed. If _dotflag_ is 1, then "hidden" files beginning with '.' are also retrieved except '.' and '..'. If _dotflag_ is 2 then "." and ".." are included as well. Otherwise if _dotflag_ is zero, then only files NOT beginning with '.' are listed. The function returns -1 if any errors occur or if any parameters are invalid. If successful, the number of items on the list is returned. NOTE: _dl_ is NOT cleared beforehand. File listings are appended to any contents already in _dl_. Use lib_clear_dlist() to empty the dynamic list before calling this function. ::::::::::::::: int lib_dlist_sort(struct dlist_type *dl, char ignorecase) lib_dlist_sort() sorts the contents of a dynamic list pointed to by _dl_ in alphabetical (ASCII) order. If _ignorecase_ is FALSE (zero), then the list will be alphabetized according to ASCII values alone (eg. 'A' is < 'a'). Otherwise, if _ignorecase_ is TRUE (nonzero), then the case of alphabetic characters will be ignored (eg. 'A' = 'a'). The function returns -1 if _dl_ is invalid. If _dl_ was already in sorted order, then 0 is returned. Otherwise, if some sorting had to be done, 1 is returned. NOTE: when case is ignored, the order of "identical" strings is undefined (aka "Alf" may appear just before OR just after "alf"). ::::::::::::::: int lib_dlist_qsort(struct dlist_type *dl, char ignorecase) lib_dlist_qsort() is like lib_dlist_sort() except that it uses the internal qsort() function available in the C library. {See lib_dlist_sort() above}. Under most circumstances this function is several orders of magnitude faster than lib_dlist_sort(). Under worst case scenarios it may be somewhat slower, but probably not significantly. ::::::::::::::: int lib_dlist_exec(struct dlist_type *dl) lib_dlist_exec() passes the items on a dynamic list and passes them to exec() as arguments. The first item in the list should contain the path to an external program to be executed. The second item should be the name of that program. All following items are treated as arguments to be passed to the program. If an error occurs, then -1 is returned. Otherwise, the function does not return as execution is passed to a new process image. ::::::::::::::: int lib_getdlistcount(struct dlist_type *dl) lib_getdlistcount() returns the number of items currently in a dynamic list. If _dl_ is NULL then -1 is returned. ::::::::::::::: int lib_getdlistsize(struct dlist_type *dl) lib_getdlistsize() returns the maximum number of characters the dynamic list items cummulatively contain. The terminating nul characters are not included in the tabulation. If _dl_ is NULL, then -1 is returned. ::::::::::::::: int lib_dlist_blkdelete(struct dlist_type *dl, int which, int quant, char how) lib_dlistdeletes() deletes _quant_ entries before and/or after a specified entry in a dlist _dl_. The paramber _which_ specifies which list entry is the starting entry. If _how_ is negative, then _quant_ entries before _which_ are deleted. If _how_ is positive, then _quant_ entries after _which_ are deleted. If _how_ is zero, then _quant_ entries before and after _which_ are deleted. The dynamic list is adjusted to fill in the vacated space. The function returns the number of entries deleted or -1 if an error occured or any parameters are invalid. ::::::::::::::: int lib_dlist_from_hashkeys(struct hashtable *table, struct dlist_type *dlist) lib_dlist_from_hashkeys() takes all of the keys from a hash table in order of addition and puts them on a given dynamic list. _table_ is a pointer to a hash table. _dlist_ is a pointer to an existing dynamic list struct. The key values are duplicated via malloc() and added to the items in _dlist_. This uses more memory than just copying the pointer straight out of the hash table struct itself but is MUCH safer as any manimpuations of _dlist_ will not affect the integrity of the structure of the hash table in _table_. The function returns the number of items in the dynamic list (including any items previously in it). -1 is returned on error (invalid parameters or out of memory). The data in in _table_ is not affected or modified by this function. ::::::::::::::: int lib_dlist_swap(struct dlist_type *dlist, int first, int second) lib_dlist_swap() swaps two items in a dlist pointed to by _dlist_. _first_ and _second_ specify which items are to be swapped (NOTE: items are numbered like in an array - starting with 0 as the first item instead of 1). If any parameters are invalid or out of range, then -1 is returned. The function returns 0 on success. ::::::::::::::: int lib_dlist_reverse(struct dlist_type *dlist) lib_dlist_reverse() reverses the order of the items in a dynamic list pointed to by _dlist_. The function returns 0 upon completion or -1 if an error occurred. ::::::::::::::: int lib_dlist_cgiparse(struct dlist_type *dlist, char *input) lib_dlist_cgiparse() parses an input string passed on STDIN from to a CGI calling program using the GET method. Items are seperated by =,& pairs. '+' characters are converted to spaces. % denoted ASCII values are NOT converted to their equivalents, however. lib_stringhex_conv() can be used to do that if desired. The function returns the number of items on the dynamic list if successful or -1 if an error occurred. The dynamic list should be cleared with lib_clear_dlist() before being called, otherwise the items will be appended. After processing, the key items should be in even numbered slots, and the associated values should be in odd numbered slots following the their respective keys. For example: dlist->item[0]=key1 dlist->item[1]=value1 dlist->item[2]=key2 dlist->item[3]=value2 ... If an error occurs during processing, some key/value pairs may be present in the dynamic list as they were already processed. ::::::::::::::: int lib_grep_dlist(struct dlist_type *src,struct dlist_type *res, char *pat, short flags) lib_grep_dlist() searches through the items on a dynamic list in _src_ searching for strings containing or matching the pattern string in _pat_. The matches, if any, are stored in _res_. The _flags_ flags specify whether to ignore case or not and whether to exclude or exclude matches. The first bit indicates whether to match by case or not. If it is 0 then matching is case sensitive. A 1 value causes case to be ignored. Case insensitive searches are slower than a case sensitive search. The second bit specifies whether to include matches or exclude matches (same as -v flag to grep) in the results. A 0 value specifies to include only matching items in the results. A 1 value (2 bitwise) specifies to put only nonmatching items in the results. The bit values for _flags_ should be OR'd together. Currently valid values: 0 - case sensitive + include only matching items 1 - case insensitive + include only matching items 2 - case sensitive + include only non-matching items 3 - case insensitive + include only non-matching items If any parameters are invalid or an error occurs then -1 is returned. If successful, the function returns the number of items in _res_. Previous contents of _res_ are not disturbed, so a call to lib_clear_dlist() should be made to empty it beforehand if it is not empty. ::::::::::::::: int lib_egrep_dlist(struct dlist_type *src, struct dlist_type *res, char *pat, short flags, char *expr) lib_egrep_dlist() is a more powerful version of lib_grep_dlist(). The parameters are the same except for the addition of a _expr_ parameter. _expr_ specifes how to handle the matching positionwise within the string. It can contain the following characters: '*' = something not containing the pattern '$' = the pattern in its entirety The following are all of the valid combinations: '*' = matches anything not containing pattern '$' = matches pattern exactly '$*' = matches strings beginning with pattern, but not exactly the pattern '*$' = matches strings ending with pattern, but not exactly pattern '*$*' = matches strings not beginning or ending with pattern but contains the pattern within it Note that the first _expr_ string above, '*', is inversely identical to the functionality of lib_grep_dlist(). (The exclude bit of _flags_ must be set to the opposite of what is would be with lib_grep_dlist() to effectively produce the same functionality.). See lib_grep_dlist() above for details on the rest of the parameters and their meanings as well as the return values. ::::::::::::::: int lib_dlist_sorted_uniq(struct dlist_type *dlist, char igncase) lib_dlist_sorted_uniq() searches through a list of dynamic list items and deletes duplicated items. _dlist_ is a pointer to a dynamic list struct. If _igncase_ is 0 then duplicates are matched exactly. If _igncase_ is nonzero, then case is ignored when matching (slower). The function assumes that the list is sorted, in which case, matching items will be neighbors. If it is not sorted, then some duplicate items could be missed. The function returns the number of items deleted or -1 if an error occurs. ::::::::::::::: int lib_dlist_uniq(struct dlist_type *dlist, char igncase) lib_dlist_uniq() searches through a list of dynamic list items and deletes duplicated items. _dlist_ is a pointer to a dynamic list struct. If _igncase_ is 0 then duplicates are matched exactly. If _igncase_ is nonzero, then case is ignored when matching (slower). Unlike lib_dlist_sorted_uniq(), this function can work with unsorted lists. As a result, however, lib_dlist_uniq() can be much slower since it must search the entire list for duplicates rather than just adjoining items. The function returns the number of items deleted or -1 if an error occurs. See also lib_dlist_sort() for sorting options. ::::::::::::::: int lib_dlist_compare(struct dlist_type *list1, struct dlist_type *list2, char igncase, char sorted) lib_dlist_compare() compares two dynamic lists pointed to by _list1_ and _list2_. If they are the same, then 0 is returned. If inequalities exist, then 1 is returned. If an error occurs then -1 is returned. If _igncase_ is 0, then the comparing of items is case sensitive. If _sorted_ is nonzero, then the two lists are treated as if they are sorted. Otherwise, the order of the lists is not important, only that they have the same elements. NOTE: For an accurate comparison, either all items in both lists must be unique, or all items in both lists must be sorted. Otherwise, differences between the two lists will not be accurately detected. ::::::::::::::: int lib_dlist_append(struct dlist_type *L1, struct dlist_type *L2, char copy) lib_dlist_append() appends the contents of dynamic list _L2_ to the end of _L2_. If _copy_ is nonzero, then a copy of the contents of _L2_ is placed into _L1_. Otherwise, if _copy_ is 0, then the actual items of _L2_ are moved to _L1_ and _L2_ will be empty afterwards. If there is insufficient memory to complete the operation, then -2 is returned. If _L2_ or _L1_ is invalid, then -1 is returned. Upon success, the number of items in _L1_ is returned. ::::::::::::::: int lib_dlist_merge(struct dlist_type *L1, struct dlist_type *L2, char icase) lib_dlist_merge() takes the contents of _L2_ and merges it into _L1_. The function assumes both dynamic lists are in sorted order. If nonsorted, then the order will be undefined. Upon success, _L2_ will be empty. If _icase_ is 0, then comparisons will be case sensitive, otherwise, if nonzero, case will be ignored. The function returns -2 if there is no memory available or -1 if _L1_ or _L2_ are invalid. Upon success, the number of items in _L1_ is returned. ::::::::::::::: int lib_dlist_copy(struct dlist_type *list1, struct dlist_type *list2) lib_dlist_copy() copies the contents of _list1_ to _list2_. The provious contents of _list2_ are freed. If there is insufficient memory for the operation, then _list2_ is unchanged and -2 is returned. If _list1_ or _list2_ are invalid, then -1 is returned. Otherwise, on success, the number of items on _list2_ is returned. ::::::::::::::: int lib_freeall_dlist(struct dlist_type **ptr, ...) lib_freeall_dlist() takes multiple arguments of dlist_type pointers and frees them (essentially calling lib_destroy_dlist() on them). All memory associated with the dynamic list structure is freed and the pointer is set to NULL. If a parameter has a NULL value, then it is ignored. The parameter list is terminated with a NULL pointer itself being passed (rather than a pointer to a NULL value). The function does not verify that the pointer contents are valid dynamic list returned by lib_create_dlist() beyond simple NULL value checking. The function returns 0 on success or -1 if an error occurred. ::::::::::::::: int lib_dlist_readtxtfile(struct dlist_type *dl, char *path) lib_dlist_readtxtfile() opens a file designated by _path_ and reads its contents into a dynamic list as a text file. The dynamic list is pointed to by _dl_. The function returns the number of lines read in or -1 if an error occurs. If the file is not a text file, the results are uncertain. NOTE: the function assumes lines are terminated by a newline. The function does not clear _dl_ beforehand. ::::::::::::::: :::::::::::::::QStack Functions::::::::::::::: ::::::::::::::: struct qstack *lib_create_qstack(void) lib_create_qstack() creates an empty Qstack. A pointer to the new Qstack is returned by the function. NULL is returned if an error occurs. The definition of struct qstack is as follows: struct qstack { void *first; *first data item in the queue* void *last; *last data item in the queue* int size; *number of data items in Qstack* int bsize; *number of bytes allocated for all data items* }; _first_ points to the first item in the queue. _first_ is the "bottom" of the stack. The funtions lib_qstack_pull() and lib_qstack_press() {see below} affect _first_. _last_ points to the last item in the queue or the top of the stack (the last item "pushed" onto the stack). lib_qstack_push() and lib_qstack_pop() manipulate _last_. Both _first_ and _last_ point to linklist_item structs. _size_ holds the count of items currently in the queue or stack. ::::::::::::::: int lib_delete_qstack(struct qstack *qstak) lib_delete_qstack() destroys a Qstack including all items in it. _qstak_ is a pointer to a valid Qstack. The function returns 1 on success or -1 if an error occurs. ::::::::::::::: int lib_clear_qstack(struct qstack *qstak) lib_clear_qstack() deletes all of the items on a Qstack but doesn't destroy the Qstack. It returns 1 on success or -1 if _qstak_ is NULL. ::::::::::::::: int lib_qstack_push(struct qstack *qstak, void *data, int datasize, int type) lib_qstack_push() inserts an item into a Qstack at the rear of the Qstack (or the "top" of the Qstack LIFO). _qstak_ is a pointer to a Qstack. _data_ is a pointer to the data to be inserted. _datasize_ holds the size of the data to be added. A copy of the data is made and placed on the Qstack. _type_ is an arbitrary user defined value that is added along with _data_. The function returns 1 on success or -1 if an error occurred. NOTE: if the maximum number of items on the Qstack has been exceeded, then an item at the opposite end of the Qstack is automatically removed {see lib_qstack_setmaxsize()}. ::::::::::::::: int lib_qstack_press(struct qstack *qstak, void *data, int datasize, int type) lib_qstack_press() inserts an item at the front of a Qstack (or the "bottom" of the Qstack LIFO). _qstak_ is a pointer to a Qstack. _data_ is a pointer to the data to be inserted. _datasize_ holds the size of the data to be added. A copy of the data is made and placed on the Qstack. _type_ is an arbitrary user defined value that is added with _data_. The function returns 1 on success or -1 if an error occurred. NOTE: if the maximum number of items on the Qstack has been exceeded, then an item at the opposite end of the Qstack is automatically removed {see lib_qstack_setmaxsize()}. ::::::::::::::: void *lib_qstack_pop(struct qstack *qstak, int *dsize, int *type) void *lib_qstack_vpop(struct qstack *qstak, int *dsize, int *type) lib_qstack_pop() retrieves an item from the rear of a Qstack (or the "top" of the Qstack LIFO) and removes it from the Qstack. The size of the data retrieved is stored in _dsize_. _qstak_ is a pointer to a valid Qstack. The function returns a pointer to the retrieved data or NULL if it is empty or an error occurred. If _dsize_ is NULL, then it is ignored. If _type_ is not NULL, then the user defined value included with the _data_ is stored in it. NOTE: the data returned by lib_qstack_pop() was malloc()'ed and should be free()'d when no longer needed to avoid memory leaks. This does NOT apply to lib_qstack_vpop(). lib_qstack_vpop() is the same as lib_qstack_pop() except that the data returned is NOT removed from the Qstack and will be again returned on the next call to lib_qstack_pop() or lib_qstack_vpop(). ::::::::::::::: void *lib_qstack_pull(struct qstack *qstak, int *dsize, int *type) void *lib_qstack_vpull(struct qstack *qstak, int *dsize, int *type) lib_qstack_pull() retrieves an item from the front of a Qstack (or the "bottom" of the Qstack LIFO) and removes it from the Qstack. The size of the data retrieved is stored in _dsize_. _qstak_ is a pointer to a valid Qstack. The function returns a pointer to the retrieved data or NULL if it is empty or an error occurred. If _dsize_ is NULL, then it is ignored. If _type_ is not NULL, then the user defined value included with the _data_ is stored in it. NOTE: the data returned by the function was malloc()'ed and should be free()'d when no longer needed to avoid memory leaks. This does NOT apply to lib_qstack_vpull(). lib_qstack_vpull() is the same as lib_qstack_pull() except that the data returned is NOT removed from the Qstack and will be again returned on the next call to lib_qstack_pull() or lib_qstack_vpull(). ::::::::::::::: int lib_qstack_pointers(struct qstack *qstak, void **first, void **last) lib_qstack_pointers() retrieves pointer information associated with a Qstack. _qstak_ is a pointer to a Qstack previously created with lib_create_qstack(). A pointer to the first item in the Qstack is stored in _first_. A pointer to the last item in the Qstack is stored in _last_. The function returns 1 on success or -1 if _qstak_ is NULL. If _first_ or _last_ is NULL, then it will be ignored. All of the data in the Qstack can also be retrieved using the fields in the qstack struct {see lib_create_qstack()}. ::::::::::::::: void *lib_qstack_getlistptrs(void *item, void **prev, void **next, int *dsize, int *type) lib_qstack_getlistptrs() retrieves information associated with an item in the Qstack. _item_ is a pointer to an item on the Qstack. It is usually a pointer to a struct linklist_item {see below}. _prev_ is a pointer in which a pointer to the previous item in the Qstack is stored. The previous item is closer to the "bottom" of the Qstack (or front of the Qstack). _next_ is a pointer in which a pointer to the next item in the Qstack is stored. The next item is closer to the "top" of the Qstack (or end of the Qstack). Both the next and previous items are relative to the item pointed to by _item_. The size of the data portion in _item_ is stored in _dsize_. A pointer to the data portion of _item_ is returned by the function. The definition of the struct _item_ points to is: struct linklist_item { void *prev; *data to be stored in _prev_* void *next; *data to be stored in _next_* void *data; *data to be returned by the function* int dsize; *size of data referenced by _data_* }; If _item_ is the "first" item in the Qstack then NULL is stored in _prev_. If _item_ is the "last" item in the Qstack, then NULL is stored in _next_. If _prev_, _next_, or _dsize_ is NULL, then it will be ignored. The data returned by the function is a pointer to the actual data stored in the item, so care should be exercised if changes are made to it. If _type_ is not NULL, then the user defined value included with the _data_ is stored in it. If _item_ is NULL then the function returns NULL, and no changes to the other parameters are made. ::::::::::::::: int lib_qstack_insert(struct qstack *qstak, void *item, char how, void *data, int dsize, int type) lib_qstack_insert() inserts an item into a Qstack. _qstak_ is a pointer to a Qstack. _item_ is an item that already exists in the Qstack. _data_ is the new data to be inserted into the Qstack. _how_ determines where _data_ will be inserted with respect to _item_. If _how_ is less than 0, then the data will be inserted just after _item_, closer to the "top" of the Qstack. If _how_ is greater than 0, then it will be inserted just before _item_, closer to the "bottom" of the Qstack. If _how_ is 0, then it will replace _item_. _type_ defines an arbitrary user defined value inserted with _item_. The function returns 1 on success or -1 if an error occurs. NOTE: this function ignores the max item size limit {see lib_qstack_setmaxsize()}. ::::::::::::::: int lib_qstack_remove(struct qstack *qstak, void *item) lib_qstack_remove() removes an item from the Qstack. _qstak_ is a pointer to a Qstack. _item_ is a pointer to an item in the Qstack that is to be deleted. The function returns 1 on success or -1 if an error occurs. ::::::::::::::: int lib_qstack_size(struct qstack *qstak, int *bytes) lib_qstat_size() returns the number of entries in _qstak_ or -1 if _qstak_ is NULL. If _bytes_ is not NULL, then the total number of bytes allocated for data items on the Qstack is stored in it. Otherwise, _bytes_ is ignored. ::::::::::::::: int lib_qstack_setmaxsize(struct qstack *qstak, int size) lib_qstack_setmaxsize() alters the maximum number of items a QStack can hold (normally MAXINT). The call itself does not alter the contents of the Qstack, but will affect subsequent calls to lib_qstack_push() and lib_qstack_press(). If the maximum item count has been exceeded, any calls to the above two functions will cause the item at the opposite end of the Qstack to be removed. _qstak_ is a pointer to a valid Qstack struct. _size_ specifies the maximum number of items the Qstack will be allowed to have. If _size_ is 0, then it will be set to the maximum (usually MAXINT). The function returns the maximum number of the Qstack will hold or -1 if an error occurs. If _size_ is negative, then only the max size is returned and nothing is changed. ::::::::::::::: void *lib_qstack_returnitem(struct qstack *qstak, int which, int *size, int *type) lib_qstack_returnitem() returns a pointer to a specific item on a Qstack. The firt item on the Qstack is at the bottom of the stack (or front of the queue). The first item is equivalent to what would be returned by lib_qstack_pull(). _qstak_ is a valid pointer to a Qstack struct. _which_ specifies which item to be returned from the Qstack (without removing it). If _qstak_ is invalid or _which_ is greater than the number of items on the Qstack, then NULL is returned. If _type_ is not NULL, then the user defined value included with the returned data is stored in it. If not NULL, _size_ will hold the data size of the returned item. As an example: ptr = lib_qstack_returnitem(qstak,lib_qstack_size(qstak)-1,&size) will return a pointer to the last item in the Qstack (same item lib_qstack_pop() would return). Unlike lib_qstack_pop() and lib_qstack_pull(), the items are NOT removed from the Qstack. NOTE: as with an array, the first item is numbered as 0 instead of 1. ::::::::::::::: int lib_freeall_qstack(struct qstack **ptr,...) lib_freeall_qstack() takes multiple pointers to Qstacks and completely frees the memory up for each one as if each was deleted via lib_delete_qstack(). If any pointers point to NULL then they are ignored. The last argument must be the NULL pointer itself. After successful completion, each pointer will be pointing to NULL. The function does not verify that each pointer points to a valid Qstack beyond simply checking for a NULL pointer. The function returns 0 on success or -1 if an error occurred. ::::::::::::::: :::::::::::::::Encoding Functions::::::::::::::: ::::::::::::::: char *lib_encode(char *key, char *data, int dsize, int *esize, short cycles) lib_encode() takes a data string of length _dsize_ stored in _data_ and encodes it with a key generated from the string _key_. The resulting encoded string is stored in raw binary format. The function returns a pointer to the encoded string. If _esize_ is not NULL, then the length of the encoded string is stored in it. _cycles_ determines how many iterations of the algorithm are executed. The function returns NULL if _key_ is NULL or is of zero length, if _data_ is NULL, if _dsize_ is less than one (or greater than 255), or if there is insufficient memory available. If _cycles_ is less than 1, then it defaults to 1. Larger values for _cycles_ slow the encoding process down but may improve encoding. Longer keys are also generally more secure. NOTE: Memory to hold the encoded string is allocated and should be free'd when no longer needed in order to avoid memory leaks. Also, this routine employs a combination of several somewhat weak encryption methods. The resulting combination appears to be fairly effective (in the author's un-educated opinion). While this is probably sufficient for general security, it probably is not secure enough for really sensitive data. In such cases, a more extensive encryption routine should be used. The routine is also not very fast. For security reasons, the block size, _dsize_, cannot be larger than 256. ::::::::::::::: char *lib_decode(char *key, char *estring, int esize, int *dsize, short cycles) lib_decode() decodes a string previously encoded with lib_encode(). _key_ is the same string passed to lib_encode() that was used to encode the string stored in _estring_. _cycles_ is the number of iterations to be used to decode the data. It MUST be the same number as was used to encode the string in lib_encode(). _esize_ holds the size of the encrypted data to be decode. The function returns a pointer to the decoded string of bytes. _dsize_, if not NULL, holds the size of the decoded string upon return of the function. The function returns NULL if _key_ is NULL or is of zero length, _estring_ is NULL or is invalid, or if there is insufficient memory to allocate a storage for the decoded string. If _cycles_ is less than 1, then it defaults to 1. NOTE: Memory to hold the decrypted string is allocated and should be freed when no longer needed in order to avoid memory leaks. ::::::::::::::: char *lib_pscramble(unsigned char *original, unsigned char *new, int size) lib_pscramble() takes a string of bytes in _original_ and scrambles them up in random order. _size_ holds the length of _original_. The function returns a pointer to the scrambled string which is stored in _new_. If _original_ is NULL, _new_ is NULL, or _size_ is less than 1, then NULL is returned. ::::::::::::::: char *lib_scramble(unsigned char *orig, char *new, int size, long key) lib_scramble(), like lib_pscramble() scrambles a string of bytes. The difference between them is that lib_pscramble() randomly generates a key fed to a random number generator while lib_scramble() accepts a caller supplied key. This allows the string to be unscrambled with lib_unscramble(). The string to be scrambled is in _orig_. _new_ is a string of equal or greater size than _orig_ in which to hold the scrambled result. _size_ is the number of bytes in _orig_ to be scrambled. _key_ is the value used to randomly scramble the string. If, successful, the function returns a pointer to _new_. NULL is returned if _orig_ is NULL, _new_ is NULL, or _size_ is less than 1. ::::::::::::::: char *lib_unscramble(unsigned char *str, char *orig, int size, long key) lib_unscramble() takes a scrambled string previously scrambled with lib_scramble() and unscrambles it. _str_ is the scrambled string. _orig_ is a pointer to an array of equal (or greater) size to _str_ in which the result will be stored. _size_ is the size of the scrambled string. _key_ is the value that was used to randomly scramble the string. It must be the same as the key used to scramble the string in lib_scramble() in order to successfully de-scramble the string. If successful, the function returns a pointer to _orig_. NULL is returned if _str_ is NULL, if _orig_ is NULL, or _size_ is less than 1. ::::::::::::::: unsigned int lib_checksum(char *data, int size, char function) lib_checksum() calculates a hash value using a provided string of bytes in _data_. _size_ holds the size of the array of bytes in _data_. The function returns the calculated value or 0 if _data_ is NULL or _size_ is less than 1. There are six different hash functions available. If _function_ is less than 1 then it will be set to 1. If it is greater HFUNC (currently 7) then it will be set to 7. This function provides a primitive way of comparing two strings by value rather than by the strings themselves for security reasons. It is NOT fool-proof, however. Two strings that produce the same value are probably the same, but other obscure strings could produce the same value as well. If two strings produce different values, then they are definitely NOT the same. ::::::::::::::: int lib_bitrotate(unsigned char *str, short len, char direction) lib_bitrotate() rotates the bits in a string of bytes by 1 bit. The byte string in _str_ is modified in place by the function. _len_ holds the length of the string in _str_ to be rotated. _direction_ indicates which way the rotation will occur. If _direction_ is negative, then all of the bits in _str_ are rotated/shifted 1 bit to the left. If _direction_ is positive, then the bits are rotated/shifted 1 bit to the right. The function returns 1 on success or -1 if _str_ is NULL or _len_ is less than 0. If _len_ is 0 or _direction_ is 0 then the function returns 0 and nothing is done. Byte boundaries within the string are meaningless. A bit shifted out of one byte will be shifted into the next byte with end bits being rotated into the byte at the opposite end of the string. ::::::::::::::: char *lib_hextobin(unsigned char *str, char *bin, int *dsize) lib_hextobin() converts a string of hex digits stored in _str_ to its binary ASCII equivalent. The result is stored in _bin_. If _dsize_ is not NULL, then the size of the binary data is store in it. The function returns a pointer to _bin_ if successful. The function returns NULL if _str_ is NULL, if _bin_ is NULL, or if _str_ contains less than 2 hex digits. NULL will also be returned if a non-hexidecimal character is encountered. NOTE: Since ASCII representations require 2 hex digits per character, any remaining odd digit will be ignored upon conversion (eg. for 3FE, E will be ignored as it does not form a pair). Also, case conversions are handled cleanly (eg. e = E). ::::::::::::::: char *lib_bintohex(unsigned char *str, int dsize, char *hex, int *hsize) lib_bintohex() converts a string of bytes in _str_ to their hexidecimal values. _dsize_ contains the number of bytes to be converted. _hex_ is a pointer to an array of characters. _hex_ needs to be 2*_dsize_ + 1 in size to avoid buffer overflows. The length of the converted string is stored in _hsize_ if it is not NULL. On success, the function returns a pointer to _hex_. NULL is returned if _str_ is NULL, _hex_ is NULL, or if _dsize_ is less than 1. The returned hex values are in uppercase. _hex_ is nul terminated upon completion. ::::::::::::::: void *lib_invert(void *buff,