2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
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/>.
28 #include <sys/types.h>
35 #include "pwmd-error.h"
37 #include "util-misc.h"
38 #include "util-string.h"
43 extern void log_write (const char *fmt
, ...);
46 valid_filename (const char *filename
)
50 if (!filename
|| !*filename
)
53 if (filename
[0] == '-' && filename
[1] == 0)
56 for (p
= filename
; *p
; p
++)
58 if (*p
== '/' || isspace (*p
))
65 /* If 'user' is null then lookup entry for 'uid'. Caller must free 'buf'. */
67 get_pwd_struct (const char *user
, uid_t uid
, struct passwd
*pw
, char **buf
,
70 struct passwd
*result
;
71 #ifdef HAVE_GETPWNAM_R
75 len
= sysconf (_SC_GETPW_R_SIZE_MAX
);
85 err
= getpwnam_r (user
, pw
, *buf
, len
, &result
);
91 err
= getpwuid_r (uid
, pw
, *buf
, len
, &result
);
97 *rc
= gpg_error_from_errno (err
);
105 result
= getpwnam (user
);
107 result
= getpwuid (uid
);
110 *rc
= gpg_error_from_syserror ();
117 get_pwd_entry(uid_t uid
, int which
)
122 struct passwd
*result
= get_pwd_struct (NULL
, uid
, &pw
, &buf
, &rc
);
131 value
= str_dup (result
->pw_dir
);
133 value
= str_dup (result
->pw_name
);
141 get_username (uid_t uid
)
143 return get_pwd_entry (uid
, 1);
150 return home_directory
;
152 home_directory
= get_pwd_entry (getuid(), 0);
153 return home_directory
;
157 expand_homedir (char *str
)
163 char *dir
= get_pwd_entry(getuid(), 0);
169 s
= str_asprintf ("%s%s", dir
, p
);
174 return str_dup (str
);
177 /* The 'more' parameter lets the calling command process remaining
178 * non-option arguments. */
180 parse_options (char **line
, struct argv_s
* args
[], void *data
, int more
)
193 if (*p
== '-' && *(p
+ 1) == '-')
196 char opt
[255] = { 0 }, value
[255] =
202 if (!*p
|| *p
== ' ')
210 for (tp
= opt
, len
= 0; *p
; p
++, len
++)
213 return GPG_ERR_LINE_TOO_LONG
;
215 if (*p
== ' ' || *p
== '=')
225 for (tp
= value
, len
= 0; *p
; p
++, len
++)
228 return GPG_ERR_LINE_TOO_LONG
;
235 else if (*p
== ' ' && !inquote
)
253 for (int i
= 0; args
[i
]; i
++)
255 if (!strcmp (args
[i
]->opt
, opt
))
257 log_write1 ("param: name='%s' value='%s'", opt
, value
);
258 if (args
[i
]->type
== OPTION_TYPE_NOARG
&& *value
)
259 return GPG_ERR_SYNTAX
;
260 else if (args
[i
]->type
== OPTION_TYPE_ARG
&& !*value
)
261 return GPG_ERR_SYNTAX
;
263 rc
= args
[i
]->func (data
, value
);
274 return GPG_ERR_UNKNOWN_OPTION
;
283 return GPG_ERR_SYNTAX
;
293 bin2hex (const unsigned char *data
, size_t len
)
295 size_t size
= len
* 2 + 1;
301 for (n
= 0; n
< len
; n
++)
305 sprintf (c
, "%02X", data
[n
]);
309 return str_dup (buf
);
313 plus_escape (const char *fmt
, ...)
320 if (str_vasprintf (&str
, fmt
, ap
) > 0)
324 for (p
= str
; *p
; p
++)
339 strip_texi (const char *str
)
342 char *s
= str_dup (str
);
348 for (p
= str
; *p
; p
++)
350 if (*p
== '@' && *(p
+ 1) != '@')
352 if (!strncasecmp (p
+ 1, "table", 5)
353 || !strncasecmp (p
+ 1, "end ", 4))
355 while (*p
++ != '\n');
359 else if (!strncasecmp (p
+ 1, "example", 7)
360 || !strncasecmp (p
+ 1, "end ", 4))
362 while (*p
++ != '\n');
366 else if (!strncasecmp (p
+ 1, "sp ", 3))
370 while (*p
&& isdigit (*p
++))
374 else if (!strncasecmp (p
+ 1, "item", 4))
377 while (*p
&& *p
!= '\n')
383 else if (!strncasecmp (p
+ 1, "pxref", 5))
390 else if (!strncasecmp (p
+ 1, "xref", 4))
398 while (*p
&& *p
!= '{')
412 while (*p
&& *p
!= '}')
421 else if (*p
== '@' && *(p
+ 1) == '@')
437 strip_texi_and_wrap (const char *str
)
439 char *tmp
= strip_texi (str
);
440 char *help
= xmalloc (strlen (tmp
) * 2 + 1);
444 for (p
= tmp
, ph
= help
, i
= 0; *p
; p
++, i
++)
446 if (i
== 78 || *p
== '\n')
453 while (!(*--t
== ' '))
469 while (*p
!= '\n' && *p
== ' ')
483 free_key (void *data
)
489 create_thread (void *(*cb
) (void *), void *data
,
490 pthread_t
* tid
, int detached
)
495 pthread_attr_init (&attr
);
498 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
500 n
= pthread_create (tid
, &attr
, cb
, data
);
501 pthread_attr_destroy (&attr
);
502 return gpg_error_from_errno (n
);
506 cleanup_mutex_cb (void *arg
)
508 pthread_mutex_t
*m
= (pthread_mutex_t
*) arg
;
514 cleanup_fd_cb (void *arg
)
516 int fd
= *(int *) arg
;
523 cleanup_unlink_cb (void *arg
)
532 cleanup_cache_mutex (void *arg
)
538 valid_keygrip (const unsigned char *data
, size_t len
)
540 for (size_t i
= 0; i
< len
; i
++)
549 /* The advisory lock should be obtained before calling this function. */
551 get_checksum (const char *filename
, unsigned char **r_crc
, size_t * r_crclen
)
558 if (stat (filename
, &st
) == -1)
559 return gpg_error_from_errno (errno
);
561 fd
= open (filename
, O_RDONLY
);
563 return gpg_error_from_errno (errno
);
565 pthread_cleanup_push (cleanup_fd_cb
, &fd
);
566 buf
= xmalloc (st
.st_size
);
569 pthread_cleanup_push (xfree
, buf
);
571 size_t len
= read (fd
, buf
, st
.st_size
);
572 if (len
== st
.st_size
)
578 len
= gcry_md_get_algo_dlen (GCRY_MD_CRC32
);
582 pthread_cleanup_push (xfree
, crc
);
583 gcry_md_hash_buffer (GCRY_MD_CRC32
, crc
, buf
, st
.st_size
);
586 pthread_cleanup_pop (0);
593 rc
= GPG_ERR_TOO_SHORT
;
595 pthread_cleanup_pop (1);
600 pthread_cleanup_pop (1);
604 wchar_t *str_to_wchar (const char *str
)
611 memset (&ps
, 0, sizeof(mbstate_t));
612 len
= mbsrtowcs (NULL
, &p
, 0, &ps
);
616 wc
= xcalloc (len
+1, sizeof(wchar_t));
618 memset (&ps
, 0, sizeof(mbstate_t));
619 len
= mbsrtowcs (wc
, &p
, len
, &ps
);