1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
29 #include <sys/types.h>
33 #include <glib/gprintf.h>
37 #include "pwmd-error.h"
44 extern void log_write(const gchar
*fmt
, ...);
46 gboolean
strv_printf(gchar
***array
, const gchar
*fmt
, ...)
51 gint len
= *array
? g_strv_length(*array
) : 0;
57 if ((a
= g_realloc(*array
, (len
+ 2) * sizeof(gchar
*))) == NULL
) {
58 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
63 ret
= g_vasprintf(&buf
, fmt
, ap
);
67 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
77 gchar
**strvcatv(gchar
**dst
, gchar
**src
)
93 for (p
= src
; *p
; p
++) {
96 pa
= g_realloc(d
, (i
+ 2) * sizeof(gchar
*));
117 gboolean
valid_filename(const gchar
*filename
)
121 if (!filename
|| !*filename
)
124 if (!g_strcmp0(filename
, "-"))
127 for (p
= filename
; *p
; p
++) {
128 if (*p
== '/' || isspace(*p
))
135 gchar
*print_fmt(gchar
*buf
, gsize len
, const char *fmt
, ...)
140 g_vsnprintf(buf
, len
, fmt
, ap
);
145 gchar
*expand_homedir(gchar
*str
)
150 return g_strdup_printf("%s%s", g_get_home_dir(), p
);
152 return g_strdup(str
);
155 gchar
**split_input_line(gchar
*str
, gchar
*delim
, gint n
)
160 return g_strsplit(str
, delim
, n
);
163 gpg_error_t
parse_options(gchar
**line
, struct argv_s
*args
[], gpointer data
)
168 for (; p
&& *p
; p
++) {
169 while (g_ascii_isspace(*p
))
175 if (*p
== '-' && *(p
+1) == '-') {
177 gchar opt
[255] = {0}, value
[255] = {0};
181 if (!*p
|| *p
== ' ') {
188 for (tp
= opt
, len
= 0; *p
; p
++, len
++) {
190 return GPG_ERR_LINE_TOO_LONG
;
192 if (*p
== ' ' || *p
== '=') {
193 gboolean inquote
= FALSE
;
200 for (tp
= value
, len
= 0; *p
; p
++, len
++) {
202 return GPG_ERR_LINE_TOO_LONG
;
208 else if (*p
== ' ' && !inquote
)
224 gboolean match
= FALSE
;
226 for (int i
= 0; args
[i
]; i
++) {
227 if (!g_strcmp0(args
[i
]->opt
, opt
)) {
228 log_write1("param: name='%s' value='%s'", opt
, value
);
229 if (args
[i
]->type
== OPTION_TYPE_NOARG
&& *value
)
230 return GPG_ERR_SYNTAX
;
231 else if (args
[i
]->type
== OPTION_TYPE_ARG
&& !*value
)
232 return GPG_ERR_SYNTAX
;
234 rc
= args
[i
]->func(data
, value
);
245 return GPG_ERR_UNKNOWN_OPTION
;
260 gchar
*bin2hex(const guchar
*data
, gsize len
)
262 gsize size
= len
*2+1;
268 for (n
= 0; n
< len
; n
++) {
271 g_sprintf(c
, "%02X", data
[n
]);
272 g_strlcat(buf
, c
, size
);
275 return g_strdup(buf
);
278 gchar
*plus_escape(const gchar
*fmt
, ...)
284 if (g_vasprintf(&str
, fmt
, ap
) > 0) {
287 for (p
= str
; *p
; p
++) {
300 static gchar
*strip_texi(const gchar
*str
)
303 gchar
*s
= g_strdup(str
);
304 gsize len
= strlen(s
);
310 for (p
= str
; *p
; p
++) {
311 if (*p
== '@' && *(p
+1) != '@') {
312 if (!g_ascii_strncasecmp(p
+1, "table", 5)
313 || !g_ascii_strncasecmp(p
+1, "end ", 4)) {
314 while (*p
++ != '\n');
318 else if (!g_ascii_strncasecmp(p
+1, "example", 7)
319 || !g_ascii_strncasecmp(p
+1, "end ", 4)) {
320 while (*p
++ != '\n');
324 else if (!g_ascii_strncasecmp(p
+1, "sp ", 3)) {
327 while (*p
&& isdigit(*p
++))
331 else if (!g_ascii_strncasecmp(p
+1, "item", 4)) {
333 while (*p
&& *p
!= '\n')
338 else if (!g_ascii_strncasecmp(p
+1, "pxref", 5)) {
340 c
= g_strlcat(s
, "see ", len
);
343 else if (!g_ascii_strncasecmp(p
+1, "xref", 4)) {
345 c
= g_strlcat(s
, "See ", len
);
349 while (*p
&& *p
!= '{') {
360 while (*p
&& *p
!= '}')
369 else if (*p
== '@' && *(p
+1) == '@')
384 gchar
*strip_texi_and_wrap(const gchar
*str
)
386 gchar
*tmp
= strip_texi(str
);
387 gchar
*help
= g_malloc(strlen(tmp
+1)*2);
391 for (p
= tmp
, ph
= help
, i
= 0; *p
; p
++, i
++) {
392 if (i
== 79 || *p
== '\n') {
393 if (!g_ascii_isspace(*p
)) {
397 while (!g_ascii_isspace(*--t
))
411 while (*p
!= '\n' && g_ascii_isspace(*p
))
424 void free_key(void *data
)
429 gpg_error_t
create_thread(void *(*cb
)(void *), void *data
,
430 pthread_t
*tid
, gboolean detached
)
435 pthread_attr_init(&attr
);
438 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
440 n
= pthread_create(tid
, &attr
, cb
, data
);
441 pthread_attr_destroy(&attr
);
442 return gpg_error_from_errno(n
);
445 void cleanup_mutex_cb(void *arg
)
447 pthread_mutex_t
*m
= (pthread_mutex_t
*)arg
;
452 void cleanup_fd_cb(void *arg
)
454 gint fd
= *(gint
*)arg
;
460 void cleanup_unlink_cb(void *arg
)
468 void cleanup_cache_mutex(void *arg
)
473 gboolean
valid_keygrip(const guchar
*data
, gsize len
)
475 for (gsize i
= 0; i
< len
; i
++) {
483 gpg_error_t
get_checksum(const gchar
*filename
, guchar
**r_crc
, gsize
*r_crclen
)
491 if (stat(filename
, &st
) == -1)
492 return gpg_error_from_syserror();
494 fd
= open(filename
, O_RDONLY
);
496 return gpg_error_from_syserror();
498 pthread_cleanup_push(cleanup_fd_cb
, &fd
);
499 buf
= g_malloc(st
.st_size
);
501 pthread_cleanup_push(g_free
, buf
);
503 len
= read(fd
, buf
, st
.st_size
);
504 if (len
== st
.st_size
) {
508 len
= gcry_md_get_algo_dlen(GCRY_MD_CRC32
);
511 pthread_cleanup_push(g_free
, crc
);
512 gcry_md_hash_buffer(GCRY_MD_CRC32
, crc
, buf
, st
.st_size
);
515 pthread_cleanup_pop(0);
522 rc
= GPG_ERR_TOO_SHORT
;
524 pthread_cleanup_pop(1);
529 pthread_cleanup_pop(1);