pwmc: Reset filename upon .open failure.
[libpwmd.git] / src / misc.c
blob0f70bbb58b0723916722c6528ac58fe9a089094e
1 /*
2 Copyright (C) 2006-2016 Ben Kibbey <bjk@luxsci.net>
4 This file is part of libpwmd.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #ifdef HAVE_LIMITS_H
26 #include <limits.h>
27 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <ctype.h>
39 #ifndef LINE_MAX
40 #define LINE_MAX 2048
41 #endif
43 #include <libpwmd.h>
44 #include "misc.h"
46 #ifdef HAVE_GETPWUID_R
47 char *
48 _expand_homedir (char *str, struct passwd *pw)
50 char *p = str;
51 char *pwbuf = NULL;
52 char *result;
53 struct passwd t;
55 if (!p)
56 return NULL;
58 if (*p != '~' || *(p + 1) != '/')
59 return pwmd_strdup (p);
61 if (!pw)
63 pwbuf = _getpwuid (&t);
64 if (!pwbuf)
65 return NULL;
67 pw = &t;
70 p += 2;
71 result = pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
72 pwmd_free (pwbuf);
73 return result;
76 char *
77 _getpwuid (struct passwd *pwd)
79 size_t size = sysconf (_SC_GETPW_R_SIZE_MAX);
80 struct passwd *result;
81 char *buf;
82 int n;
84 if (size == -1)
85 size = 16384;
87 buf = pwmd_malloc (size);
88 if (!buf)
89 return NULL;
91 n = getpwuid_r (getuid (), pwd, buf, size, &result);
92 if (n)
94 pwmd_free (buf);
95 errno = n;
96 return NULL;
99 if (!result)
101 pwmd_free (buf);
102 return NULL;
105 errno = n;
106 return buf;
108 #else
109 char *
110 _expand_homedir (char *str, struct passwd *pw)
112 char *p = str;
114 if (!p)
115 return NULL;
117 if (*p != '~' || *(p + 1) != '/')
118 return pwmd_strdup (p);
120 if (!pw)
122 pw = getpwuid (getuid ());
123 if (!pw)
124 return NULL;
127 p += 2;
128 return pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
131 char *
132 _getpwuid (struct passwd *pwd)
134 struct passwd *pw = getpwuid (getuid ());
136 if (!pw)
137 return NULL;
139 *pwd = *pw;
140 return pwmd_strdup ("");
142 #endif
145 * Borrowed from libassuan.
147 char *
148 _percent_escape (const char *atext)
150 const unsigned char *s;
151 int len;
152 char *buf, *p;
154 if (!atext)
155 return NULL;
157 len = strlen (atext) * 3 + 1;
158 buf = (char *) pwmd_malloc (len);
160 if (!buf)
161 return NULL;
163 p = buf;
165 for (s = (const unsigned char *) atext; *s; s++)
167 if (*s < ' ')
169 sprintf (p, "%%%02X", *s);
170 p += 3;
172 else
173 *p++ = *s;
176 *p = 0;
177 return buf;
180 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
181 * port specification.
183 gpg_error_t
184 parse_hostname_common (const char *str, char **host, int *port)
186 const char *p = str;
187 char *t = NULL;
189 /* IPv6 with optional port. */
190 if (*p == '[')
192 p++;
193 t = strchr (p, ']');
195 else
197 int n = 0;
198 const char *x;
200 /* Handle IPv6 without proper braces around the IP. */
201 for (x = p; *x; x++)
203 if (*x == ':')
204 n++;
207 if (n <= 1)
208 t = strchr (p, ':');
211 if (t)
213 size_t len = strlen (p) - strlen (t) + 1;
215 *host = pwmd_malloc (len);
216 if (!*host)
217 return gpg_error_from_errno (ENOMEM);
219 snprintf (*host, len, "%s", p);
220 t++;
222 if (*t == ':')
223 t++;
225 if (*t)
226 *port = strtol (t, NULL, 10);
228 if (*t == '-')
229 t++;
231 while (*t && isdigit (*t))
232 t++;
234 p = t;
236 else
238 *host = pwmd_strdup (str);
239 if (!*host)
240 return gpg_error_from_errno (ENOMEM);
243 return 0;
246 char *
247 bin2hex (const unsigned char *data, size_t len)
249 size_t size = len * 2 + 1;
250 char buf[size]; // C99
251 size_t n;
253 buf[0] = 0;
255 for (n = 0; n < len; n++)
257 char c[3];
259 sprintf (c, "%02X", data[n]);
260 strcat (buf, c);
263 return pwmd_strdup (buf);