This file is part of polypaudio.
polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
polypaudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with polypaudio; if not, write to the Free Software
+ You should have received a copy of the GNU Lesser General Public
+ License along with polypaudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#include <limits.h>
#include <unistd.h>
#include <grp.h>
+#include <netdb.h>
#include <samplerate.h>
#include "xmalloc.h"
#include "log.h"
+#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
+
/** Make a file descriptor nonblock. Doesn't do any error checking */
void pa_make_nonblock_fd(int fd) {
int v;
return -1;
}
+/* Creates a the parent directory of the specified path securely */
+int pa_make_secure_parent_dir(const char *fn) {
+ int ret = -1;
+ char *slash, *dir = pa_xstrdup(fn);
+
+ if (!(slash = strrchr(dir, '/')))
+ goto finish;
+ *slash = 0;
+
+ if (pa_make_secure_dir(dir) < 0)
+ goto finish;
+
+ ret = 0;
+
+finish:
+ pa_xfree(dir);
+ return ret;
+}
+
+
/** Calls read() in a loop. Makes sure that as much as 'size' bytes,
* unless EOF is reached or an error occured */
ssize_t pa_loop_read(int fd, void*data, size_t size) {
char *p;
assert(s && l > 0);
- if (!(p = getenv("USER")))
- if (!(p = getenv("LOGNAME")))
- if (!(p = getenv("USERNAME"))) {
-
+ if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
+
#ifdef HAVE_GETPWUID_R
- if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
+ if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
#else
- /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
- * that do not support getpwuid_r. */
- if ((r = getpwuid(getuid())) == NULL) {
+ /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
+ * that do not support getpwuid_r. */
+ if ((r = getpwuid(getuid())) == NULL) {
#endif
- snprintf(s, l, "%lu", (unsigned long) getuid());
- return s;
- }
-
- p = r->pw_name;
+ snprintf(s, l, "%lu", (unsigned long) getuid());
+ return s;
}
+
+ p = r->pw_name;
+ }
return pa_strlcpy(s, p, l);
-}
+ }
/* Return the current hostname in the specified buffer. */
char *pa_get_host_name(char *s, size_t l) {
assert(s && l > 0);
- gethostname(s, l);
+ if (gethostname(s, l) < 0) {
+ pa_log(__FILE__": gethostname(): %s\n", strerror(errno));
+ return NULL;
+ }
s[l-1] = 0;
return s;
}
if ((e = getenv("HOME")))
return pa_strlcpy(s, e, l);
- if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r)
+ if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
+ pa_log(__FILE__": getpwuid_r() failed\n");
return NULL;
+ }
return pa_strlcpy(s, r->pw_dir, l);
}
const char *current = *state ? *state : c;
size_t l;
- if (!*current)
+ if (!*current || *c == 0)
return NULL;
current += strspn(current, WHITESPACE);
return fopen(global, "r");
}
+/* Format the specified data as a hexademical string */
+char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
+ size_t i = 0, j = 0;
+ const char hex[] = "0123456789abcdef";
+ assert(d && s && slength > 0);
+
+ while (i < dlength && j+3 <= slength) {
+ s[j++] = hex[*d >> 4];
+ s[j++] = hex[*d & 0xF];
+
+ d++;
+ i++;
+ }
+
+ s[j < slength ? j : slength] = 0;
+ return s;
+}
+
+/* Convert a hexadecimal digit to a number or -1 if invalid */
+static int hexc(char c) {
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+
+ return -1;
+}
+
+/* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
+size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
+ size_t j = 0;
+ assert(p && d);
+
+ while (j < dlength && *p) {
+ int b;
+
+ if ((b = hexc(*(p++))) < 0)
+ return (size_t) -1;
+
+ d[j] = (uint8_t) (b << 4);
+
+ if (!*p)
+ return (size_t) -1;
+
+ if ((b = hexc(*(p++))) < 0)
+ return (size_t) -1;
+
+ d[j] |= (uint8_t) b;
+ j++;
+ }
+
+ return j;
+}
+
+/* Return the fully qualified domain name in *s */
+char *pa_get_fqdn(char *s, size_t l) {
+ char hn[256];
+ struct addrinfo *a, hints;
+
+ if (!pa_get_host_name(hn, sizeof(hn)))
+ return NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+
+ if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname)
+ return pa_strlcpy(s, hn, l);
+
+ pa_strlcpy(s, a->ai_canonname, l);
+ freeaddrinfo(a);
+ return s;
+}
+
+/* Returns nonzero when *s starts with *pfx */
+int pa_startswith(const char *s, const char *pfx) {
+ size_t l;
+ assert(s && pfx);
+ l = strlen(pfx);
+
+ return strlen(s) >= l && strncmp(s, pfx, l) == 0;
+}
+
+/* if fn is null return the polypaudio run time path in s (/tmp/polypaudio)
+ * if fn is non-null and starts with / return fn in s
+ * otherwise append fn to the run time path and return it in s */
+char *pa_runtime_path(const char *fn, char *s, size_t l) {
+ char u[256];
+
+ if (fn && *fn == '/')
+ return pa_strlcpy(s, fn, l);
+
+ snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : "");
+ return s;
+}