• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11 
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <errno.h>
28 
29 #include <pulse/xmalloc.h>
30 
31 #include <pulsecore/i18n.h>
32 #include <pulsecore/macro.h>
33 #include <pulsecore/core-error.h>
34 #include <pulsecore/log.h>
35 #include <pulsecore/conf-parser.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/authkey.h>
38 
39 #include "client-conf.h"
40 
41 #ifdef HAVE_X11
42 #include <pulse/client-conf-x11.h>
43 #endif
44 
45 #define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "client.conf"
46 #define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf"
47 
48 #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG"
49 #define ENV_DEFAULT_SINK "PULSE_SINK"
50 #define ENV_DEFAULT_SOURCE "PULSE_SOURCE"
51 #define ENV_DEFAULT_SERVER "PULSE_SERVER"
52 #define ENV_DAEMON_BINARY "PULSE_BINARY"
53 #define ENV_COOKIE_FILE "PULSE_COOKIE"
54 
55 static const pa_client_conf default_conf = {
56     .daemon_binary = NULL,
57     .extra_arguments = NULL,
58     .default_sink = NULL,
59     .default_source = NULL,
60     .default_server = NULL,
61     .default_dbus_server = NULL,
62     .cookie_file_from_env = NULL,
63     .cookie_from_x11_valid = false,
64     .cookie_file_from_application = NULL,
65     .cookie_file_from_client_conf = NULL,
66     .autospawn = true,
67     .disable_shm = false,
68     .disable_memfd = false,
69     .shm_size = 0,
70     .auto_connect_localhost = false,
71     .auto_connect_display = false
72 };
73 
pa_client_conf_new(void)74 pa_client_conf *pa_client_conf_new(void) {
75     pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
76 
77     c->daemon_binary = pa_xstrdup(PA_BINARY);
78     c->extra_arguments = pa_xstrdup("--log-target=syslog");
79 
80     return c;
81 }
82 
pa_client_conf_free(pa_client_conf * c)83 void pa_client_conf_free(pa_client_conf *c) {
84     pa_assert(c);
85     pa_xfree(c->daemon_binary);
86     pa_xfree(c->extra_arguments);
87     pa_xfree(c->default_sink);
88     pa_xfree(c->default_source);
89     pa_xfree(c->default_server);
90     pa_xfree(c->default_dbus_server);
91     pa_xfree(c->cookie_file_from_env);
92     pa_xfree(c->cookie_file_from_application);
93     pa_xfree(c->cookie_file_from_client_conf);
94     pa_xfree(c);
95 }
96 
load_env(pa_client_conf * c)97 static void load_env(pa_client_conf *c) {
98     char *e;
99 
100     if ((e = getenv(ENV_DEFAULT_SINK))) {
101         pa_xfree(c->default_sink);
102         c->default_sink = pa_xstrdup(e);
103     }
104 
105     if ((e = getenv(ENV_DEFAULT_SOURCE))) {
106         pa_xfree(c->default_source);
107         c->default_source = pa_xstrdup(e);
108     }
109 
110     if ((e = getenv(ENV_DEFAULT_SERVER))) {
111         pa_xfree(c->default_server);
112         c->default_server = pa_xstrdup(e);
113 
114         /* We disable autospawning automatically if a specific server was set */
115         c->autospawn = false;
116     }
117 
118     if ((e = getenv(ENV_DAEMON_BINARY))) {
119         pa_xfree(c->daemon_binary);
120         c->daemon_binary = pa_xstrdup(e);
121     }
122 
123     if ((e = getenv(ENV_COOKIE_FILE)) && *e) {
124         pa_xfree(c->cookie_file_from_env);
125         c->cookie_file_from_env = pa_xstrdup(e);
126     }
127 }
128 
pa_client_conf_load(pa_client_conf * c,bool load_from_x11,bool load_from_env)129 void pa_client_conf_load(pa_client_conf *c, bool load_from_x11, bool load_from_env) {
130     FILE *f = NULL;
131     char *fn = NULL;
132 
133     /* Prepare the configuration parse table */
134     pa_config_item table[] = {
135         { "daemon-binary",          pa_config_parse_string,   &c->daemon_binary, NULL },
136         { "extra-arguments",        pa_config_parse_string,   &c->extra_arguments, NULL },
137         { "default-sink",           pa_config_parse_string,   &c->default_sink, NULL },
138         { "default-source",         pa_config_parse_string,   &c->default_source, NULL },
139         { "default-server",         pa_config_parse_string,   &c->default_server, NULL },
140         { "default-dbus-server",    pa_config_parse_string,   &c->default_dbus_server, NULL },
141         { "autospawn",              pa_config_parse_bool,     &c->autospawn, NULL },
142         { "cookie-file",            pa_config_parse_string,   &c->cookie_file_from_client_conf, NULL },
143         { "disable-shm",            pa_config_parse_bool,     &c->disable_shm, NULL },
144         { "enable-shm",             pa_config_parse_not_bool, &c->disable_shm, NULL },
145         { "enable-memfd",           pa_config_parse_not_bool, &c->disable_memfd, NULL },
146         { "shm-size-bytes",         pa_config_parse_size,     &c->shm_size, NULL },
147         { "auto-connect-localhost", pa_config_parse_bool,     &c->auto_connect_localhost, NULL },
148         { "auto-connect-display",   pa_config_parse_bool,     &c->auto_connect_display, NULL },
149         { NULL,                     NULL,                     NULL, NULL },
150     };
151 
152     f = pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn);
153     if (f) {
154         pa_config_parse(fn, f, table, NULL, true, NULL);
155         pa_xfree(fn);
156         fclose(f);
157     }
158 
159     if (load_from_x11) {
160 #ifdef HAVE_X11
161         pa_client_conf_from_x11(c);
162 #endif
163     }
164 
165     if (load_from_env)
166         load_env(c);
167 }
168 
pa_client_conf_load_cookie(pa_client_conf * c,uint8_t * cookie,size_t cookie_length)169 int pa_client_conf_load_cookie(pa_client_conf *c, uint8_t *cookie, size_t cookie_length) {
170     int r;
171     char *fallback_path;
172 
173     pa_assert(c);
174     pa_assert(cookie);
175     pa_assert(cookie_length > 0);
176 
177     if (c->cookie_file_from_env) {
178         r = pa_authkey_load(c->cookie_file_from_env, true, cookie, cookie_length);
179         if (r >= 0)
180             return 0;
181 
182         pa_log_warn("Failed to load cookie from %s (configured with environment variable PULSE_COOKIE): %s",
183                     c->cookie_file_from_env, pa_cstrerror(errno));
184     }
185 
186     if (c->cookie_from_x11_valid) {
187         if (cookie_length == sizeof(c->cookie_from_x11)) {
188             memcpy(cookie, c->cookie_from_x11, cookie_length);
189             return 0;
190         }
191 
192         pa_log_warn("Failed to load cookie from X11 root window property PULSE_COOKIE: size mismatch.");
193     }
194 
195     if (c->cookie_file_from_application) {
196         r = pa_authkey_load(c->cookie_file_from_application, true, cookie, cookie_length);
197         if (r >= 0)
198             return 0;
199 
200         pa_log_warn("Failed to load cookie from %s (configured by the application): %s", c->cookie_file_from_application,
201                     pa_cstrerror(errno));
202     }
203 
204     if (c->cookie_file_from_client_conf) {
205         r = pa_authkey_load(c->cookie_file_from_client_conf, true, cookie, cookie_length);
206         if (r >= 0)
207             return 0;
208 
209         pa_log_warn("Failed to load cookie from %s (configured in client.conf): %s", c->cookie_file_from_client_conf,
210                     pa_cstrerror(errno));
211     }
212 
213     r = pa_authkey_load(PA_NATIVE_COOKIE_FILE, false, cookie, cookie_length);
214     if (r >= 0)
215         return 0;
216 
217     if (pa_append_to_home_dir(PA_NATIVE_COOKIE_FILE_FALLBACK, &fallback_path) >= 0) {
218         r = pa_authkey_load(fallback_path, false, cookie, cookie_length);
219         pa_xfree(fallback_path);
220         if (r >= 0)
221             return 0;
222     }
223 
224     r = pa_authkey_load(PA_NATIVE_COOKIE_FILE, true, cookie, cookie_length);
225     if (r >= 0)
226         return 0;
227 
228     pa_log("Failed to load cookie file from %s: %s", PA_NATIVE_COOKIE_FILE, pa_cstrerror(errno));
229     memset(cookie, 0, cookie_length);
230 
231     return -1;
232 }
233 
pa_client_conf_set_cookie_file_from_application(pa_client_conf * c,const char * cookie_file)234 void pa_client_conf_set_cookie_file_from_application(pa_client_conf *c, const char *cookie_file) {
235     pa_assert(c);
236     pa_assert(!cookie_file || *cookie_file);
237 
238     pa_xfree(c->cookie_file_from_application);
239     c->cookie_file_from_application = pa_xstrdup(cookie_file);
240 }
241