Version 3.0.12.
[pwmd.git] / src / util-misc.c
blob1c7541b552470102f670419975d4e71d97fb3ef7
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
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 static char *
66 get_pwd_entry(uid_t uid, int which)
68 struct passwd *result;
69 #ifdef HAVE_GETPWNAM_R
70 struct passwd pw;
71 size_t len;
72 char *buf;
73 char *value = NULL;
75 len = sysconf (_SC_GETPW_R_SIZE_MAX);
76 if (len == -1)
77 len = 16384;
79 buf = xmalloc (len);
80 if (!buf)
81 return NULL;
83 if (!getpwuid_r (uid, &pw, buf, len, &result))
84 #else
85 result = getpwuid (uid);
86 #endif
87 if (result)
89 if (!which)
90 value = str_dup (result->pw_dir);
91 else
92 value = str_dup (result->pw_name);
95 #ifdef HAVE_GETPWNAM_R
96 xfree (buf);
97 #endif
98 return value;
101 char *
102 get_username (uid_t uid)
104 return get_pwd_entry (uid, 1);
107 char *
108 get_home_dir ()
110 if (home_directory)
111 return home_directory;
113 home_directory = get_pwd_entry (getuid(), 0);
114 return home_directory;
117 char *
118 expand_homedir (char *str)
120 char *p = str;
122 if (*p++ == '~')
124 char *dir = get_pwd_entry(getuid(), 0);
125 char *s = str_asprintf ("%s%s", dir, p);
127 xfree (dir);
128 return s;
131 return str_dup (str);
134 gpg_error_t
135 parse_options (char **line, struct argv_s * args[], void *data)
137 char *p = *line;
138 gpg_error_t rc = 0;
140 for (; p && *p; p++)
142 while (*p == ' ')
143 p++;
145 if (!*p)
146 break;
148 if (*p == '-' && *(p + 1) == '-')
150 p += 2;
151 char opt[255] = { 0 }, value[255] =
154 char *tp;
155 unsigned len;
157 if (!*p || *p == ' ')
159 if (*p)
160 p++;
162 break;
165 for (tp = opt, len = 0; *p; p++, len++)
167 if (len + 1 == 255)
168 return GPG_ERR_LINE_TOO_LONG;
170 if (*p == ' ' || *p == '=')
172 *tp = 0;
174 if (*p == '=')
176 int inquote = 0;
178 p++;
180 for (tp = value, len = 0; *p; p++, len++)
182 if (len + 1 == 255)
183 return GPG_ERR_LINE_TOO_LONG;
185 if (*p == '\"')
187 inquote = !inquote;
188 continue;
190 else if (*p == ' ' && !inquote)
191 break;
193 *tp++ = *p;
196 *tp = 0;
199 break;
202 *tp++ = *p;
205 *tp = 0;
206 int match = 0;
208 for (int i = 0; args[i]; i++)
210 if (!strcmp (args[i]->opt, opt))
212 log_write1 ("param: name='%s' value='%s'", opt, value);
213 if (args[i]->type == OPTION_TYPE_NOARG && *value)
214 return GPG_ERR_SYNTAX;
215 else if (args[i]->type == OPTION_TYPE_ARG && !*value)
216 return GPG_ERR_SYNTAX;
218 rc = args[i]->func (data, value);
220 if (rc)
221 return rc;
223 match = 1;
224 break;
228 if (!match)
229 return GPG_ERR_UNKNOWN_OPTION;
231 if (!*p)
232 break;
234 continue;
237 break;
240 *line = p;
241 return rc;
244 char *
245 bin2hex (const unsigned char *data, size_t len)
247 size_t size = len * 2 + 1;
248 char buf[size];
249 size_t n;
251 buf[0] = 0;
253 for (n = 0; n < len; n++)
255 char c[3];
257 sprintf (c, "%02X", data[n]);
258 strcat (buf, c);
261 return str_dup (buf);
264 char *
265 plus_escape (const char *fmt, ...)
267 va_list ap;
268 char *str;
270 va_start (ap, fmt);
272 if (str_vasprintf (&str, fmt, ap) > 0)
274 char *p;
276 for (p = str; *p; p++)
278 if (*p == ' ')
279 *p = '+';
282 va_end (ap);
283 return str;
286 va_end (ap);
287 return NULL;
290 static char *
291 strip_texi (const char *str)
293 const char *p;
294 char *s = str_dup (str);
295 int c = 0;
297 if (!s)
298 return NULL;
300 for (p = str; *p; p++)
302 if (*p == '@' && *(p + 1) != '@')
304 if (!strncasecmp (p + 1, "table", 5)
305 || !strncasecmp (p + 1, "end ", 4))
307 while (*p++ != '\n');
308 p--;
309 continue;
311 else if (!strncasecmp (p + 1, "example", 7)
312 || !strncasecmp (p + 1, "end ", 4))
314 while (*p++ != '\n');
315 p--;
316 continue;
318 else if (!strncasecmp (p + 1, "sp ", 3))
320 p += 3;
322 while (*p && isdigit (*p++))
323 p++;
324 continue;
326 else if (!strncasecmp (p + 1, "item", 4))
328 p += 5;
329 while (*p && *p != '\n')
330 s[c++] = *p++;
332 continue;
334 else if (!strncasecmp (p + 1, "pxref", 5))
336 p += 6;
337 strcat (s, "see ");
338 c = strlen (s);
339 goto close;
341 else if (!strncasecmp (p + 1, "xref", 4))
343 p += 5;
344 strcat (s, "See ");
345 c = strlen (s);
346 goto close;
349 while (*p && *p != '{')
351 if (*++p == '*')
353 p++;
354 goto append;
358 close:
359 if (*p)
361 p++;
362 s[c++] = '`';
363 while (*p && *p != '}')
364 s[c++] = *p++;
366 if (*p)
367 p++;
369 s[c++] = '\'';
372 else if (*p == '@' && *(p + 1) == '@')
373 p++;
375 append:
376 if (*p)
377 s[c++] = *p;
379 s[c] = 0;
382 s[c] = 0;
383 return s;
387 char *
388 strip_texi_and_wrap (const char *str)
390 char *tmp = strip_texi (str);
391 char *help = xmalloc (strlen (tmp + 1) * 2);
392 char *p, *ph;
393 int i;
395 for (p = tmp, ph = help, i = 0; *p; p++, i++)
397 if (i == 78 || *p == '\n')
399 if (!isspace (*p))
401 char *t = ph;
402 int n = 0;
404 while (!(*--t == ' '))
405 n++;
407 *t++ = '\n';
408 i = -1;
409 p -= n;
410 while (n--)
412 *t++ = *p++;
413 i++;
416 else
418 *ph++ = '\n';
419 i = -1;
420 while (*p != '\n' && *p == ' ')
421 p++;
425 *ph++ = *p;
428 *ph = 0;
429 xfree (tmp);
430 return help;
433 void
434 free_key (void *data)
436 xfree (data);
439 gpg_error_t
440 create_thread (void *(*cb) (void *), void *data,
441 pthread_t * tid, int detached)
443 pthread_attr_t attr;
444 int n;
446 pthread_attr_init (&attr);
448 if (detached)
449 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
451 n = pthread_create (tid, &attr, cb, data);
452 pthread_attr_destroy (&attr);
453 return gpg_error_from_errno (n);
456 void
457 cleanup_mutex_cb (void *arg)
459 pthread_mutex_t *m = (pthread_mutex_t *) arg;
461 MUTEX_UNLOCK (m);
464 void
465 cleanup_fd_cb (void *arg)
467 int fd = *(int *) arg;
469 if (fd != -1)
470 close (fd);
473 void
474 cleanup_unlink_cb (void *arg)
476 char *file = arg;
478 if (file && *file)
479 unlink (file);
482 void
483 cleanup_cache_mutex (void *arg)
485 cache_unlock ();
489 valid_keygrip (const unsigned char *data, size_t len)
491 for (size_t i = 0; i < len; i++)
493 if (data[i])
494 return 1;
497 return 0;
500 gpg_error_t
501 get_checksum (const char *filename, unsigned char **r_crc, size_t * r_crclen)
503 int fd;
504 unsigned char *buf;
505 gpg_error_t rc = 0;
506 struct stat st;
508 if (stat (filename, &st) == -1)
509 return gpg_error_from_errno (errno);
511 fd = open (filename, O_RDONLY);
512 if (fd == -1)
513 return gpg_error_from_errno (errno);
515 pthread_cleanup_push (cleanup_fd_cb, &fd);
516 buf = xmalloc (st.st_size);
517 if (buf)
519 pthread_cleanup_push (xfree, buf);
521 size_t len = read (fd, buf, st.st_size);
522 if (len == st.st_size)
524 if (buf)
526 unsigned char *crc;
528 len = gcry_md_get_algo_dlen (GCRY_MD_CRC32);
529 crc = xmalloc (len);
530 if (crc)
532 pthread_cleanup_push (xfree, crc);
533 gcry_md_hash_buffer (GCRY_MD_CRC32, crc, buf, st.st_size);
534 *r_crc = crc;
535 *r_crclen = len;
536 pthread_cleanup_pop (0);
538 else
539 rc = GPG_ERR_ENOMEM;
542 else
543 rc = GPG_ERR_TOO_SHORT;
545 pthread_cleanup_pop (1);
547 else
548 rc = GPG_ERR_ENOMEM;
550 pthread_cleanup_pop (1);
551 return rc;
554 wchar_t *str_to_wchar (const char *str)
556 wchar_t *wc;
557 mbstate_t ps;
558 const char *p = str;
559 size_t len;
561 memset (&ps, 0, sizeof(mbstate_t));
562 len = mbsrtowcs (NULL, &p, 0, &ps);
563 if (len == -1)
564 return NULL;
566 wc = xcalloc (len+1, sizeof(wchar_t));
567 p = str;
568 memset (&ps, 0, sizeof(mbstate_t));
569 len = mbsrtowcs (wc, &p, len, &ps);
570 return wc;