1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * Copyright © 2016 Ingo Bürk
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the names of the authors or their
24  * institutions shall not be used in advertising or otherwise to promote the
25  * sale, use or other dealings in this Software without prior written
26  * authorization from the authors.
27  *
28  */
29 #include "externals.h"
30 
31 #include "util.h"
32 
str2long(long * out,const char * input,const int base)33 int str2long(long *out, const char *input, const int base) {
34     char *end;
35     long result;
36 
37     if (input[0] == '\0' || isspace(input[0]))
38         return -FAILURE;
39 
40     errno = 0;
41     result = strtol(input, &end, base);
42     if (errno == ERANGE && result == LONG_MAX)
43         return -FAILURE;
44     if (errno == ERANGE && result == LONG_MIN)
45         return -FAILURE;
46     if (*end != '\0')
47         return -FAILURE;
48 
49     *out = result;
50     return SUCCESS;
51 }
52 
get_home_dir_file(const char * filename)53 char *get_home_dir_file(const char *filename) {
54     char *result;
55 
56     char *home = getenv("HOME");
57     if (home == NULL)
58         return NULL;
59 
60     if (asprintf(&result, "%s/%s", home, filename) < 0)
61         return NULL;
62 
63     return result;
64 }
65 
resolve_path(const char * path,const char * _base)66 char *resolve_path(const char *path, const char *_base) {
67     char *base;
68     char *result;
69 
70     if (path[0] == '/')
71         return strdup(path);
72 
73     base = (_base == NULL) ? getcwd(NULL, 0) : strdup(_base);
74     if (base == NULL)
75         return NULL;
76 
77     if (asprintf(&result, "%s/%s", base, path) < 0) {
78         FREE(base);
79         return NULL;
80     }
81     FREE(base);
82 
83     return result;
84 }
85 
file_get_contents(const char * filename)86 char *file_get_contents(const char *filename) {
87     FILE *file;
88     struct stat stbuf;
89     size_t file_size;
90     char *content;
91 
92     if ((file = fopen(filename, "rb")) == NULL)
93         return NULL;
94 
95     /* We want to read the file in one go, so figure out the file size. */
96     if (fstat(fileno(file), &stbuf) < 0) {
97         fclose(file);
98         return NULL;
99     }
100     file_size = stbuf.st_size;
101 
102     /* Read the file content. */
103     content = calloc(file_size + 1, 1);
104     if (content == NULL) {
105         fclose(file);
106         return NULL;
107     }
108 
109     if (fread(content, 1, file_size, file) != file_size) {
110         FREE(content);
111         fclose(file);
112         return NULL;
113     }
114 
115     fclose(file);
116     content[file_size] = '\0';
117     return content;
118 }
119 
xcb_util_get_property(xcb_connection_t * conn,xcb_window_t window,xcb_atom_t atom,xcb_atom_t type,size_t size)120 char *xcb_util_get_property(xcb_connection_t *conn, xcb_window_t window, xcb_atom_t atom,
121         xcb_atom_t type, size_t size) {
122     xcb_get_property_cookie_t cookie;
123     xcb_get_property_reply_t *reply;
124     xcb_generic_error_t *err;
125     int reply_length;
126     char *content;
127 
128     cookie = xcb_get_property(conn, 0, window, atom, type, 0, size);
129     reply = xcb_get_property_reply(conn, cookie, &err);
130     if (err != NULL) {
131         FREE(err);
132         return NULL;
133     }
134 
135     if (reply == NULL || (reply_length = xcb_get_property_value_length(reply)) == 0) {
136         FREE(reply);
137         return NULL;
138     }
139 
140     if (reply->bytes_after > 0) {
141         size_t adjusted_size = size + ceil(reply->bytes_after / 4.0);
142         FREE(reply);
143         return xcb_util_get_property(conn, window, atom, type, adjusted_size);
144     }
145 
146     if (asprintf(&content, "%.*s", reply_length, (char *)xcb_get_property_value(reply)) < 0) {
147         FREE(reply);
148         return NULL;
149     }
150 
151     FREE(reply);
152     return content;
153 }
154