1267
static char *get_pulse_home(void) {
1271
if (!pa_get_home_dir(h, sizeof(h))) {
1272
pa_log_error("Failed to get home directory.");
1276
if (stat(h, &st) < 0) {
1277
pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1281
if (st.st_uid != getuid()) {
1282
pa_log_error("Home directory %s not ours.", h);
1287
return pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1290
char *pa_get_state_dir(void) {
1293
/* The state directory shall contain dynamic data that should be
1294
* kept across reboots, and is private to this user */
1296
if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1297
if (!(d = get_pulse_home()))
1300
/* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1301
* dir then this will break. */
1303
if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1304
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1312
static char* make_random_dir(mode_t m) {
1313
static const char table[] =
1314
"abcdefghijklmnopqrstuvwxyz"
1315
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1322
if (!(tmpdir = getenv("TMPDIR")))
1323
if (!(tmpdir = getenv("TMP")))
1324
if (!(tmpdir = getenv("TEMP")))
1325
tmpdir = getenv("TEMPDIR");
1327
if (!tmpdir || !pa_is_path_absolute(tmpdir))
1330
fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
1331
pathlen = strlen(fn);
1339
for (i = pathlen - 12; i < pathlen; i++)
1340
fn[i] = table[rand() % (sizeof(table)-1)];
1342
u = umask((~m) & 0777);
1345
saved_errno = errno;
1347
errno = saved_errno;
1352
if (errno != EEXIST) {
1353
pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1360
static int make_random_dir_and_link(mode_t m, const char *k) {
1363
if (!(p = make_random_dir(m)))
1366
if (symlink(p, k) < 0) {
1367
int saved_errno = errno;
1369
if (errno != EEXIST)
1370
pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1375
errno = saved_errno;
1382
char *pa_get_runtime_dir(void) {
1383
char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1387
/* The runtime directory shall contain dynamic data that needs NOT
1388
* to be kept accross reboots and is usuallly private to the user,
1389
* except in system mode, where it might be accessible by other
1390
* users, too. Since we need POSIX locking and UNIX sockets in
1391
* this directory, we link it to a random subdir in /tmp, if it
1392
* was not explicitly configured. */
1394
m = pa_in_system_mode() ? 0755U : 0700U;
1396
if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1398
if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1399
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1403
return pa_xstrdup(d);
1406
if (!(d = get_pulse_home()))
1409
if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1410
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1414
if (!(mid = pa_machine_id())) {
1419
k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid);
1424
/* OK, first let's check if the "runtime" symlink is already
1427
if (!(p = pa_readlink(k))) {
1429
if (errno != ENOENT) {
1430
pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1434
/* Hmm, so the runtime directory didn't exist yet, so let's
1435
* create one in /tmp and symlink that to it */
1437
if (make_random_dir_and_link(0700, k) < 0) {
1439
/* Mhmm, maybe another process was quicker than us,
1440
* let's check if that was valid */
1441
if (errno == EEXIST)
1450
/* Make sure that this actually makes sense */
1451
if (!pa_is_path_absolute(p)) {
1452
pa_log_error("Path %s in link %s is not absolute.", p, k);
1457
/* Hmm, so this symlink is still around, make sure nobody fools
1460
if (lstat(p, &st) < 0) {
1462
if (errno != ENOENT) {
1463
pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1469
if (S_ISDIR(st.st_mode) &&
1470
(st.st_uid == getuid()) &&
1471
((st.st_mode & 0777) == 0700)) {
1477
pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1483
/* Hmm, so the link points to some nonexisting or invalid
1484
* dir. Let's replace it by a new link. We first create a
1485
* temporary link and then rename that to allow concurrent
1486
* execution of this function. */
1488
t = pa_sprintf_malloc("%s.tmp", k);
1490
if (make_random_dir_and_link(0700, t) < 0) {
1492
if (errno != EEXIST) {
1493
pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1500
/* Hmm, someone lese was quicker then us. Let's give
1501
* him some time to finish, and retry. */
1506
/* OK, we succeeded in creating the temporary symlink, so
1507
* let's rename it */
1508
if (rename(t, k) < 0) {
1509
pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1096
1525
/* Try to open a configuration file. If "env" is specified, open the
1097
1526
* value of the specified environment variable. Otherwise look for a
1098
1527
* file "local" in the home directory or a file "global" in global
1099
1528
* file system. If "result" is non-NULL, a pointer to a newly
1100
1529
* allocated buffer containing the used configuration file is
1101
1530
* stored there.*/
1102
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result, const char *mode) {
1109
if (!getenv(PULSE_ROOTENV))
1113
if (env && (fn = getenv(env))) {
1115
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1121
*result = pa_xstrdup(fn);
1123
return fopen(fn, mode);
1130
if ((e = getenv("PULSE_CONFIG_PATH")))
1131
fn = lfn = pa_sprintf_malloc("%s/%s", e, local);
1132
else if (pa_get_home_dir(h, sizeof(h))) {
1135
d = pa_sprintf_malloc("%s/.pulse", h);
1139
fn = lfn = pa_sprintf_malloc("%s/.pulse/%s", h, local);
1146
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
1151
f = fopen(fn, mode);
1154
*result = pa_xstrdup(fn);
1159
if (errno != ENOENT)
1160
pa_log_warn("Failed to open configuration file '%s': %s", lfn, pa_cstrerror(errno));
1174
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1180
*result = pa_xstrdup(global);
1182
return fopen(global, mode);
1531
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1536
if (!getenv(PULSE_ROOTENV))
1540
if (env && (fn = getenv(env))) {
1544
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1545
/* FIXME: Needs to set errno! */
1550
if ((f = fopen(fn, "r"))) {
1552
*result = pa_xstrdup(fn);
1557
pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1567
if ((e = getenv("PULSE_CONFIG_PATH")))
1568
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1569
else if (pa_get_home_dir(h, sizeof(h)))
1570
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1575
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1576
/* FIXME: Needs to set errno! */
1583
if ((f = fopen(fn, "r"))) {
1585
*result = pa_xstrdup(fn);
1591
if (errno != ENOENT) {
1592
pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1604
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1605
/* FIXME: Needs to set errno! */
1610
if ((f = fopen(global, "r"))) {
1613
*result = pa_xstrdup(global);
1623
char *pa_find_config_file(const char *global, const char *local, const char *env) {
1628
if (!getenv(PULSE_ROOTENV))
1632
if (env && (fn = getenv(env))) {
1635
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1636
/* FIXME: Needs to set errno! */
1641
if (access(fn, R_OK) == 0)
1642
return pa_xstrdup(fn);
1644
pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1653
if ((e = getenv("PULSE_CONFIG_PATH")))
1654
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1655
else if (pa_get_home_dir(h, sizeof(h)))
1656
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1661
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1662
/* FIXME: Needs to set errno! */
1669
if (access(fn, R_OK) == 0) {
1670
char *r = pa_xstrdup(fn);
1675
if (errno != ENOENT) {
1676
pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1686
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1687
/* FIXME: Needs to set errno! */
1692
if (access(global, R_OK) == 0)
1693
return pa_xstrdup(global);
1185
1701
/* Format the specified data as a hexademical string */
1270
1787
return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1273
/* if fn is null return the PulseAudio run time path in s (/tmp/pulse)
1274
* if fn is non-null and starts with / return fn in s
1275
* otherwise append fn to the run time path and return it in s */
1276
char *pa_runtime_path(const char *fn, char *s, size_t l) {
1790
pa_bool_t pa_is_path_absolute(const char *fn) {
1279
1793
#ifndef OS_IS_WIN32
1280
if (fn && *fn == '/')
1282
if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
1284
return pa_strlcpy(s, fn, l);
1286
if ((e = getenv("PULSE_RUNTIME_PATH"))) {
1289
pa_snprintf(s, l, "%s%c%s", e, PA_PATH_SEP_CHAR, fn);
1291
pa_snprintf(s, l, "%s", e);
1297
pa_snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PA_PATH_SEP_CHAR, fn);
1299
pa_snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
1307
ExpandEnvironmentStrings(buf, s, l);
1796
return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1800
char *pa_make_path_absolute(const char *p) {
1806
if (pa_is_path_absolute(p))
1807
return pa_xstrdup(p);
1809
if (!(cwd = pa_getcwd()))
1810
return pa_xstrdup(p);
1812
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1817
/* if fn is null return the PulseAudio run time path in s (~/.pulse)
1818
* if fn is non-null and starts with / return fn
1819
* otherwise append fn to the run time path and return it */
1820
static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1823
if (pa_is_path_absolute(fn))
1824
return pa_xstrdup(fn);
1826
rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1837
if (!(mid = pa_machine_id())) {
1842
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn);
1845
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1853
char *pa_runtime_path(const char *fn) {
1854
return get_path(fn, FALSE, TRUE);
1857
char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1858
return get_path(fn, appendmid, FALSE);
1314
1861
/* Convert the string s to a signed integer in *ret_i */
2139
int pa_close_all(int except_fd, ...) {
2144
va_start(ap, except_fd);
2147
for (n = 1; va_arg(ap, int) >= 0; n++)
2152
p = pa_xnew(int, n+1);
2154
va_start(ap, except_fd);
2157
if (except_fd >= 0) {
2161
while ((fd = va_arg(ap, int)) >= 0)
2168
r = pa_close_allv(p);
2174
int pa_close_allv(const int except_fds[]) {
2183
if ((d = opendir("/proc/self/fd"))) {
2187
while ((de = readdir(d))) {
2193
if (de->d_name[0] == '.')
2197
l = strtol(de->d_name, &e, 10);
2198
if (errno != 0 || !e || *e) {
2206
if ((long) fd != l) {
2219
for (i = 0; except_fds[i] >= 0; i++)
2220
if (except_fds[i] == fd) {
2228
if (pa_close(fd) < 0) {
2229
saved_errno = errno;
2231
errno = saved_errno;
2243
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
2246
for (fd = 3; fd < (int) rl.rlim_max; fd++) {
2251
for (i = 0; except_fds[i] >= 0; i++)
2252
if (except_fds[i] == fd) {
2260
if (pa_close(fd) < 0 && errno != EBADF)
2267
int pa_unblock_sigs(int except, ...) {
2272
va_start(ap, except);
2275
for (n = 1; va_arg(ap, int) >= 0; n++)
2280
p = pa_xnew(int, n+1);
2282
va_start(ap, except);
2289
while ((sig = va_arg(ap, int)) >= 0)
2296
r = pa_unblock_sigsv(p);
2302
int pa_unblock_sigsv(const int except[]) {
2306
if (sigemptyset(&ss) < 0)
2309
for (i = 0; except[i] > 0; i++)
2310
if (sigaddset(&ss, except[i]) < 0)
2313
return sigprocmask(SIG_SETMASK, &ss, NULL);
2316
int pa_reset_sigs(int except, ...) {
2321
va_start(ap, except);
2324
for (n = 1; va_arg(ap, int) >= 0; n++)
2329
p = pa_xnew(int, n+1);
2331
va_start(ap, except);
2338
while ((sig = va_arg(ap, int)) >= 0)
2345
r = pa_reset_sigsv(p);
2351
int pa_reset_sigsv(const int except[]) {
2354
for (sig = 1; sig < NSIG; sig++) {
2355
pa_bool_t reset = TRUE;
2366
for (i = 0; except[i] > 0; i++) {
2367
if (sig == except[i]) {
2376
struct sigaction sa;
2378
memset(&sa, 0, sizeof(sa));
2379
sa.sa_handler = SIG_DFL;
2381
/* On Linux the first two RT signals are reserved by
2382
* glibc, and sigaction() will return EINVAL for them. */
2383
if ((sigaction(sig, &sa, NULL) < 0))
2384
if (errno != EINVAL)
2392
void pa_set_env(const char *key, const char *value) {
2396
putenv(pa_sprintf_malloc("%s=%s", key, value));
2399
pa_bool_t pa_in_system_mode(void) {
2402
if (!(e = getenv("PULSE_SYSTEM")))
2408
char *pa_machine_id(void) {
2412
/* The returned value is supposed be some kind of ascii identifier
2413
* that is unique and stable across reboots. */
2415
/* First we try the D-Bus UUID, which is the best option we have,
2416
* since it fits perfectly our needs and is not as volatile as the
2417
* hostname which might be set from dhcp. */
2419
if ((f = fopen(PA_MACHINE_ID, "r"))) {
2420
char ln[34] = "", *r;
2422
r = fgets(ln, sizeof(ln)-1, f);
2428
return pa_xstrdup(ln);
2431
/* The we fall back to the host name. It supposed to be somewhat
2432
* unique, at least in a network, but may change. */
2440
if (!pa_get_host_name(c, l)) {
2442
if (errno != EINVAL && errno != ENAMETOOLONG)
2445
} else if (strlen(c) < l-1) {
2455
/* Hmm, the hostname is as long the space we offered the
2456
* function, we cannot know if it fully fit in, so let's play
2457
* safe and retry. */
2463
/* If no hostname was set we use the POSIX hostid. It's usually
2464
* the IPv4 address. Mit not be that stable. */
2465
return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2468
char *pa_uname_string(void) {
2471
pa_assert_se(uname(&u) == 0);
2473
return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2476
#ifdef HAVE_VALGRIND_MEMCHECK_H
2477
pa_bool_t pa_in_valgrind(void) {
2480
/* To make heisenbugs a bit simpler to find we check for $VALGRIND
2481
* here instead of really checking whether we run in valgrind or
2485
b = getenv("VALGRIND") ? 2 : 1;