#ifdef HAVE_CONFIG_H # include "config.h" #endif #include "xwrap.h" #include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #define RETRY_SEC 0 #define RETRY_NSEC 250000000 static const char fail_msg[] = "Fail to allocate memory. Retry ...\n"; static const size_t fail_len = STATIC_STRLEN (fail_msg); void* xmalloc (size_t size) { void* memptr; while ((memptr = malloc (size)) == NULL) { nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); write (STDERR_FILENO, fail_msg, fail_len); } return memptr; } void* xrealloc (void* ptr, size_t size) { void* newptr; while ((newptr = realloc (ptr, size)) == NULL) { nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); write (STDERR_FILENO, fail_msg, fail_len); } return newptr; } char* xstrcat (const char* str, ...) { va_list ap; char* strp; char* strnow; char* newstr; int len = strlen (str); va_start (ap, str); while ((strp = va_arg (ap, char*)) != NULL) { len += strlen (strp); } va_end (ap); newstr = xmalloc (len + 1); va_start (ap, str); strnow = stpcpy (newstr, str); while ((strp = va_arg (ap, char*)) != NULL) { strnow = stpcpy (strnow, strp); } newstr[len] = '\0'; va_end (ap); return newstr; } char* xstrdup (const char* str) { char* newstr; while ((newstr = strdup (str)) == NULL) { nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); write (STDERR_FILENO, fail_msg, fail_len); } return newstr; } char* xsprintf (const char* format, ...) { va_list ap; char* newstr; int len; va_start (ap, format); len = vsnprintf (NULL, 0, format, ap) + 1; va_end (ap); newstr = xmalloc (len); va_start (ap, format); vsnprintf (newstr, len, format, ap); va_end (ap); return newstr; } char* xgetcwd (void) { char *cwd, *result; size_t size = pathconf (".", _PC_PATH_MAX); size = size > 0 ? size : 256; cwd = xmalloc (sizeof (char) * size); while ((result = getcwd (cwd, size)) == NULL && errno == ERANGE) { size *= 2; cwd = xrealloc (cwd, size); } if (result == NULL) { strncpy (cwd, "<Unknown working directory>", size - 1); } return cwd; }