diff options
Diffstat (limited to 'src/pulse/context.c')
-rw-r--r-- | src/pulse/context.c | 153 |
1 files changed, 54 insertions, 99 deletions
diff --git a/src/pulse/context.c b/src/pulse/context.c index f9f021af..f56cb241 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -1,5 +1,3 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. @@ -70,6 +68,7 @@ #include <pulsecore/socket-util.h> #include <pulsecore/creds.h> #include <pulsecore/macro.h> +#include <pulsecore/proplist-util.h> #include "internal.h" @@ -103,7 +102,9 @@ static void unlock_autospawn_lock_file(pa_context *c) { if (c->autospawn_lock_fd >= 0) { char *lf; - lf = pa_runtime_path(AUTOSPAWN_LOCK); + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) + pa_log_warn("Cannot unlock autospawn because runtime path is no more."); + pa_unlock_lockfile(lf, c->autospawn_lock_fd); pa_xfree(lf); @@ -167,6 +168,7 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * c->autospawn_lock_fd = -1; memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = FALSE; + c->do_shm = FALSE; #ifndef MSG_NOSIGNAL #ifdef SIGPIPE @@ -175,10 +177,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * #endif c->conf = pa_client_conf_new(); - pa_client_conf_load(c->conf, NULL); #ifdef HAVE_X11 pa_client_conf_from_x11(c->conf, NULL); #endif + pa_client_conf_load(c->conf, NULL); pa_client_conf_env(c->conf); if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) { @@ -422,6 +424,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; + pa_bool_t shm_on_remote; if (pa_tagstruct_getu32(t, &c->version) < 0 || !pa_tagstruct_eof(t)) { @@ -435,10 +438,22 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t goto finish; } + /* Starting with protocol version 13 the MSB of the version + tag reflects if shm is available for this connection or + not. */ + if (c->version >= 13) { + shm_on_remote = !!(c->version & 0x80000000U); + c->version &= 0x7FFFFFFFU; + } + + pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); + /* Enable shared memory support if possible */ - if (c->version >= 10 && - pa_mempool_is_shared(c->mempool) && - c->is_local) { + if (c->do_shm) + if (c->version < 10 || (c->version >= 13 && !shm_on_remote)) + c->do_shm = FALSE; + + if (c->do_shm) { /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise @@ -446,12 +461,14 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t #ifdef HAVE_CREDS const pa_creds *creds; - if ((creds = pa_pdispatch_creds(pd))) - if (getuid() == creds->uid) - pa_pstream_enable_shm(c->pstream, TRUE); + if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid) + c->do_shm = FALSE; #endif } + pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm)); + pa_pstream_enable_shm(c->pstream, c->do_shm); + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); if (c->version >= 13) { @@ -510,7 +527,16 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_log_info("No cookie loaded. Attempting to connect without."); t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); - pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); + + c->do_shm = + pa_mempool_is_shared(c->mempool) && + c->is_local; + + pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm)); + + /* Starting with protocol version 13 we use the MSB of the version + * tag for informing the other side if we could do SHM or not */ + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0)); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); #ifdef HAVE_CREDS @@ -621,6 +647,7 @@ static int context_connect_spawn(pa_context *c) { /* Parent */ pa_assert_se(pa_close(fds[1]) == 0); + fds[1] = -1; r = waitpid(pid, &status, 0); @@ -749,11 +776,15 @@ static char *get_legacy_runtime_dir(void) { p = pa_sprintf_malloc("/tmp/pulse-%s", u); - if (stat(p, &st) < 0) + if (stat(p, &st) < 0) { + pa_xfree(p); return NULL; + } - if (st.st_uid != getuid()) + if (st.st_uid != getuid()) { + pa_xfree(p); return NULL; + } return p; } @@ -809,7 +840,7 @@ int pa_context_connect( /* The system wide instance */ c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET); - /* The old per-user instance path. This is supported only to easy upgrades */ + /* The old per-user instance path. This is supported only to ease upgrades */ if ((legacy_dir = get_legacy_runtime_dir())) { char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); c->server_list = pa_strlist_prepend(c->server_list, p); @@ -818,14 +849,20 @@ int pa_context_connect( } /* The per-user instance */ - c->server_list = pa_strlist_prepend(c->server_list, ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET)); - pa_xfree(ufn); + if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { + c->server_list = pa_strlist_prepend(c->server_list, ufn); + pa_xfree(ufn); + } /* Wrap the connection attempts in a single transaction for sane autospawn locking */ if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { char *lf; - lf = pa_runtime_path(AUTOSPAWN_LOCK); + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) { + pa_context_fail(c, PA_ERR_ACCESS); + goto finish; + } + pa_assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); pa_xfree(lf); @@ -1193,85 +1230,3 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[] return o; } - -void pa_init_proplist(pa_proplist *p) { - int a, b; -#ifndef HAVE_DECL_ENVIRON - extern char **environ; -#endif - char **e; - - pa_assert(p); - - for (e = environ; *e; e++) { - - if (pa_startswith(*e, "PULSE_PROP_")) { - size_t kl = strcspn(*e+11, "="); - char *k; - - if ((*e)[11+kl] != '=') - continue; - - if (!pa_utf8_valid(*e+11+kl+1)) - continue; - - k = pa_xstrndup(*e+11, kl); - - if (pa_proplist_contains(p, k)) { - pa_xfree(k); - continue; - } - - pa_proplist_sets(p, k, *e+11+kl+1); - pa_xfree(k); - } - } - - if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) { - char t[32]; - pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid()); - pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t); - } - - if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) { - char t[64]; - if (pa_get_user_name(t, sizeof(t))) { - char *c = pa_utf8_filter(t); - pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, c); - pa_xfree(c); - } - } - - if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) { - char t[64]; - if (pa_get_host_name(t, sizeof(t))) { - char *c = pa_utf8_filter(t); - pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, c); - pa_xfree(c); - } - } - - a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY); - b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME); - - if (!a || !b) { - char t[PATH_MAX]; - if (pa_get_binary_name(t, sizeof(t))) { - char *c = pa_utf8_filter(t); - - if (!a) - pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c); - if (!b) - pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c); - - pa_xfree(c); - } - } - - if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) { - const char *l; - - if ((l = setlocale(LC_MESSAGES, NULL))) - pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l); - } -} |