chiark / gitweb /
rename recentact to lowvol
[inn-innduct.git] / lib / xmalloc.c
1 /* $Id: xmalloc.c 5381 2002-03-31 22:35:47Z rra $
2 **
3 **  malloc routines with failure handling.
4 **
5 **  Usage:
6 **
7 **       extern xmalloc_handler_t memory_error;
8 **       extern const char *string;
9 **       char *buffer;
10 **
11 **       xmalloc_error_handler = memory_error;
12 **       buffer = xmalloc(1024);
13 **       xrealloc(buffer, 2048);
14 **       free(buffer);
15 **       buffer = xcalloc(1024);
16 **       free(buffer);
17 **       buffer = xstrdup(string);
18 **       free(buffer);
19 **       buffer = xstrndup(string, 25);
20 **
21 **  xmalloc, xcalloc, xrealloc, and xstrdup behave exactly like their C
22 **  library counterparts without the leading x except that they will never
23 **  return NULL.  Instead, on error, they call xmalloc_error_handler,
24 **  passing it the name of the function whose memory allocation failed, the
25 **  amount of the allocation, and the file and line number where the
26 **  allocation function was invoked (from __FILE__ and __LINE__).  This
27 **  function may do whatever it wishes, such as some action to free up
28 **  memory or a call to sleep to hope that system resources return.  If the
29 **  handler returns, the interrupted memory allocation function will try its
30 **  allocation again (calling the handler again if it still fails).
31 **
32 **  xstrndup behaves like xstrdup but only copies the given number of
33 **  characters.  It allocates an additional byte over its second argument and
34 **  always nul-terminates the string.
35 **
36 **  The default error handler, if none is set by the caller, prints an error
37 **  message to stderr and exits with exit status 1.  An error handler must
38 **  take a const char * (function name), size_t (bytes allocated), const
39 **  char * (file), and int (line).
40 **
41 **  xmalloc will return a pointer to a valid memory region on an xmalloc of 0
42 **  bytes, ensuring this by allocating space for one character instead of 0
43 **  bytes.
44 **
45 **  The functions defined here are actually x_malloc, x_realloc, etc.  The
46 **  header file defines macros named xmalloc, etc. that pass the file name
47 **  and line number to these functions.
48 */
49
50 #include "config.h"
51 #include "clibrary.h"
52
53 #include "inn/messages.h"
54 #include "libinn.h"
55
56 /* The default error handler. */
57 void
58 xmalloc_fail(const char *function, size_t size, const char *file, int line)
59 {
60     sysdie("failed to %s %lu bytes at %s line %d", function,
61            (unsigned long) size, file, line);
62 }
63
64 /* Assign to this variable to choose a handler other than the default. */
65 xmalloc_handler_t xmalloc_error_handler = xmalloc_fail;
66
67 void *
68 x_malloc(size_t size, const char *file, int line)
69 {
70     void *p;
71     size_t real_size;
72
73     real_size = (size > 0) ? size : 1;
74     p = malloc(real_size);
75     while (p == NULL) {
76         (*xmalloc_error_handler)("malloc", size, file, line);
77         p = malloc(real_size);
78     }
79     return p;
80 }
81
82 void *
83 x_calloc(size_t n, size_t size, const char *file, int line)
84 {
85     void *p;
86
87     n = (n > 0) ? n : 1;
88     size = (size > 0) ? size : 1;
89     p = calloc(n, size);
90     while (p == NULL) {
91         (*xmalloc_error_handler)("calloc", n * size, file, line);
92         p = calloc(n, size);
93     }
94     return p;
95 }
96
97 void *
98 x_realloc(void *p, size_t size, const char *file, int line)
99 {
100     void *newp;
101
102     newp = realloc(p, size);
103     while (newp == NULL && size > 0) {
104         (*xmalloc_error_handler)("realloc", size, file, line);
105         newp = realloc(p, size);
106     }
107     return newp;
108 }
109
110 char *
111 x_strdup(const char *s, const char *file, int line)
112 {
113     char *p;
114     size_t len;
115
116     len = strlen(s) + 1;
117     p = malloc(len);
118     while (p == NULL) {
119         (*xmalloc_error_handler)("strdup", len, file, line);
120         p = malloc(len);
121     }
122     memcpy(p, s, len);
123     return p;
124 }
125
126 char *
127 x_strndup(const char *s, size_t size, const char *file, int line)
128 {
129     char *p;
130
131     p = malloc(size + 1);
132     while (p == NULL) {
133         (*xmalloc_error_handler)("strndup", size + 1, file, line);
134         p = malloc(size + 1);
135     }
136     memcpy(p, s, size);
137     p[size] = '\0';
138     return p;
139 }