Remove GLib dependency.
[pwmd.git] / src / util-misc.c
blobdb5f07dd8d2a984def71bc9364c7972dff5521dd
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <pwd.h>
35 #include "pwmd-error.h"
36 #include <gcrypt.h>
37 #include "util-misc.h"
38 #include "util-string.h"
39 #include "mutex.h"
40 #include "cache.h"
41 #include "mem.h"
43 extern void log_write(const char *fmt, ...);
45 int valid_filename(const char *filename)
47 const char *p;
49 if (!filename || !*filename)
50 return 0;
52 if (!strcmp(filename, "-"))
53 return 0;
55 for (p = filename; *p; p++) {
56 if (*p == '/' || isspace(*p))
57 return 0;
60 return 1;
63 char *get_username()
65 struct passwd *pw = getpwuid(getuid());
67 return pw ? pw->pw_name : NULL;
70 char *get_home_dir()
72 struct passwd pw, *result;
73 size_t len;
74 char *buf;
76 if (home_directory)
77 return home_directory;
79 len = sysconf(_SC_GETPW_R_SIZE_MAX);
80 if (len == -1)
81 len = 16384;
83 buf = xmalloc(len);
84 if (!buf)
85 return NULL;
87 if (!getpwuid_r(getuid(), &pw, buf, len, &result))
88 home_directory = str_dup(result->pw_dir);
90 xfree(buf);
91 return home_directory;
94 char *expand_homedir(char *str)
96 char *p = str;
98 if (*p++ == '~')
99 return str_asprintf("%s%s", get_home_dir(), p);
101 return str_dup(str);
104 gpg_error_t parse_options(char **line, struct argv_s *args[], void * data)
106 char *p = *line;
107 gpg_error_t rc = 0;
109 for (; p && *p; p++) {
110 while (*p == ' ')
111 p++;
113 if (!*p)
114 break;
116 if (*p == '-' && *(p+1) == '-') {
117 p += 2;
118 char opt[255] = {0}, value[255] = {0};
119 char *tp;
120 unsigned len;
122 if (!*p || *p == ' ') {
123 if (*p)
124 p++;
126 break;
129 for (tp = opt, len = 0; *p; p++, len++) {
130 if (len+1 == 255)
131 return GPG_ERR_LINE_TOO_LONG;
133 if (*p == ' ' || *p == '=') {
134 int inquote = 0;
136 *tp = 0;
138 if (*p == '=') {
139 p++;
141 for (tp = value, len = 0; *p; p++, len++) {
142 if (len+1 == 255)
143 return GPG_ERR_LINE_TOO_LONG;
145 if (*p == '\"') {
146 inquote = !inquote;
147 continue;
149 else if (*p == ' ' && !inquote)
150 break;
152 *tp++ = *p;
155 *tp = 0;
158 break;
161 *tp++ = *p;
164 *tp = 0;
165 int match = 0;
167 for (int i = 0; args[i]; i++) {
168 if (!strcmp(args[i]->opt, opt)) {
169 log_write1("param: name='%s' value='%s'", opt, value);
170 if (args[i]->type == OPTION_TYPE_NOARG && *value)
171 return GPG_ERR_SYNTAX;
172 else if (args[i]->type == OPTION_TYPE_ARG && !*value)
173 return GPG_ERR_SYNTAX;
175 rc = args[i]->func(data, value);
177 if (rc)
178 return rc;
180 match = 1;
181 break;
185 if (!match)
186 return GPG_ERR_UNKNOWN_OPTION;
188 if (!*p)
189 break;
191 continue;
194 break;
197 *line = p;
198 return rc;
201 char *bin2hex(const unsigned char *data, size_t len)
203 size_t size = len*2+1;
204 char buf[size];
205 size_t n;
207 buf[0] = 0;
209 for (n = 0; n < len; n++) {
210 char c[3];
212 sprintf(c, "%02X", data[n]);
213 strcat(buf, c);
216 return str_dup(buf);
219 char *plus_escape(const char *fmt, ...)
221 va_list ap;
222 char *str;
224 va_start(ap, fmt);
226 if (str_vasprintf(&str, fmt, ap) > 0) {
227 char *p;
229 for (p = str; *p; p++) {
230 if (*p == ' ')
231 *p = '+';
234 va_end(ap);
235 return str;
238 va_end(ap);
239 return NULL;
242 static char *strip_texi(const char *str)
244 const char *p;
245 char *s = str_dup(str);
246 int c = 0;
248 if (!s)
249 return NULL;
251 for (p = str; *p; p++) {
252 if (*p == '@' && *(p+1) != '@') {
253 if (!strncasecmp(p+1, "table", 5)
254 || !strncasecmp(p+1, "end ", 4)) {
255 while (*p++ != '\n');
256 p--;
257 continue;
259 else if (!strncasecmp(p+1, "example", 7)
260 || !strncasecmp(p+1, "end ", 4)) {
261 while (*p++ != '\n');
262 p--;
263 continue;
265 else if (!strncasecmp(p+1, "sp ", 3)) {
266 p += 3;
268 while (*p && isdigit(*p++))
269 p++;
270 continue;
272 else if (!strncasecmp(p+1, "item", 4)) {
273 p += 5;
274 while (*p && *p != '\n')
275 s[c++] = *p++;
277 continue;
279 else if (!strncasecmp(p+1, "pxref", 5)) {
280 p += 6;
281 strcat(s, "see ");
282 c = strlen(s);
283 goto close;
285 else if (!strncasecmp(p+1, "xref", 4)) {
286 p += 5;
287 strcat(s, "See ");
288 c = strlen(s);
289 goto close;
292 while (*p && *p != '{') {
293 if (*++p == '*') {
294 p++;
295 goto append;
299 close:
300 if (*p) {
301 p++;
302 s[c++] = '`';
303 while (*p && *p != '}')
304 s[c++] = *p++;
306 if (*p)
307 p++;
309 s[c++] = '\'';
312 else if (*p == '@' && *(p+1) == '@')
313 p++;
315 append:
316 if (*p)
317 s[c++] = *p;
319 s[c] = 0;
322 s[c] = 0;
323 return s;
327 char *strip_texi_and_wrap(const char *str)
329 char *tmp = strip_texi(str);
330 char *help = xmalloc(strlen(tmp+1)*2);
331 char *p, *ph;
332 int i;
334 for (p = tmp, ph = help, i = 0; *p; p++, i++) {
335 if (i == 79 || *p == '\n') {
336 if (!(*p == ' ')) {
337 char *t = ph;
338 int n = 0;
340 while (!(*--t == ' '))
341 n++;
343 *t++ = '\n';
344 i = -1;
345 p -= n;
346 while (n--) {
347 *t++ = *p++;
348 i++;
351 else {
352 *ph++ = '\n';
353 i = -1;
354 while (*p != '\n' && *p == ' ')
355 p++;
359 *ph++ = *p;
362 *ph = 0;
363 xfree(tmp);
364 return help;
367 void free_key(void *data)
369 xfree(data);
372 gpg_error_t create_thread(void *(*cb)(void *), void *data,
373 pthread_t *tid, int detached)
375 pthread_attr_t attr;
376 int n;
378 pthread_attr_init(&attr);
380 if (detached)
381 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
383 n = pthread_create(tid, &attr, cb, data);
384 pthread_attr_destroy(&attr);
385 return gpg_error_from_errno(n);
388 void cleanup_mutex_cb(void *arg)
390 pthread_mutex_t *m = (pthread_mutex_t *)arg;
392 MUTEX_UNLOCK(m);
395 void cleanup_fd_cb(void *arg)
397 int fd = *(int *)arg;
399 if (fd != -1)
400 close(fd);
403 void cleanup_unlink_cb(void *arg)
405 char *file = arg;
407 if (file && *file)
408 unlink(file);
411 void cleanup_cache_mutex(void *arg)
413 cache_unlock();
416 int valid_keygrip(const unsigned char *data, size_t len)
418 for (size_t i = 0; i < len; i++) {
419 if (data[i])
420 return 1;
423 return 0;
426 gpg_error_t get_checksum(const char *filename, unsigned char **r_crc, size_t *r_crclen)
428 int fd;
429 unsigned char *buf;
430 gpg_error_t rc = 0;
431 size_t len;
432 struct stat st;
434 if (stat(filename, &st) == -1)
435 return gpg_error_from_syserror();
437 fd = open(filename, O_RDONLY);
438 if (fd == -1)
439 return gpg_error_from_syserror();
441 pthread_cleanup_push(cleanup_fd_cb, &fd);
442 buf = xmalloc(st.st_size);
443 if (buf) {
444 pthread_cleanup_push(xfree, buf);
446 len = read(fd, buf, st.st_size);
447 if (len == st.st_size) {
448 if (buf) {
449 unsigned char *crc;
451 len = gcry_md_get_algo_dlen(GCRY_MD_CRC32);
452 crc = xmalloc(len);
453 if (crc) {
454 pthread_cleanup_push(xfree, crc);
455 gcry_md_hash_buffer(GCRY_MD_CRC32, crc, buf, st.st_size);
456 *r_crc = crc;
457 *r_crclen = len;
458 pthread_cleanup_pop(0);
460 else
461 rc = GPG_ERR_ENOMEM;
464 else
465 rc = GPG_ERR_TOO_SHORT;
467 pthread_cleanup_pop(1);
469 else
470 rc = GPG_ERR_ENOMEM;
472 pthread_cleanup_pop(1);
473 return rc;