Re-added PWMD_OPTION_PINENTRY_TRIES for the local pinentry.
[libpwmd.git] / src / mem.c
blobbded9282d70c232b756433aff7817508165c6b81
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of libpwmd.
8 Libpwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Libpwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <err.h>
31 #include <pthread.h>
33 #include "gettext.h"
34 #define N_(msgid) gettext(msgid)
36 #include "mem.h"
38 static struct memlist_s *memlist;
39 static pthread_mutex_t mem_mutex;
40 #ifdef DEBUG
41 static size_t allocations, deallocations;
42 #endif
44 void _xmem_init()
46 static int init;
48 if (!init)
49 pthread_mutex_init(&mem_mutex, NULL);
51 init = 1;
54 static int memlist_remove(void *ptr, const char *func)
56 struct memlist_s *m, *last = NULL, *p;
58 pthread_mutex_lock(&mem_mutex);
60 for (m = memlist; m; m = m->next) {
61 if (m->ptr == ptr) {
62 #ifdef DEBUG
63 fprintf(stderr, "%s: %p %i\n", func, ptr, m->size);
64 #endif
65 memset(m->ptr, 0, m->size);
66 free(m->ptr);
68 p = m->next;
69 free(m);
70 #ifdef DEBUG
71 deallocations++;
72 #endif
74 if (last)
75 last->next = p;
76 else
77 memlist = p;
79 pthread_mutex_unlock(&mem_mutex);
80 return 1;
83 last = m;
86 pthread_mutex_unlock(&mem_mutex);
87 return 0;
90 static void memlist_prepend(struct memlist_s *new)
92 pthread_mutex_lock(&mem_mutex);
93 #ifdef DEBUG
94 allocations++;
95 #endif
96 new->next = memlist;
97 memlist = new;
98 pthread_mutex_unlock(&mem_mutex);
101 void _xfree(void *ptr)
103 if (!ptr)
104 return;
106 if (!memlist_remove(ptr, __FUNCTION__)) {
107 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
108 assert(0);
112 void *_xmalloc(size_t size)
114 void *p;
115 struct memlist_s *m;
117 if (size <= 0)
118 return NULL;
120 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
121 return NULL;
123 if ((p = (void *)malloc(size)) == NULL) {
124 free(m);
125 return NULL;
128 m->ptr = p;
129 m->size = size;
130 memlist_prepend(m);
131 #ifdef DEBUG
132 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
133 #endif
134 return m->ptr;
137 void *_xcalloc(size_t nmemb, size_t size)
139 void *p;
140 struct memlist_s *m;
142 if (size <= 0)
143 return NULL;
145 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
146 return NULL;
148 if ((p = calloc(nmemb, size)) == NULL) {
149 free(m);
150 return NULL;
153 m->ptr = p;
154 m->size = nmemb * size;
155 memlist_prepend(m);
156 #ifdef DEBUG
157 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, nmemb * size);
158 #endif
159 return m->ptr;
162 void *_xrealloc(void *ptr, size_t size)
164 void *p;
165 struct memlist_s *m;
167 if (size <= 0)
168 return ptr;
170 if (!ptr)
171 return _xmalloc(size);
173 pthread_mutex_lock(&mem_mutex);
175 for (m = memlist; m; m = m->next) {
176 if (m->ptr == ptr) {
177 if ((p = (void *)malloc(size)) == NULL) {
178 pthread_mutex_unlock(&mem_mutex);
179 return NULL;
182 memcpy(p, m->ptr, size < m->size ? size : m->size);
183 memset(m->ptr, 0, m->size);
184 free(m->ptr);
185 m->ptr = p;
186 m->size = size;
187 #ifdef DEBUG
188 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
189 #endif
190 pthread_mutex_unlock(&mem_mutex);
191 return m->ptr;
195 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
196 pthread_mutex_unlock(&mem_mutex);
197 assert(0);
198 return NULL;
201 char *_xstrdup(const char *str)
203 char *t, *tp;
204 size_t len;
205 const char *p;
207 if (!str)
208 return NULL;
210 len = strlen(str) + 1;
212 if ((t = (char *)_xmalloc(len * sizeof(char))) == NULL)
213 return NULL;
215 for (p = str, tp = t; *p; p++)
216 *tp++ = *p;
218 *tp = 0;
219 #ifdef DEBUG
220 fprintf(stderr, "%s: %p\n", __FUNCTION__, t);
221 #endif
222 return t;
225 void _xpanic(void)
227 struct memlist_s *m;
229 pthread_mutex_lock(&mem_mutex);
231 for (m = memlist; m; m = memlist)
232 _xfree(m->ptr);
234 pthread_mutex_unlock(&mem_mutex);
237 #ifdef DEBUG
238 void _xdump(void)
240 struct memlist_s *m;
241 size_t total = 0;
243 pthread_mutex_lock(&mem_mutex);
245 for (m = memlist; m; m = m->next) {
246 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size);
247 total += m->size;
250 fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total,
251 allocations, deallocations);
252 pthread_mutex_unlock(&mem_mutex);
254 #endif