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