You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smartcardauth/src/xmalloc.c

164 lines
4.5 KiB

/* $Id: xmalloc.c 5381 2002-03-31 22:35:47Z rra $
**
** malloc routines with failure handling.
**
** Usage:
**
** extern xmalloc_handler_t memory_error;
** extern const char *string;
** char *buffer;
**
** xmalloc_error_handler = memory_error;
** buffer = xmalloc(1024);
** xrealloc(buffer, 2048);
** free(buffer);
** buffer = xcalloc(1024);
** free(buffer);
** buffer = xstrdup(string);
** free(buffer);
** buffer = xstrndup(string, 25);
**
** xmalloc, xcalloc, xrealloc, and xstrdup behave exactly like their C
** library counterparts without the leading x except that they will never
** return NULL. Instead, on error, they call xmalloc_error_handler,
** passing it the name of the function whose memory allocation failed, the
** amount of the allocation, and the file and line number where the
** allocation function was invoked (from __FILE__ and __LINE__). This
** function may do whatever it wishes, such as some action to free up
** memory or a call to sleep to hope that system resources return. If the
** handler returns, the interrupted memory allocation function will try its
** allocation again (calling the handler again if it still fails).
**
** xstrndup behaves like xstrdup but only copies the given number of
** characters. It allocates an additional byte over its second argument and
** always nul-terminates the string.
**
** The default error handler, if none is set by the caller, prints an error
** message to stderr and exits with exit status 1. An error handler must
** take a const char * (function name), size_t (bytes allocated), const
** char * (file), and int (line).
**
** xmalloc will return a pointer to a valid memory region on an xmalloc of 0
** bytes, ensuring this by allocating space for one character instead of 0
** bytes.
**
** The functions defined here are actually x_malloc, x_realloc, etc. The
** header file defines macros named xmalloc, etc. that pass the file name
** and line number to these functions.
*/
/* Used for unused parameters to silence gcc warnings. */
#define UNUSED __attribute__((__unused__))
/* Make available the bool type. */
#if INN_HAVE_STDBOOL_H
# include <stdbool.h>
#else
# undef true
# undef false
# define true (1)
# define false (0)
# ifndef __cplusplus
# define bool int
# endif
#endif /* INN_HAVE_STDBOOL_H */
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
/* Failure handler takes the function, the size, the file, and the line. */
typedef void (*xmalloc_handler_t)(const char *, size_t, const char *, int);
/* Assign to this variable to choose a handler other than the default, which
just calls sysdie. */
extern xmalloc_handler_t xmalloc_error_handler;
/* The default error handler. */
void
xmalloc_fail(const char *function, size_t size, const char *file, int line)
{
sysdie("failed to %s %lu bytes at %s line %d", function,
(unsigned long) size, file, line);
}
/* Assign to this variable to choose a handler other than the default. */
xmalloc_handler_t xmalloc_error_handler = xmalloc_fail;
void *
x_malloc(size_t size, const char *file, int line)
{
void *p;
size_t real_size;
real_size = (size > 0) ? size : 1;
p = malloc(real_size);
while (p == NULL) {
(*xmalloc_error_handler)("malloc", size, file, line);
p = malloc(real_size);
}
return p;
}
void *
x_calloc(size_t n, size_t size, const char *file, int line)
{
void *p;
n = (n > 0) ? n : 1;
size = (size > 0) ? size : 1;
p = calloc(n, size);
while (p == NULL) {
(*xmalloc_error_handler)("calloc", n * size, file, line);
p = calloc(n, size);
}
return p;
}
void *
x_realloc(void *p, size_t size, const char *file, int line)
{
void *newp;
newp = realloc(p, size);
while (newp == NULL && size > 0) {
(*xmalloc_error_handler)("realloc", size, file, line);
newp = realloc(p, size);
}
return newp;
}
char *
x_strdup(const char *s, const char *file, int line)
{
char *p;
size_t len;
len = strlen(s) + 1;
p = malloc(len);
while (p == NULL) {
(*xmalloc_error_handler)("strdup", len, file, line);
p = malloc(len);
}
memcpy(p, s, len);
return p;
}
char *
x_strndup(const char *s, size_t size, const char *file, int line)
{
char *p;
p = malloc(size + 1);
while (p == NULL) {
(*xmalloc_error_handler)("strndup", size + 1, file, line);
p = malloc(size + 1);
}
memcpy(p, s, size);
p[size] = '\0';
return p;
}