1 /* **************************** */
2 /* Memory management functions. */
3 /* **************************** */
4 
5 /* Created by Kevin Locke (from numerous canonical examples).        */
6 /*                                                                   */
7 /* Adapted for use by smenu.                                         */
8 /*                                                                   */
9 /* I hereby place this file in the public domain.  It may be freely  */
10 /* reproduced, distributed, used, modified, built upon, or otherwise */
11 /* employed by anyone for any purpose without restriction.           */
12 /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 
19 #include "config.h"
20 #include "xmalloc.h"
21 
22 /* The following rpl_* function are necessary for AIX which doesn't     */
23 /* provide 'GNU compatible' allocation functions.                       */
24 /* Every call to malloc()/realloc() is then replaced by a call to       */
25 /* rpl_malloc()/rpl_realloc() as defined in the GNU generated config.h. */
26 /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
27 
28 #ifdef malloc
29 
30 #undef malloc
31 extern void * malloc(size_t);
32 
33 void *
rpl_malloc(size_t size)34 rpl_malloc(size_t size)
35 {
36   if (!size)
37     size++;
38   return malloc(size);
39 }
40 
41 #undef realloc
42 extern void *
43 realloc(void *, size_t);
44 
45 void *
rpl_realloc(void * ptr,size_t size)46 rpl_realloc(void * ptr, size_t size)
47 {
48   if (!size)
49     size++;
50   return (ptr ? realloc(ptr, size) : malloc(size));
51 }
52 
53 #endif
54 
55 /* ================== */
56 /* Customized malloc. */
57 /* ================== */
58 void *
xmalloc(size_t size)59 xmalloc(size_t size)
60 {
61   void * allocated;
62   size_t real_size;
63 
64   real_size = (size > 0) ? size : 1;
65   allocated = malloc(real_size);
66   if (allocated == NULL)
67   {
68     fprintf(stderr,
69             "Error: Insufficient memory (attempt to malloc %lu bytes)\n",
70             (unsigned long int)size);
71 
72     exit(EXIT_FAILURE);
73   }
74 
75   return allocated;
76 }
77 
78 /* ================== */
79 /* Customized calloc. */
80 /* ================== */
81 void *
xcalloc(size_t n,size_t size)82 xcalloc(size_t n, size_t size)
83 {
84   void * allocated;
85 
86   n         = (n > 0) ? n : 1;
87   size      = (size > 0) ? size : 1;
88   allocated = calloc(n, size);
89   if (allocated == NULL)
90   {
91     fprintf(stderr,
92             "Error: Insufficient memory (attempt to calloc %lu bytes)\n",
93             (unsigned long int)size);
94 
95     exit(EXIT_FAILURE);
96   }
97 
98   return allocated;
99 }
100 
101 /* =================== */
102 /* Customized realloc. */
103 /* =================== */
104 void *
xrealloc(void * p,size_t size)105 xrealloc(void * p, size_t size)
106 {
107   void * allocated;
108 
109   allocated = realloc(p, size);
110   if (allocated == NULL && size > 0)
111   {
112     fprintf(stderr,
113             "Error: Insufficient memory (attempt to xrealloc %lu bytes)\n",
114             (unsigned long int)size);
115 
116     exit(EXIT_FAILURE);
117   }
118 
119   return allocated;
120 }
121 
122 /* ==================================== */
123 /* strdup implementation using xmalloc. */
124 /* ==================================== */
125 char *
xstrdup(const char * p)126 xstrdup(const char * p)
127 {
128   char * allocated;
129 
130 #ifdef HAVE_STRDUP
131   allocated = strdup(p);
132 
133   if (allocated == NULL)
134   {
135     fprintf(stderr, "Error: Insufficient memory for strdup.\n");
136 
137     exit(EXIT_FAILURE);
138   }
139 #else
140   allocated = xmalloc(strlen(p) + 1);
141   strcpy(allocated, p);
142 #endif
143 
144   return allocated;
145 }
146 
147 /* =================================================== */
148 /* strndup implementation using xmalloc.               */
149 /* This version guarantees that there is a final '\0'. */
150 /* =================================================== */
151 char *
xstrndup(const char * str,size_t len)152 xstrndup(const char * str, size_t len)
153 {
154   char * p;
155 
156 #ifdef HAVE_STRNDUP
157   p = strndup(str, len);
158 
159   if (p == NULL)
160   {
161     fprintf(stderr, "Error: Insufficient memory for strndup.\n");
162 
163     exit(EXIT_FAILURE);
164   }
165 #else
166   p = memchr(str, '\0', len);
167 
168   if (p)
169     len = p - str;
170 
171   p = xmalloc(len + 1);
172   memcpy(p, str, len);
173   p[len] = '\0';
174 #endif
175 
176   return p;
177 }
178