Version 8.2.1.
[libpwmd.git] / src / misc.c
bloba638204b7a39e2bf9b019bb46904bb77a4a57923
1 /*
2 Copyright (C) 2006-2018 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>
38 #include <fcntl.h>
40 #ifndef LINE_MAX
41 #define LINE_MAX 2048
42 #endif
44 #include <libpwmd.h>
45 #include "misc.h"
47 #ifndef __MINGW32__
48 #ifdef HAVE_GETPWUID_R
49 char *
50 _expand_homedir (char *str, struct passwd *pw)
52 char *p = str;
53 char *pwbuf = NULL;
54 char *result;
55 struct passwd t;
57 if (!p)
58 return NULL;
60 if (*p != '~' || *(p + 1) != '/')
61 return pwmd_strdup (p);
63 if (!pw)
65 pwbuf = _getpwuid (&t);
66 if (!pwbuf)
67 return NULL;
69 pw = &t;
72 p += 2;
73 result = pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
74 pwmd_free (pwbuf);
75 return result;
78 char *
79 _getpwuid (struct passwd *pwd)
81 size_t size = sysconf (_SC_GETPW_R_SIZE_MAX);
82 struct passwd *result;
83 char *buf;
84 int n;
86 if (size == -1)
87 size = 16384;
89 buf = pwmd_malloc (size);
90 if (!buf)
91 return NULL;
93 n = getpwuid_r (getuid (), pwd, buf, size, &result);
94 if (n)
96 pwmd_free (buf);
97 errno = n;
98 return NULL;
101 if (!result)
103 pwmd_free (buf);
104 return NULL;
107 errno = n;
108 return buf;
110 #else
111 char *
112 _expand_homedir (char *str, struct passwd *pw)
114 char *p = str;
116 if (!p)
117 return NULL;
119 if (*p != '~' || *(p + 1) != '/')
120 return pwmd_strdup (p);
122 if (!pw)
124 pw = getpwuid (getuid ());
125 if (!pw)
126 return NULL;
129 p += 2;
130 return pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
133 char *
134 _getpwuid (struct passwd *pwd)
136 struct passwd *pw = getpwuid (getuid ());
138 if (!pw)
139 return NULL;
141 *pwd = *pw;
142 return pwmd_strdup ("");
144 #endif
145 #endif
148 * Borrowed from libassuan.
150 char *
151 _percent_escape (const char *atext)
153 const unsigned char *s;
154 int len;
155 char *buf, *p;
157 if (!atext)
158 return NULL;
160 len = strlen (atext) * 3 + 1;
161 buf = (char *) pwmd_malloc (len);
163 if (!buf)
164 return NULL;
166 p = buf;
168 for (s = (const unsigned char *) atext; *s; s++)
170 if (*s < ' ')
172 sprintf (p, "%%%02X", *s);
173 p += 3;
175 else
176 *p++ = *s;
179 *p = 0;
180 return buf;
183 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
184 * port specification.
186 gpg_error_t
187 parse_hostname_common (const char *str, char **host, int *port)
189 const char *p = str;
190 char *t = NULL;
192 /* IPv6 with optional port. */
193 if (*p == '[')
195 p++;
196 t = strchr (p, ']');
198 else
200 int n = 0;
201 const char *x;
203 /* Handle IPv6 without proper braces around the IP. */
204 for (x = p; *x; x++)
206 if (*x == ':')
207 n++;
210 if (n <= 1)
211 t = strchr (p, ':');
214 if (t)
216 size_t len = strlen (p) - strlen (t) + 1;
218 *host = pwmd_malloc (len);
219 if (!*host)
220 return gpg_error_from_errno (ENOMEM);
222 snprintf (*host, len, "%s", p);
223 t++;
225 if (*t == ':')
226 t++;
228 if (*t)
229 *port = strtol (t, NULL, 10);
231 if (*t == '-')
232 t++;
234 while (*t && isdigit (*t))
235 t++;
237 else
239 *host = pwmd_strdup (str);
240 if (!*host)
241 return gpg_error_from_errno (ENOMEM);
244 return 0;
247 char *
248 bin2hex (const unsigned char *data, size_t len)
250 size_t size = len * 2 + 1;
251 char buf[size]; // C99
252 size_t n;
254 buf[0] = 0;
256 for (n = 0; n < len; n++)
258 char c[3];
260 sprintf (c, "%02X", data[n]);
261 strcat (buf, c);
264 return pwmd_strdup (buf);
267 gpg_error_t
268 set_non_blocking (assuan_fd_t fd, int n)
270 #ifdef __MINGW32__
271 unsigned long opt = !!n;
273 if (ioctlsocket (HANDLE2SOCKET (fd), FIONBIO, &opt) != NO_ERROR)
274 return gpg_error_from_syserror ();
275 #else
276 int flags = fcntl (fd, F_GETFL);
278 if (!n)
279 flags &= ~O_NONBLOCK;
280 else
281 flags |= O_NONBLOCK;
283 if (fcntl (fd, F_SETFL, flags) == -1)
284 return gpg_error_from_syserror ();
285 #endif
287 return 0;