Test for error from cache_iscached().
[pwmd.git] / src / util-misc.c
blob4aedf6ce5f12c974135b60bd8f8fcebf45f688d2
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
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
46 valid_filename (const char *filename)
48 const char *p;
50 if (!filename || !*filename)
51 return 0;
53 if (filename[0] == '-' && filename[1] == 0)
54 return 0;
56 for (p = filename; *p; p++)
58 if (*p == '/' || isspace (*p))
59 return 0;
62 return 1;
65 char *
66 get_username ()
68 struct passwd *pw = getpwuid (getuid ());
70 return pw ? pw->pw_name : NULL;
73 char *
74 get_home_dir ()
76 #ifdef HAVE_GETPWNAM_R
77 struct passwd pw, *result;
78 size_t len;
79 char *buf;
81 if (home_directory)
82 return home_directory;
84 len = sysconf (_SC_GETPW_R_SIZE_MAX);
85 if (len == -1)
86 len = 16384;
88 buf = xmalloc (len);
89 if (!buf)
90 return NULL;
92 if (!getpwuid_r (getuid (), &pw, buf, len, &result))
93 home_directory = str_dup (result->pw_dir);
95 xfree (buf);
96 #else
97 struct passwd *result = getpwuid (getuid ());
99 if (result)
100 home_directory = str_dup (result->pw_dir);
101 #endif
103 return home_directory;
106 char *
107 expand_homedir (char *str)
109 char *p = str;
111 if (*p++ == '~')
112 return str_asprintf ("%s%s", get_home_dir (), p);
114 return str_dup (str);
117 gpg_error_t
118 parse_options (char **line, struct argv_s * args[], void *data)
120 char *p = *line;
121 gpg_error_t rc = 0;
123 for (; p && *p; p++)
125 while (*p == ' ')
126 p++;
128 if (!*p)
129 break;
131 if (*p == '-' && *(p + 1) == '-')
133 p += 2;
134 char opt[255] = { 0 }, value[255] =
137 char *tp;
138 unsigned len;
140 if (!*p || *p == ' ')
142 if (*p)
143 p++;
145 break;
148 for (tp = opt, len = 0; *p; p++, len++)
150 if (len + 1 == 255)
151 return GPG_ERR_LINE_TOO_LONG;
153 if (*p == ' ' || *p == '=')
155 int inquote = 0;
157 *tp = 0;
159 if (*p == '=')
161 p++;
163 for (tp = value, len = 0; *p; p++, len++)
165 if (len + 1 == 255)
166 return GPG_ERR_LINE_TOO_LONG;
168 if (*p == '\"')
170 inquote = !inquote;
171 continue;
173 else if (*p == ' ' && !inquote)
174 break;
176 *tp++ = *p;
179 *tp = 0;
182 break;
185 *tp++ = *p;
188 *tp = 0;
189 int match = 0;
191 for (int i = 0; args[i]; i++)
193 if (!strcmp (args[i]->opt, opt))
195 log_write1 ("param: name='%s' value='%s'", opt, value);
196 if (args[i]->type == OPTION_TYPE_NOARG && *value)
197 return GPG_ERR_SYNTAX;
198 else if (args[i]->type == OPTION_TYPE_ARG && !*value)
199 return GPG_ERR_SYNTAX;
201 rc = args[i]->func (data, value);
203 if (rc)
204 return rc;
206 match = 1;
207 break;
211 if (!match)
212 return GPG_ERR_UNKNOWN_OPTION;
214 if (!*p)
215 break;
217 continue;
220 break;
223 *line = p;
224 return rc;
227 char *
228 bin2hex (const unsigned char *data, size_t len)
230 size_t size = len * 2 + 1;
231 char buf[size];
232 size_t n;
234 buf[0] = 0;
236 for (n = 0; n < len; n++)
238 char c[3];
240 sprintf (c, "%02X", data[n]);
241 strcat (buf, c);
244 return str_dup (buf);
247 char *
248 plus_escape (const char *fmt, ...)
250 va_list ap;
251 char *str;
253 va_start (ap, fmt);
255 if (str_vasprintf (&str, fmt, ap) > 0)
257 char *p;
259 for (p = str; *p; p++)
261 if (*p == ' ')
262 *p = '+';
265 va_end (ap);
266 return str;
269 va_end (ap);
270 return NULL;
273 static char *
274 strip_texi (const char *str)
276 const char *p;
277 char *s = str_dup (str);
278 int c = 0;
280 if (!s)
281 return NULL;
283 for (p = str; *p; p++)
285 if (*p == '@' && *(p + 1) != '@')
287 if (!strncasecmp (p + 1, "table", 5)
288 || !strncasecmp (p + 1, "end ", 4))
290 while (*p++ != '\n');
291 p--;
292 continue;
294 else if (!strncasecmp (p + 1, "example", 7)
295 || !strncasecmp (p + 1, "end ", 4))
297 while (*p++ != '\n');
298 p--;
299 continue;
301 else if (!strncasecmp (p + 1, "sp ", 3))
303 p += 3;
305 while (*p && isdigit (*p++))
306 p++;
307 continue;
309 else if (!strncasecmp (p + 1, "item", 4))
311 p += 5;
312 while (*p && *p != '\n')
313 s[c++] = *p++;
315 continue;
317 else if (!strncasecmp (p + 1, "pxref", 5))
319 p += 6;
320 strcat (s, "see ");
321 c = strlen (s);
322 goto close;
324 else if (!strncasecmp (p + 1, "xref", 4))
326 p += 5;
327 strcat (s, "See ");
328 c = strlen (s);
329 goto close;
332 while (*p && *p != '{')
334 if (*++p == '*')
336 p++;
337 goto append;
341 close:
342 if (*p)
344 p++;
345 s[c++] = '`';
346 while (*p && *p != '}')
347 s[c++] = *p++;
349 if (*p)
350 p++;
352 s[c++] = '\'';
355 else if (*p == '@' && *(p + 1) == '@')
356 p++;
358 append:
359 if (*p)
360 s[c++] = *p;
362 s[c] = 0;
365 s[c] = 0;
366 return s;
370 char *
371 strip_texi_and_wrap (const char *str)
373 char *tmp = strip_texi (str);
374 char *help = xmalloc (strlen (tmp + 1) * 2);
375 char *p, *ph;
376 int i;
378 for (p = tmp, ph = help, i = 0; *p; p++, i++)
380 if (i == 78 || *p == '\n')
382 if (!isspace (*p))
384 char *t = ph;
385 int n = 0;
387 while (!(*--t == ' '))
388 n++;
390 *t++ = '\n';
391 i = -1;
392 p -= n;
393 while (n--)
395 *t++ = *p++;
396 i++;
399 else
401 *ph++ = '\n';
402 i = -1;
403 while (*p != '\n' && *p == ' ')
404 p++;
408 *ph++ = *p;
411 *ph = 0;
412 xfree (tmp);
413 return help;
416 void
417 free_key (void *data)
419 xfree (data);
422 gpg_error_t
423 create_thread (void *(*cb) (void *), void *data,
424 pthread_t * tid, int detached)
426 pthread_attr_t attr;
427 int n;
429 pthread_attr_init (&attr);
431 if (detached)
432 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
434 n = pthread_create (tid, &attr, cb, data);
435 pthread_attr_destroy (&attr);
436 return gpg_error_from_errno (n);
439 void
440 cleanup_mutex_cb (void *arg)
442 pthread_mutex_t *m = (pthread_mutex_t *) arg;
444 MUTEX_UNLOCK (m);
447 void
448 cleanup_fd_cb (void *arg)
450 int fd = *(int *) arg;
452 if (fd != -1)
453 close (fd);
456 void
457 cleanup_unlink_cb (void *arg)
459 char *file = arg;
461 if (file && *file)
462 unlink (file);
465 void
466 cleanup_cache_mutex (void *arg)
468 cache_unlock ();
472 valid_keygrip (const unsigned char *data, size_t len)
474 for (size_t i = 0; i < len; i++)
476 if (data[i])
477 return 1;
480 return 0;
483 gpg_error_t
484 get_checksum (const char *filename, unsigned char **r_crc, size_t * r_crclen)
486 int fd;
487 unsigned char *buf;
488 gpg_error_t rc = 0;
489 size_t len;
490 struct stat st;
492 if (stat (filename, &st) == -1)
493 return gpg_error_from_errno (errno);
495 fd = open (filename, O_RDONLY);
496 if (fd == -1)
497 return gpg_error_from_errno (errno);
499 pthread_cleanup_push (cleanup_fd_cb, &fd);
500 buf = xmalloc (st.st_size);
501 if (buf)
503 pthread_cleanup_push (xfree, buf);
505 len = read (fd, buf, st.st_size);
506 if (len == st.st_size)
508 if (buf)
510 unsigned char *crc;
512 len = gcry_md_get_algo_dlen (GCRY_MD_CRC32);
513 crc = xmalloc (len);
514 if (crc)
516 pthread_cleanup_push (xfree, crc);
517 gcry_md_hash_buffer (GCRY_MD_CRC32, crc, buf, st.st_size);
518 *r_crc = crc;
519 *r_crclen = len;
520 pthread_cleanup_pop (0);
522 else
523 rc = GPG_ERR_ENOMEM;
526 else
527 rc = GPG_ERR_TOO_SHORT;
529 pthread_cleanup_pop (1);
531 else
532 rc = GPG_ERR_ENOMEM;
534 pthread_cleanup_pop (1);
535 return rc;