-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmisc.c
162 lines (131 loc) · 3.19 KB
/
misc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <wordexp.h>
#include "misc.h"
#include "kvmap.h"
#include "platform.h"
/* Return the current value of fd's O_NONBLOCK flag */
int get_fd_nonblock(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
perror("fcntl");
abort();
}
return !!(flags & O_NONBLOCK);
}
/* Set fd's O_NONBLOCK flag to 'nb' */
void set_fd_nonblock(int fd, int nb)
{
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
perror("fcntl");
abort();
}
if (nb)
flags |= O_NONBLOCK;
else
flags &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags)) {
perror("fcntl");
abort();
}
}
/* Set fd's FD_CLOEXEC flag to 'ce' */
void set_fd_cloexec(int fd, int ce)
{
int flags = fcntl(fd, F_GETFD);
if (flags == -1) {
perror("fcntl");
abort();
}
if (ce)
flags |= FD_CLOEXEC;
else
flags &= ~FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags)) {
perror("fcntl");
abort();
}
}
/*
* Perform shell-like word expansion on a string (so we can have conveniences
* like "~" to refer to home directories in paths in config files).
*/
char* expand_word(const char* wd)
{
char* ret;
wordexp_t exp;
/*
* OSX's wordexp(3) sadly just ignores these flags, but I guess we
* might as well try...
*/
if (wordexp(wd, &exp, WRDE_NOCMD|WRDE_UNDEF) || exp.we_wordc != 1)
return NULL;
ret = xstrdup(exp.we_wordv[0]);
wordfree(&exp);
return ret;
}
struct kvmflatten_ctx {
struct kvpair* pairs;
u_int numpairs;
};
/* kvmap_foreach() callback used for flattening a kvmap into a pair array */
static void flattencb(const char* key, const char* value, void* arg)
{
struct kvmflatten_ctx* ctx = arg;
ctx->pairs = xrealloc(ctx->pairs, (ctx->numpairs + 1) * sizeof(*ctx->pairs));
ctx->pairs[ctx->numpairs].key = xstrdup(key);
ctx->pairs[ctx->numpairs].value = xstrdup(value);
ctx->numpairs++;
}
/*
* Turn a kvmap into an array of struct kvpairs, returning the number of
* kvpairs in *numpairs.
*/
struct kvpair* flatten_kvmap(const struct kvmap* kvm, u_int* numpairs)
{
struct kvmflatten_ctx ctx = { .pairs = NULL, .numpairs = 0, };
kvmap_foreach(kvm, flattencb, &ctx);
*numpairs = ctx.numpairs;
return ctx.pairs;
}
/* Inverse of flatten_kvmap(). */
struct kvmap* unflatten_kvmap(const struct kvpair* pairs, u_int numpairs)
{
int i;
struct kvmap* kvm = new_kvmap();
for (i = 0; i < numpairs; i++)
kvmap_put(kvm, pairs[i].key, pairs[i].value);
return kvm;
}
/*
* Small helper to tack a NUL-terminator onto a buffer (presumably from a
* message) containing a string and set the clipboard from it.
*/
void set_clipboard_from_buf(const void* buf, size_t len)
{
char* tmp;
/*
* extra intermediate malloc()ed area just to tack on the NUL
* terminator here is a bit inefficient...
*/
tmp = xmalloc(len + 1);
memcpy(tmp, buf, len);
tmp[len] = '\0';
set_clipboard_text(tmp);
xfree(tmp);
}
/*
* Adapted from Ted Unangst's public-domain explicit_bzero.c (originally in
* OpenBSD libc I think, now also elsewhere).
*
* Indirect bzero through a volatile pointer to hopefully avoid dead-store
* optimisation eliminating the call.
*/
static void (* volatile enthrall_bzero)(void *, size_t) = bzero;
void explicit_bzero(void* p, size_t n)
{
enthrall_bzero(p, n);
}