diff options
Diffstat (limited to 'bin/lem.c')
-rw-r--r-- | bin/lem.c | 55 |
1 files changed, 54 insertions, 1 deletions
@@ -37,7 +37,7 @@ #endif #ifdef NDEBUG -#define lem_log_error(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#define lem_log_error(fmt, ...) lem_dprintf(STDERR_FILENO, fmt "\n", ##__VA_ARGS__) #else #define lem_log_error lem_debug #endif @@ -93,6 +93,59 @@ lem_xmalloc(size_t size) return p; } +/* non-blocking tolerant version of dprintf(3) */ +void +lem_dprintf(int fd, const char *fmt, ...) +{ + int size = 0; + char *p = NULL; + va_list ap; + char *pos; + ssize_t ret; + size_t bytes_left; + + /* Determine required size */ + va_start(ap, fmt); + size = vsnprintf(p, size, fmt, ap); + va_end(ap); + + if (size < 0) + return; + + size++; /* for '\0' */ + p = lem_xmalloc(size); + if (p == NULL) + return; + + va_start(ap, fmt); + size = vsnprintf(p, size, fmt, ap); + va_end(ap); + + if (size < 0) { + free(p); + return; + } + + pos = p; + bytes_left = size; + while (bytes_left > 0) { + ret = write(fd, pos, bytes_left); + if (ret == -1) { + /* since this function is only used for debug messages + * we prefer sleeping, over missing debug messages */ + if (errno == EAGAIN || errno == EINTR) { + usleep(100); + continue; + } + break; + } else { + pos += ret; + bytes_left -= ret; + } + } + free(p); +} + static int setsignal(int signal, void (*handler)(int), int flags) { |