contrib: Add helper to build Android dependencies.
[libpwmd.git] / src / misc.c
blob98d4b942b551bbf5f92637570bae252b50dad50c
1 /*
2 Copyright (C) 2006-2023 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 version 2.1 as published by the Free Software Foundation.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 USA
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #ifdef HAVE_LIMITS_H
29 #include <limits.h>
30 #endif
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #ifdef HAVE_FCNTL_H
38 #include <fcntl.h>
39 #endif
41 #ifndef LINE_MAX
42 #define LINE_MAX 2048
43 #endif
45 #include <libpwmd.h>
46 #include "misc.h"
48 #ifndef __MINGW32__
49 #ifdef HAVE_GETPWUID_R
50 char *
51 _expand_homedir (char *str, struct passwd *pw)
53 char *p = str;
54 char *pwbuf = NULL;
55 char *result;
56 struct passwd t;
58 if (!p)
59 return NULL;
61 if (*p != '~' || *(p + 1) != '/')
62 return pwmd_strdup (p);
64 if (!pw)
66 pwbuf = _getpwuid (&t);
67 if (!pwbuf)
68 return NULL;
70 pw = &t;
73 p += 2;
74 result = pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
75 pwmd_free (pwbuf);
76 return result;
79 char *
80 _getpwuid (struct passwd *pwd)
82 size_t size = sysconf (_SC_GETPW_R_SIZE_MAX);
83 struct passwd *result;
84 char *buf;
85 int n;
87 if (size == -1)
88 size = 16384;
90 buf = pwmd_malloc (size);
91 if (!buf)
92 return NULL;
94 n = getpwuid_r (getuid (), pwd, buf, size, &result);
95 if (n)
97 pwmd_free (buf);
98 errno = n;
99 return NULL;
102 if (!result)
104 pwmd_free (buf);
105 return NULL;
108 errno = n;
109 return buf;
111 #else
112 char *
113 _expand_homedir (char *str, struct passwd *pw)
115 char *p = str;
117 if (!p)
118 return NULL;
120 if (*p != '~' || *(p + 1) != '/')
121 return pwmd_strdup (p);
123 if (!pw)
125 pw = getpwuid (getuid ());
126 if (!pw)
127 return NULL;
130 p += 2;
131 return pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
134 char *
135 _getpwuid (struct passwd *pwd)
137 struct passwd *pw = getpwuid (getuid ());
139 if (!pw)
140 return NULL;
142 *pwd = *pw;
143 return pwmd_strdup ("");
145 #endif
146 #endif
149 * Borrowed from libassuan.
151 char *
152 _percent_escape (const char *atext)
154 const unsigned char *s;
155 int len;
156 char *buf, *p;
158 if (!atext)
159 return NULL;
161 len = strlen (atext) * 3 + 1;
162 buf = (char *) pwmd_malloc (len);
164 if (!buf)
165 return NULL;
167 p = buf;
169 for (s = (const unsigned char *) atext; *s; s++)
171 if (*s < ' ')
173 sprintf (p, "%%%02X", *s);
174 p += 3;
176 else
177 *p++ = *s;
180 *p = 0;
181 return buf;
184 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
185 * port specification.
187 gpg_error_t
188 parse_hostname_common (const char *str, char **host, int *port)
190 const char *p = str;
191 char *t = NULL;
193 /* IPv6 with optional port. */
194 if (*p == '[')
196 p++;
197 t = strchr (p, ']');
199 else
201 int n = 0;
202 const char *x;
204 /* Handle IPv6 without proper braces around the IP. */
205 for (x = p; *x; x++)
207 if (*x == ':')
208 n++;
211 if (n <= 1)
212 t = strchr (p, ':');
215 if (t)
217 size_t len = strlen (p) - strlen (t) + 1;
219 *host = pwmd_malloc (len);
220 if (!*host)
221 return gpg_error_from_errno (ENOMEM);
223 snprintf (*host, len, "%s", p);
224 t++;
226 if (*t == ':')
227 t++;
229 if (*t)
230 *port = strtol (t, NULL, 10);
232 if (*t == '-')
233 t++;
235 while (*t && isdigit (*t))
236 t++;
238 else
240 *host = pwmd_strdup (str);
241 if (!*host)
242 return gpg_error_from_errno (ENOMEM);
245 return 0;
248 char *
249 bin2hex (const unsigned char *data, size_t len)
251 size_t size = len * 2 + 1;
252 char buf[size]; // C99
253 size_t n;
255 buf[0] = 0;
257 for (n = 0; n < len; n++)
259 char c[3];
261 sprintf (c, "%02X", data[n]);
262 strcat (buf, c);
265 return pwmd_strdup (buf);
268 gpg_error_t
269 set_non_blocking (assuan_fd_t fd, int n)
271 #ifdef __MINGW32__
272 unsigned long opt = !!n;
274 if (ioctlsocket (HANDLE2SOCKET (fd), FIONBIO, &opt) != NO_ERROR)
275 return gpg_error_from_syserror ();
276 #else
277 int flags = fcntl (fd, F_GETFL);
279 if (!n)
280 flags &= ~O_NONBLOCK;
281 else
282 flags |= O_NONBLOCK;
284 if (fcntl (fd, F_SETFL, flags) == -1)
285 return gpg_error_from_syserror ();
286 #endif
288 return 0;