1 /*
2 * vim:ts=4:sw=4:expandtab
3 *
4 * i3 - an improved dynamic tiling window manager
5 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6 *
7 */
8 #include "libi3.h"
9
10 #include <err.h>
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 /*
17 * The s* functions (safe) are wrappers around malloc, strdup, …, which exits if one of
18 * the called functions returns NULL, meaning that there is no more memory available
19 *
20 */
smalloc(size_t size)21 void *smalloc(size_t size) {
22 void *result = malloc(size);
23 if (result == NULL)
24 err(EXIT_FAILURE, "malloc(%zd)", size);
25 return result;
26 }
27
scalloc(size_t num,size_t size)28 void *scalloc(size_t num, size_t size) {
29 void *result = calloc(num, size);
30 if (result == NULL)
31 err(EXIT_FAILURE, "calloc(%zd, %zd)", num, size);
32 return result;
33 }
34
srealloc(void * ptr,size_t size)35 void *srealloc(void *ptr, size_t size) {
36 void *result = realloc(ptr, size);
37 if (result == NULL && size > 0)
38 err(EXIT_FAILURE, "realloc(%zd)", size);
39 return result;
40 }
41
sstrdup(const char * str)42 char *sstrdup(const char *str) {
43 char *result = strdup(str);
44 if (result == NULL)
45 err(EXIT_FAILURE, "strdup()");
46 return result;
47 }
48
sstrndup(const char * str,size_t size)49 char *sstrndup(const char *str, size_t size) {
50 char *result = strndup(str, size);
51 if (result == NULL)
52 err(EXIT_FAILURE, "strndup()");
53 return result;
54 }
55
sasprintf(char ** strp,const char * fmt,...)56 int sasprintf(char **strp, const char *fmt, ...) {
57 va_list args;
58 int result;
59
60 va_start(args, fmt);
61 if ((result = vasprintf(strp, fmt, args)) == -1)
62 err(EXIT_FAILURE, "asprintf(%s)", fmt);
63 va_end(args);
64 return result;
65 }
66
writeall(int fd,const void * buf,size_t count)67 ssize_t writeall(int fd, const void *buf, size_t count) {
68 size_t written = 0;
69
70 while (written < count) {
71 const ssize_t n = write(fd, ((char *)buf) + written, count - written);
72 if (n == -1) {
73 if (errno == EINTR || errno == EAGAIN)
74 continue;
75 return n;
76 }
77 written += (size_t)n;
78 }
79
80 return written;
81 }
82
writeall_nonblock(int fd,const void * buf,size_t count)83 ssize_t writeall_nonblock(int fd, const void *buf, size_t count) {
84 size_t written = 0;
85
86 while (written < count) {
87 const ssize_t n = write(fd, ((char *)buf) + written, count - written);
88 if (n == -1) {
89 if (errno == EAGAIN) {
90 return written;
91 } else if (errno == EINTR) {
92 continue;
93 } else {
94 return n;
95 }
96 }
97 written += (size_t)n;
98 }
99 return written;
100 }
101
swrite(int fd,const void * buf,size_t count)102 ssize_t swrite(int fd, const void *buf, size_t count) {
103 ssize_t n;
104
105 n = writeall(fd, buf, count);
106 if (n == -1)
107 err(EXIT_FAILURE, "Failed to write %d", fd);
108 else
109 return n;
110 }
111
112 /*
113 * Like strcasecmp but considers the case where either string is NULL.
114 *
115 */
strcasecmp_nullable(const char * a,const char * b)116 int strcasecmp_nullable(const char *a, const char *b) {
117 if (a == b) {
118 return 0;
119 }
120 if (a == NULL) {
121 return -1;
122 }
123 if (b == NULL) {
124 return 1;
125 }
126 return strcasecmp(a, b);
127 }
128