• 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 <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <signal.h>
31 #include <stddef.h>
32 #include <ltdl.h>
33 #include <limits.h>
34 #include <unistd.h>
35 #include <locale.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 
39 #ifdef HAVE_SYS_MMAN_H
40 #include <sys/mman.h>
41 #endif
42 
43 #ifdef HAVE_PWD_H
44 #include <pwd.h>
45 #endif
46 #ifdef HAVE_GRP_H
47 #include <grp.h>
48 #endif
49 
50 #ifdef HAVE_LIBWRAP
51 #include <syslog.h>
52 #include <tcpd.h>
53 #endif
54 
55 #ifdef HAVE_DBUS
56 #include <dbus/dbus.h>
57 #endif
58 
59 #ifdef HAVE_SYSTEMD_DAEMON
60 #include <systemd/sd-daemon.h>
61 #endif
62 
63 #ifdef HAVE_WINDOWS_H
64 #include <windows.h>
65 #include <aclapi.h>
66 #include <sddl.h>
67 #endif
68 
69 #include <pulse/client-conf.h>
70 #include <pulse/mainloop.h>
71 #include <pulse/mainloop-signal.h>
72 #include <pulse/timeval.h>
73 #include <pulse/xmalloc.h>
74 
75 #include <pulsecore/i18n.h>
76 #include <pulsecore/lock-autospawn.h>
77 #include <pulsecore/socket.h>
78 #include <pulsecore/core-error.h>
79 #include <pulsecore/core-rtclock.h>
80 #include <pulsecore/core-scache.h>
81 #include <pulsecore/core.h>
82 #include <pulsecore/module.h>
83 #include <pulsecore/cli-command.h>
84 #include <pulsecore/log.h>
85 #include <pulsecore/core-util.h>
86 #include <pulsecore/sioman.h>
87 #include <pulsecore/cli-text.h>
88 #include <pulsecore/pid.h>
89 #include <pulsecore/random.h>
90 #include <pulsecore/macro.h>
91 #include <pulsecore/shm.h>
92 #include <pulsecore/memtrap.h>
93 #include <pulsecore/strlist.h>
94 #ifdef HAVE_DBUS
95 #include <pulsecore/dbus-shared.h>
96 #endif
97 #include <pulsecore/cpu.h>
98 
99 #include "cmdline.h"
100 #include "cpulimit.h"
101 #include "daemon-conf.h"
102 #include "dumpmodules.h"
103 #include "caps.h"
104 #include "ltdl-bind-now.h"
105 #include "server-lookup.h"
106 
107 #ifdef __cplusplus
108 #if __cplusplus
109 extern "C" {
110 #endif
111 #endif /* End of #ifdef __cplusplus */
112 #ifdef DISABLE_LIBTOOL_PRELOAD
113 /* FIXME: work around a libtool bug by making sure we have 2 elements. Bug has
114  * been reported: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29576 */
115 LT_DLSYM_CONST lt_dlsymlist lt_preloaded_symbols[] = {
116     { "@PROGRAM@", NULL },
117     { NULL, NULL }
118 };
119 #endif
120 
121 #ifdef HAVE_LIBWRAP
122 /* Only one instance of these variables */
123 int allow_severity = LOG_INFO;
124 int deny_severity = LOG_WARNING;
125 #endif
126 
127 #ifdef HAVE_OSS_WRAPPER
128 /* padsp looks for this symbol in the running process and disables
129  * itself if it finds it and it is set to 7 (which is actually a bit
130  * mask). For details see padsp. */
131 int __padsp_disabled__ = 7;
132 #endif
133 
signal_callback(pa_mainloop_api * m,pa_signal_event * e,int sig,void * userdata)134 static void signal_callback(pa_mainloop_api* m, pa_signal_event *e, int sig, void *userdata) {
135     pa_module *module = NULL;
136 
137     pa_log_info("Got signal %s.", pa_sig2str(sig));
138 
139     switch (sig) {
140 #ifdef SIGUSR1
141         case SIGUSR1:
142             pa_module_load(&module, userdata, "module-cli", NULL);
143             break;
144 #endif
145 
146 #ifdef SIGUSR2
147         case SIGUSR2:
148             pa_module_load(&module, userdata, "module-cli-protocol-unix", NULL);
149             break;
150 #endif
151 
152 #ifdef SIGHUP
153         case SIGHUP: {
154             char *c = pa_full_status_string(userdata);
155             pa_log_notice("%s", c);
156             pa_xfree(c);
157             return;
158         }
159 #endif
160 
161         case SIGINT:
162         case SIGTERM:
163         default:
164             pa_log_info("Do nothing.");
165             break;
166     }
167 }
168 
169 #if defined(OS_IS_WIN32)
170 
change_user(void)171 static int change_user(void) {
172     pa_log_info("Overriding system runtime/config base dir to '%s'.", pa_win32_get_system_appdata());
173 
174     /* On other platforms, these paths are compiled into PulseAudio. This isn't
175      * suitable on Windows. Firstly, Windows doesn't follow the FHS or use Unix
176      * paths and the build system can't handle Windows-style paths properly.
177      * Secondly, the idiomatic location for a service's state and shared data is
178      * ProgramData, and the location of special folders is dynamic on Windows.
179      * Also, this method of handling paths is consistent with how they are
180      * handled on Windows in other parts of PA. Note that this is only needed
181      * in system-wide mode since paths in user instances are already handled
182      * properly.
183      */
184 
185     char *run_path = pa_sprintf_malloc("%s" PA_PATH_SEP "run", pa_win32_get_system_appdata());
186     char *lib_path = pa_sprintf_malloc("%s" PA_PATH_SEP "lib", pa_win32_get_system_appdata());
187 
188     /* https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings */
189     /* https://docs.microsoft.com/en-us/windows/win32/secauthz/modifying-the-acls-of-an-object-in-c-- */
190     /* https://docs.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertstringsecuritydescriptortosecuritydescriptora */
191     {
192         mkdir(run_path);
193         PSECURITY_DESCRIPTOR sd;
194         if (ConvertStringSecurityDescriptorToSecurityDescriptorA(
195             "D:PAI"                   /* DACL, disable inheritance from parent, enable propagation to children */
196             "(A;OICI;FA;;;SY)"        /* give system full access */
197             "(A;OICI;FA;;;CO)"        /* give owner full access */
198             "(A;OICI;FA;;;BA)"        /* give administrators full access */
199             "(A;OICI;0x1200a9;;;WD)", /* give everyone read/write/execute access */
200             SDDL_REVISION_1, &sd, NULL
201         )) {
202             PACL acl;
203             BOOL acl_present, acl_default;
204             if (GetSecurityDescriptorDacl(sd, &acl_present, &acl, &acl_default)) {
205                 if (SetNamedSecurityInfo(run_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) != ERROR_SUCCESS) {
206                     pa_log_warn("Failed to set DACL for runtime dir: failed to apply DACL: error %lu.", GetLastError());
207                 }
208                 LocalFree(acl);
209             } else {
210                 pa_log_warn("Failed to set DACL for runtime dir: failed to get security descriptor DACL: error %lu.", GetLastError());
211             }
212         } else {
213             pa_log_warn("Failed to set DACL for runtime dir: failed to parse security descriptor: error %lu.", GetLastError());
214         }
215     }
216     {
217         mkdir(lib_path);
218         PSECURITY_DESCRIPTOR sd;
219         if (ConvertStringSecurityDescriptorToSecurityDescriptorA(
220             "D:PAI"             /* DACL, disable inheritance from parent, enable propagation to children */
221             "(A;OICI;FA;;;SY)"  /* give system full access */
222             "(A;OICI;FA;;;CO)"  /* give owner full access */
223             "(A;OICI;FA;;;BA)", /* give administrators full access */
224             SDDL_REVISION_1, &sd, NULL
225         )) {
226             PACL acl;
227             BOOL acl_present, acl_default;
228             if (GetSecurityDescriptorDacl(sd, &acl_present, &acl, &acl_default)) {
229                 if (SetNamedSecurityInfo(lib_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) != ERROR_SUCCESS) {
230                     pa_log_warn("Failed to set DACL for lib dir: failed to apply DACL: error %lu.", GetLastError());
231                 }
232                 LocalFree(acl);
233             } else {
234                 pa_log_warn("Failed to set DACL for lib dir: failed to get security descriptor DACL: error %lu.", GetLastError());
235             }
236         } else {
237             pa_log_warn("Failed to set DACL for lib dir: failed to parse security descriptor: error %lu.", GetLastError());
238         }
239     }
240 
241     pa_set_env("HOME", run_path);
242     if (!getenv("PULSE_RUNTIME_PATH"))
243         pa_set_env("PULSE_RUNTIME_PATH", run_path);
244     if (!getenv("PULSE_CONFIG_PATH"))
245         pa_set_env("PULSE_CONFIG_PATH", lib_path);
246     if (!getenv("PULSE_STATE_PATH"))
247         pa_set_env("PULSE_STATE_PATH", lib_path);
248 
249     pa_xfree(run_path);
250     pa_xfree(lib_path);
251 
252     pa_log_info("Not changing user for system instance on Windows.");
253     return 0;
254 }
255 
256 #elif defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
257 
change_user(void)258 static int change_user(void) {
259     struct passwd *pw;
260     struct group * gr;
261     int r;
262 
263     /* This function is called only in system-wide mode. It creates a
264      * runtime dir in /var/run/ with proper UID/GID and drops privs
265      * afterwards. */
266 
267     if (!(pw = getpwnam(PA_SYSTEM_USER))) {
268         pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
269         return -1;
270     }
271 
272     if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
273         pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
274         return -1;
275     }
276 
277     pa_log_info("Found user '%s' (UID %lu) and group '%s' (GID %lu).",
278                 PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
279                 PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
280 
281     if (pw->pw_gid != gr->gr_gid) {
282         pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
283         return -1;
284     }
285 
286     if (!pa_streq(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH))
287         pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
288 
289     if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid, true) < 0) {
290         pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
291         return -1;
292     }
293 
294     if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid, true) < 0) {
295         pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
296         return -1;
297     }
298 
299     /* We don't create the config dir here, because we don't need to write to it */
300 
301     if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
302         pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
303         return -1;
304     }
305 
306 #if defined(HAVE_SETRESGID)
307     r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
308 #elif defined(HAVE_SETEGID)
309     if ((r = setgid(gr->gr_gid)) >= 0)
310         r = setegid(gr->gr_gid);
311 #elif defined(HAVE_SETREGID)
312     r = setregid(gr->gr_gid, gr->gr_gid);
313 #else
314 #error "No API to drop privileges"
315 #endif
316 
317     if (r < 0) {
318         pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
319         return -1;
320     }
321 
322 #if defined(HAVE_SETRESUID)
323     r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
324 #elif defined(HAVE_SETEUID)
325     if ((r = setuid(pw->pw_uid)) >= 0)
326         r = seteuid(pw->pw_uid);
327 #elif defined(HAVE_SETREUID)
328     r = setreuid(pw->pw_uid, pw->pw_uid);
329 #else
330 #error "No API to drop privileges"
331 #endif
332 
333     if (r < 0) {
334         pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
335         return -1;
336     }
337 
338     pa_drop_caps();
339 
340     pa_set_env("USER", PA_SYSTEM_USER);
341     pa_set_env("USERNAME", PA_SYSTEM_USER);
342     pa_set_env("LOGNAME", PA_SYSTEM_USER);
343     pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
344 
345     /* Relevant for pa_runtime_path() */
346     if (!getenv("PULSE_RUNTIME_PATH"))
347         pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
348 
349     if (!getenv("PULSE_CONFIG_PATH"))
350         pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
351 
352     if (!getenv("PULSE_STATE_PATH"))
353         pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
354 
355     pa_log_info("Successfully changed user to \"" PA_SYSTEM_USER "\".");
356 
357     return 0;
358 }
359 
360 #else /* HAVE_PWD_H && HAVE_GRP_H */
361 
change_user(void)362 static int change_user(void) {
363     pa_log(_("System wide mode unsupported on this platform."));
364     return -1;
365 }
366 
367 #endif /* HAVE_PWD_H && HAVE_GRP_H */
368 
369 #ifdef HAVE_SYS_RESOURCE_H
370 
set_one_rlimit(const pa_rlimit * r,int resource,const char * name)371 static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
372     struct rlimit rl;
373     pa_assert(r);
374 
375     if (!r->is_set)
376         return 0;
377 
378     rl.rlim_cur = rl.rlim_max = r->value;
379 
380     if (setrlimit(resource, &rl) < 0) {
381         pa_log_info("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
382         return -1;
383     }
384 
385     return 0;
386 }
387 
set_all_rlimits(const pa_daemon_conf * conf)388 static void set_all_rlimits(const pa_daemon_conf *conf) {
389     set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE");
390     set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
391     set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK");
392     set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
393 #ifdef RLIMIT_RSS
394     set_one_rlimit(&conf->rlimit_rss, RLIMIT_RSS, "RLIMIT_RSS");
395 #endif
396 #ifdef RLIMIT_NPROC
397     set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC");
398 #endif
399 #ifdef RLIMIT_NOFILE
400     set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
401 #endif
402 #ifdef RLIMIT_MEMLOCK
403     set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK");
404 #endif
405 #ifdef RLIMIT_AS
406     set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
407 #endif
408 #ifdef RLIMIT_LOCKS
409     set_one_rlimit(&conf->rlimit_locks, RLIMIT_LOCKS, "RLIMIT_LOCKS");
410 #endif
411 #ifdef RLIMIT_SIGPENDING
412     set_one_rlimit(&conf->rlimit_sigpending, RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING");
413 #endif
414 #ifdef RLIMIT_MSGQUEUE
415     set_one_rlimit(&conf->rlimit_msgqueue, RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE");
416 #endif
417 #ifdef RLIMIT_NICE
418     set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE");
419 #endif
420 #ifdef RLIMIT_RTPRIO
421     set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO");
422 #endif
423 #ifdef RLIMIT_RTTIME
424     set_one_rlimit(&conf->rlimit_rttime, RLIMIT_RTTIME, "RLIMIT_RTTIME");
425 #endif
426 }
427 #endif
428 
check_configured_address(void)429 static char *check_configured_address(void) {
430     char *default_server = NULL;
431     pa_client_conf *c = pa_client_conf_new();
432 
433     pa_client_conf_load(c, true, true);
434 
435     if (c->default_server && *c->default_server)
436         default_server = pa_xstrdup(c->default_server);
437 
438     pa_client_conf_free(c);
439 
440     return default_server;
441 }
442 
443 #ifdef HAVE_DBUS
register_dbus_name(pa_core * c,DBusBusType bus,const char * name)444 static pa_dbus_connection *register_dbus_name(pa_core *c, DBusBusType bus, const char* name) {
445     DBusError error;
446     pa_dbus_connection *conn;
447 
448     dbus_error_init(&error);
449 
450     if (!(conn = pa_dbus_bus_get(c, bus, &error)) || dbus_error_is_set(&error)) {
451         pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);
452         goto fail;
453     }
454 
455     if (dbus_bus_request_name(pa_dbus_connection_get(conn), name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
456         pa_log_debug("Got %s!", name);
457         return conn;
458     }
459 
460     if (dbus_error_is_set(&error))
461         pa_log_error("Failed to acquire %s: %s: %s", name, error.name, error.message);
462     else
463         pa_log_error("D-Bus name %s already taken.", name);
464 
465     /* PA cannot be started twice by the same user and hence we can
466      * ignore mostly the case that a name is already taken. */
467 
468 fail:
469     if (conn)
470         pa_dbus_connection_unref(conn);
471 
472     dbus_error_free(&error);
473     return NULL;
474 }
475 #endif
476 
change_permission(const char * path,mode_t mode)477 void change_permission(const char *path, mode_t mode) {
478     if (!path) {
479         pa_log_error("chmod empty path");
480         return;
481     }
482 
483     if (chmod(path, mode)) {
484         pa_log_error("chmod failed for directory: %s", path);
485     }
486 }
487 
488 #ifdef OS_IS_WIN32
489 #define SVC_NAME "PulseAudio"
490 static bool is_svc = true;
491 static int argc;
492 static char **argv;
493 static int real_main(int s_argc, char *s_argv[]);
494 static SERVICE_STATUS_HANDLE svc_status;
495 
svc_callback(DWORD ctl,DWORD evt,LPVOID data,LPVOID userdata)496 DWORD svc_callback(DWORD ctl, DWORD evt, LPVOID data, LPVOID userdata) {
497     pa_mainloop **m = userdata;
498     switch (ctl) {
499     case SERVICE_CONTROL_STOP:
500     case SERVICE_CONTROL_SHUTDOWN:
501         if (m) {
502             pa_log_info("Exiting.");
503             pa_mainloop_get_api(*m)->quit(pa_mainloop_get_api(*m), 0);
504         }
505         return NO_ERROR;
506     case SERVICE_CONTROL_INTERROGATE:
507         return NO_ERROR;
508     }
509     return ERROR_CALL_NOT_IMPLEMENTED;
510 }
511 
ohos_pa_main(int argc,char * argv[])512 int ohos_pa_main(int argc, char *argv[]) {
513     argc = p_argc;
514     argv = p_argv;
515     if (StartServiceCtrlDispatcherA((SERVICE_TABLE_ENTRYA[]){
516         {SVC_NAME, (LPSERVICE_MAIN_FUNCTIONA) real_main},
517         {0},
518     })) return 0;
519     is_svc = false;
520     return real_main(0, NULL);
521 }
522 
real_main(int s_argc,char * s_argv[])523 static int real_main(int s_argc, char *s_argv[]) {
524 #else
525 int ohos_pa_main(int argc, char *argv[]) {
526 #endif
527     pa_core *c = NULL;
528     pa_strbuf *buf = NULL;
529     pa_daemon_conf *conf = NULL;
530     pa_mainloop *mainloop = NULL;
531     char *s;
532     char *configured_address;
533     int r = 0, retval = 1, d = 0;
534     bool valid_pid_file = false;
535 #ifdef HAVE_NO_OHOS
536     bool ltdl_init = false;
537 #endif
538     int n_fds = 0, *passed_fds = NULL;
539     const char *e;
540 #ifdef HAVE_FORK
541     int daemon_pipe[2] = { -1, -1 };
542     int daemon_pipe2[2] = { -1, -1 };
543 #endif
544     int autospawn_fd = -1;
545     bool autospawn_locked = false;
546 #ifdef HAVE_DBUS
547     pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */
548     pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */
549     pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
550     bool start_server;
551 #endif
552 
553 #ifdef OS_IS_WIN32
554     if (is_svc && !(svc_status = RegisterServiceCtrlHandlerExA(SVC_NAME, (LPHANDLER_FUNCTION_EX) svc_callback, &mainloop))) {
555         pa_log("Failed to register service control handler.");
556         goto finish;
557     }
558 
559     if (is_svc) {
560         SetServiceStatus(svc_status, &(SERVICE_STATUS){
561             .dwServiceType      = SERVICE_WIN32,
562             .dwCurrentState     = SERVICE_START_PENDING,
563             .dwControlsAccepted = 0,
564             .dwWin32ExitCode    = NO_ERROR,
565             .dwWaitHint         = 3000,
566         });
567     }
568 #endif
569 
570     pa_log_set_ident("pulseaudio");
571     pa_log_set_level(PA_LOG_NOTICE);
572     pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);
573 
574 #if !defined(HAVE_BIND_NOW) && defined(__linux__) && defined(__OPTIMIZE__)
575     /*
576        Disable lazy relocations to make usage of external libraries
577        more deterministic for our RT threads. We abuse __OPTIMIZE__ as
578        a check whether we are a debug build or not. This all is
579        admittedly a bit snake-oilish.
580     */
581 
582     if (!getenv("LD_BIND_NOW")) {
583         char *rp;
584         char *canonical_rp;
585 
586         /* We have to execute ourselves, because the libc caches the
587          * value of $LD_BIND_NOW on initialization. */
588 
589         pa_set_env("LD_BIND_NOW", "1");
590 
591         if ((canonical_rp = pa_realpath(PA_BINARY))) {
592 
593             if ((rp = pa_readlink("/proc/self/exe"))) {
594 
595                 if (pa_streq(rp, canonical_rp))
596                     pa_assert_se(execv(rp, argv) == 0);
597                 else
598                     pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
599 
600                 pa_xfree(rp);
601 
602             } else
603                 pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
604 
605             pa_xfree(canonical_rp);
606 
607         } else
608             pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
609     }
610 #endif
611 
612 #ifdef HAVE_SYSTEMD_DAEMON
613     n_fds = sd_listen_fds(0);
614     if (n_fds > 0) {
615         int i = n_fds;
616 
617         passed_fds = pa_xnew(int, n_fds+2);
618         passed_fds[n_fds] = passed_fds[n_fds+1] = -1;
619         while (i--)
620             passed_fds[i] = SD_LISTEN_FDS_START + i;
621     }
622 #endif
623 
624     if (!passed_fds) {
625         n_fds = 0;
626         passed_fds = pa_xnew(int, 2);
627         passed_fds[0] = passed_fds[1] = -1;
628     }
629 
630     if ((e = getenv("PULSE_PASSED_FD"))) {
631         int passed_fd = atoi(e);
632         if (passed_fd > 2)
633             passed_fds[n_fds] = passed_fd;
634     }
635 
636     /* We might be autospawned, in which case have no idea in which
637      * context we have been started. Let's cleanup our execution
638      * context as good as possible */
639 
640     pa_reset_personality();
641     pa_drop_root();
642 #ifdef HAVE_NO_OHOS
643     pa_close_allv(passed_fds);
644     pa_xfree(passed_fds);
645 #endif
646     pa_reset_priority();
647 
648     /* Load locale from the environment. */
649     setlocale(LC_ALL, "");
650 
651     /* Set LC_NUMERIC to C so that floating point strings are consistently
652      * formatted and parsed across locales. */
653     setlocale(LC_NUMERIC, "C");
654 
655     pa_init_i18n();
656 
657     conf = pa_daemon_conf_new();
658     if (!conf) {
659         pa_log(_("Failed to create daemon conf."));
660         goto finish;
661     }
662 
663     if (pa_daemon_conf_load(conf, NULL) < 0)
664         goto finish;
665 
666     if (pa_daemon_conf_env(conf) < 0)
667         goto finish;
668 
669     if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
670         pa_log(_("Failed to parse command line."));
671         goto finish;
672     }
673 
674     if (conf->log_target)
675         pa_log_set_target(conf->log_target);
676     else {
677         pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL };
678         pa_log_set_target(&target);
679     }
680 
681     pa_log_set_level(conf->log_level);
682     if (conf->log_meta)
683         pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
684     if (conf->log_time)
685         pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
686     pa_log_set_show_backtrace(conf->log_backtrace);
687 
688 #ifdef HAVE_DBUS
689     /* conf->system_instance and conf->local_server_type control almost the
690      * same thing; make them agree about what is requested. */
691     switch (conf->local_server_type) {
692         case PA_SERVER_TYPE_UNSET:
693             conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER;
694             break;
695         case PA_SERVER_TYPE_USER:
696         case PA_SERVER_TYPE_NONE:
697             conf->system_instance = false;
698             break;
699         case PA_SERVER_TYPE_SYSTEM:
700             conf->system_instance = true;
701             break;
702         default:
703             pa_assert_not_reached();
704     }
705 
706     start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);
707 
708     if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
709         pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
710         conf->system_instance = false;
711     }
712 #endif
713 
714 #ifdef HAVE_NO_OHOS
715     LTDL_SET_PRELOADED_SYMBOLS();
716     pa_ltdl_init();
717     ltdl_init = true;
718 
719     if (conf->dl_search_path)
720         lt_dlsetsearchpath(conf->dl_search_path);
721 #endif
722 
723 #ifdef OS_IS_WIN32
724     {
725         WSADATA data;
726         WSAStartup(MAKEWORD(2, 0), &data);
727     }
728 #endif
729 
730     pa_random_seed();
731 
732     switch (conf->cmd) {
733         case PA_CMD_DUMP_MODULES:
734 #ifdef HAVE_NO_OHOS
735             pa_dump_modules(conf, argc-d, argv+d);
736 #endif
737             retval = 0;
738             goto finish;
739 
740         case PA_CMD_DUMP_CONF: {
741 
742             if (d < argc) {
743                 pa_log("Too many arguments.");
744                 goto finish;
745             }
746 
747             s = pa_daemon_conf_dump(conf);
748             fputs(s, stdout);
749             pa_xfree(s);
750             retval = 0;
751             goto finish;
752         }
753 
754         case PA_CMD_DUMP_RESAMPLE_METHODS: {
755             int i;
756 
757             if (d < argc) {
758                 pa_log("Too many arguments.");
759                 goto finish;
760             }
761 
762             for (i = 0; i < PA_RESAMPLER_MAX; i++)
763                 if (pa_resample_method_supported(i))
764                     printf("%s\n", pa_resample_method_to_string(i));
765 
766             retval = 0;
767             goto finish;
768         }
769 
770         case PA_CMD_HELP :
771             pa_cmdline_help(argv[0]);
772             retval = 0;
773             goto finish;
774 
775         case PA_CMD_VERSION :
776 
777             if (d < argc) {
778                 pa_log("Too many arguments.");
779                 goto finish;
780             }
781 
782             printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
783             retval = 0;
784             goto finish;
785 
786         case PA_CMD_CHECK: {
787             pid_t pid;
788 
789             if (d < argc) {
790                 pa_log("Too many arguments.");
791                 goto finish;
792             }
793 
794             if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
795                 pa_log_info("Daemon not running");
796             else {
797                 pa_log_info("Daemon running as PID %u", pid);
798                 retval = 0;
799             }
800 
801             goto finish;
802 
803         }
804         case PA_CMD_KILL:
805 
806             if (d < argc) {
807                 pa_log("Too many arguments.");
808                 goto finish;
809             }
810 
811             if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
812                 pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
813             else
814                 retval = 0;
815 
816             goto finish;
817 
818         case PA_CMD_CLEANUP_SHM:
819 
820             if (d < argc) {
821                 pa_log("Too many arguments.");
822                 goto finish;
823             }
824 
825             if (pa_shm_cleanup() >= 0)
826                 retval = 0;
827 
828             goto finish;
829 
830         default:
831             pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
832     }
833 
834     if (d < argc) {
835         pa_log("Too many arguments.");
836         goto finish;
837     }
838 
839 #ifdef HAVE_GETUID
840     if (getuid() == 0 && !conf->system_instance)
841         pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
842 #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
843     else if (getuid() != 0 && conf->system_instance) {
844         pa_log(_("Root privileges required."));
845         goto finish;
846     }
847 #endif
848 #endif  /* HAVE_GETUID */
849 
850     if (conf->cmd == PA_CMD_START && conf->system_instance) {
851         pa_log(_("--start not supported for system instances."));
852         goto finish;
853     }
854 
855     if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) {
856         /* There is an server address in our config, but where did it come from?
857          * By default a standard X11 login will load module-x11-publish which will
858          * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end
859          * up hitting this code path. So we have to check to see if our configured_address
860          * is the same as the value that would go into this property so that we can
861          * recover (i.e. autospawn) from a crash.
862          */
863         char *ufn;
864         bool start_anyway = false;
865 
866         if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
867             char *id;
868 
869             if ((id = pa_machine_id())) {
870                 pa_strlist *server_list;
871                 char formatted_ufn[256];
872 
873                 pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn);
874                 pa_xfree(id);
875 
876                 if ((server_list = pa_strlist_parse(configured_address))) {
877                     char *u = NULL;
878 
879                     /* We only need to check the first server */
880                     server_list = pa_strlist_pop(server_list, &u);
881                     pa_strlist_free(server_list);
882 
883                     start_anyway = (u && pa_streq(formatted_ufn, u));
884                     pa_xfree(u);
885                 }
886             }
887             pa_xfree(ufn);
888         }
889 
890         if (!start_anyway) {
891             pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address);
892             pa_xfree(configured_address);
893             retval = 0;
894             goto finish;
895         }
896 
897         pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address);
898         pa_xfree(configured_address);
899     }
900 
901     if (conf->system_instance && !conf->disallow_exit)
902         pa_log_warn(_("Running in system mode, but --disallow-exit not set."));
903 
904     if (conf->system_instance && !conf->disallow_module_loading)
905         pa_log_warn(_("Running in system mode, but --disallow-module-loading not set."));
906 
907     if (conf->system_instance && !conf->disable_shm) {
908         pa_log_notice(_("Running in system mode, forcibly disabling SHM mode."));
909         conf->disable_shm = true;
910     }
911 
912     if (conf->system_instance && conf->exit_idle_time >= 0) {
913         pa_log_notice(_("Running in system mode, forcibly disabling exit idle time."));
914         conf->exit_idle_time = -1;
915     }
916 
917     if (conf->cmd == PA_CMD_START) {
918         /* If we shall start PA only when it is not running yet, we
919          * first take the autospawn lock to make things
920          * synchronous. */
921 
922         /* This locking and thread synchronisation code doesn't work reliably
923          * on kFreeBSD (Debian bug #705435), or in upstream FreeBSD ports
924          * (bug reference: ports/128947, patched in SVN r231972). */
925 #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
926         if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
927             pa_log("Failed to initialize autospawn lock");
928             goto finish;
929         }
930 
931         if ((pa_autospawn_lock_acquire(true) < 0)) {
932             pa_log("Failed to acquire autospawn lock");
933             goto finish;
934         }
935 
936         autospawn_locked = true;
937 #endif
938     }
939 
940     if (conf->daemonize) {
941 #ifdef HAVE_FORK
942         pid_t child;
943 #endif
944 
945         if (pa_stdio_acquire() < 0) {
946             pa_log(_("Failed to acquire stdio."));
947             goto finish;
948         }
949 
950 #ifdef HAVE_FORK
951         if (pipe(daemon_pipe) < 0) {
952             pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
953             goto finish;
954         }
955 
956         if ((child = fork()) < 0) {
957             pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
958             pa_close_pipe(daemon_pipe);
959             goto finish;
960         }
961 
962         if (child != 0) {
963             ssize_t n;
964             /* Father */
965 
966             pa_assert_se(pa_close(daemon_pipe[1]) == 0);
967             daemon_pipe[1] = -1;
968 
969             if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
970 
971                 if (n < 0)
972                     pa_log(_("read() failed: %s"), pa_cstrerror(errno));
973 
974                 retval = 1;
975             }
976 
977             if (retval)
978                 pa_log(_("Daemon startup failed."));
979             else
980                 pa_log_info("Daemon startup successful.");
981 
982             goto finish;
983         }
984 
985         if (autospawn_fd >= 0) {
986             /* The lock file is unlocked from the parent, so we need
987              * to close it in the child */
988 
989             pa_autospawn_lock_release();
990             pa_autospawn_lock_done(true);
991 
992             autospawn_locked = false;
993             autospawn_fd = -1;
994         }
995 
996         pa_assert_se(pa_close(daemon_pipe[0]) == 0);
997         daemon_pipe[0] = -1;
998 #endif
999 
1000         if (!conf->log_target) {
1001 #ifdef HAVE_SYSTEMD_JOURNAL
1002             pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL };
1003 #else
1004             pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
1005 #endif
1006             pa_log_set_target(&target);
1007         }
1008 
1009 #ifdef HAVE_SETSID
1010         if (setsid() < 0) {
1011             pa_log(_("setsid() failed: %s"), pa_cstrerror(errno));
1012             goto finish;
1013         }
1014 #endif
1015 
1016 #ifdef HAVE_FORK
1017         /* We now are a session and process group leader. Let's fork
1018          * again and let the father die, so that we'll become a
1019          * process that can never acquire a TTY again, in a session and
1020          * process group without leader */
1021 
1022         if (pipe(daemon_pipe2) < 0) {
1023             pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
1024             goto finish;
1025         }
1026 
1027         if ((child = fork()) < 0) {
1028             pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
1029             pa_close_pipe(daemon_pipe2);
1030             goto finish;
1031         }
1032 
1033         if (child != 0) {
1034             ssize_t n;
1035             /* Father */
1036 
1037             pa_assert_se(pa_close(daemon_pipe2[1]) == 0);
1038             daemon_pipe2[1] = -1;
1039 
1040             if ((n = pa_loop_read(daemon_pipe2[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
1041 
1042                 if (n < 0)
1043                     pa_log(_("read() failed: %s"), pa_cstrerror(errno));
1044 
1045                 retval = 1;
1046             }
1047 
1048             /* We now have to take care of signalling the first fork with
1049              * the return value we've received from this fork... */
1050             pa_assert(daemon_pipe[1] >= 0);
1051 
1052             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
1053             pa_close(daemon_pipe[1]);
1054             daemon_pipe[1] = -1;
1055 
1056             goto finish;
1057         }
1058 
1059         pa_assert_se(pa_close(daemon_pipe2[0]) == 0);
1060         daemon_pipe2[0] = -1;
1061 
1062         /* We no longer need the (first) daemon_pipe as it's handled in our child above */
1063         pa_close_pipe(daemon_pipe);
1064 #endif
1065 
1066 #ifdef SIGTTOU
1067         signal(SIGTTOU, SIG_IGN);
1068 #endif
1069 #ifdef SIGTTIN
1070         signal(SIGTTIN, SIG_IGN);
1071 #endif
1072 #ifdef SIGTSTP
1073         signal(SIGTSTP, SIG_IGN);
1074 #endif
1075 
1076         pa_nullify_stdfds();
1077     }
1078 
1079     pa_set_env_and_record("PULSE_INTERNAL", "1");
1080     pa_assert_se(chdir("/") == 0);
1081 #ifdef HAVE_NO_OHOS
1082     umask(0077);
1083 #endif
1084 #ifdef HAVE_SYS_RESOURCE_H
1085     set_all_rlimits(conf);
1086 #endif
1087     pa_rtclock_hrtimer_enable();
1088 
1089 #ifdef HAVE_NO_OHOS
1090     if (conf->high_priority)
1091         pa_raise_priority(conf->nice_level);
1092 #endif
1093     if (conf->system_instance)
1094         if (change_user() < 0)
1095             goto finish;
1096 
1097     pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
1098 
1099     pa_log_info("This is PulseAudio %s", PACKAGE_VERSION);
1100     pa_log_debug("Compilation CFLAGS: %s", PA_CFLAGS);
1101 
1102 #ifdef HAVE_LIBSAMPLERATE
1103     pa_log_warn("Compiled with DEPRECATED libsamplerate support!");
1104 #endif
1105 
1106     s = pa_uname_string();
1107     pa_log_debug("Running on host: %s", s);
1108     pa_xfree(s);
1109 
1110     pa_log_debug("Found %u CPUs.", pa_ncpus());
1111 
1112     pa_log_info("Page size is %zu bytes", pa_page_size());
1113 
1114 #ifdef HAVE_VALGRIND_MEMCHECK_H
1115     pa_log_debug("Compiled with Valgrind support: yes");
1116 #else
1117     pa_log_debug("Compiled with Valgrind support: no");
1118 #endif
1119 
1120     pa_log_debug("Running in valgrind mode: %s", pa_yes_no(pa_in_valgrind()));
1121 
1122     pa_log_debug("Running in VM: %s", pa_yes_no(pa_running_in_vm()));
1123 
1124 #ifdef HAVE_RUNNING_FROM_BUILD_TREE
1125     pa_log_debug("Running from build tree: %s", pa_yes_no(pa_run_from_build_tree()));
1126 #else
1127     pa_log_debug("Running from build tree: no");
1128 #endif
1129 
1130 #ifdef __OPTIMIZE__
1131     pa_log_debug("Optimized build: yes");
1132 #else
1133     pa_log_debug("Optimized build: no");
1134 #endif
1135 
1136 #ifdef NDEBUG
1137     pa_log_debug("NDEBUG defined, all asserts disabled.");
1138 #elif defined(FASTPATH)
1139     pa_log_debug("FASTPATH defined, only fast path asserts disabled.");
1140 #else
1141     pa_log_debug("All asserts enabled.");
1142 #endif
1143 
1144     if (!(s = pa_machine_id())) {
1145         pa_log(_("Failed to get machine ID"));
1146         goto finish;
1147     }
1148     pa_log_info("Machine ID is %s.", s);
1149     pa_xfree(s);
1150 
1151     if ((s = pa_session_id())) {
1152         pa_log_info("Session ID is %s.", s);
1153         pa_xfree(s);
1154     }
1155 
1156     if (!(s = pa_get_runtime_dir()))
1157         goto finish;
1158     pa_log_info("Using runtime directory %s.", s);
1159     pa_xfree(s);
1160 
1161     if (!(s = pa_get_state_dir()))
1162         goto finish;
1163     pa_log_info("Using state directory %s.", s);
1164     pa_xfree(s);
1165 
1166     pa_log_info("Using modules directory %s.", conf->dl_search_path);
1167 
1168     pa_log_info("Running in system mode: %s", pa_yes_no(pa_in_system_mode()));
1169 
1170 #ifdef HAVE_NO_OHOS
1171     if (pa_in_system_mode())
1172         pa_log_warn(_("OK, so you are running PA in system mode. Please make sure that you actually do want to do that.\n"
1173                       "Please read http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ for an explanation why system mode is usually a bad idea."));
1174 #endif
1175     if (conf->use_pid_file) {
1176         int z;
1177         pa_pid_file_remove();
1178         if ((z = pa_pid_file_create("pulseaudio")) != 0) {
1179 
1180             if (conf->cmd == PA_CMD_START && z > 0) {
1181                 /* If we are already running and with are run in
1182                  * --start mode, then let's return this as success. */
1183 
1184                 retval = 0;
1185                 goto finish;
1186             }
1187 
1188             pa_log(_("pa_pid_file_create() failed."));
1189             goto finish;
1190         }
1191 
1192         valid_pid_file = true;
1193     }
1194 
1195     pa_disable_sigpipe();
1196 
1197     if (pa_rtclock_hrtimer())
1198         pa_log_info("System supports high resolution timers");
1199     else
1200         pa_log_info("System appears to not support high resolution timers");
1201 
1202     if (conf->lock_memory) {
1203 #if defined(HAVE_SYS_MMAN_H) && !defined(__ANDROID__)
1204         if (mlockall(MCL_FUTURE) < 0)
1205             pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
1206         else
1207             pa_log_info("Successfully locked process into memory.");
1208 #else
1209         pa_log_warn("Memory locking requested but not supported on platform.");
1210 #endif
1211     }
1212 
1213     pa_memtrap_install();
1214 
1215     pa_assert_se(mainloop = pa_mainloop_new());
1216 
1217     if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm,
1218                           !conf->disable_shm && !conf->disable_memfd && pa_memfd_is_locally_supported(),
1219                           conf->shm_size))) {
1220         pa_log(_("pa_core_new() failed."));
1221         goto finish;
1222     }
1223 
1224     c->default_sample_spec = conf->default_sample_spec;
1225     c->alternate_sample_rate = conf->alternate_sample_rate;
1226     c->default_channel_map = conf->default_channel_map;
1227     c->default_n_fragments = conf->default_n_fragments;
1228     c->default_fragment_size_msec = conf->default_fragment_size_msec;
1229     c->deferred_volume_safety_margin_usec = conf->deferred_volume_safety_margin_usec;
1230     c->deferred_volume_extra_delay_usec = conf->deferred_volume_extra_delay_usec;
1231     c->lfe_crossover_freq = conf->lfe_crossover_freq;
1232     c->exit_idle_time = conf->exit_idle_time;
1233     c->scache_idle_time = conf->scache_idle_time;
1234     c->resample_method = conf->resample_method;
1235     c->realtime_priority = conf->realtime_priority;
1236     c->realtime_scheduling = conf->realtime_scheduling;
1237     c->avoid_resampling = conf->avoid_resampling;
1238     c->disable_remixing = conf->disable_remixing;
1239     c->remixing_use_all_sink_channels = conf->remixing_use_all_sink_channels;
1240     c->remixing_produce_lfe = conf->remixing_produce_lfe;
1241     c->remixing_consume_lfe = conf->remixing_consume_lfe;
1242     c->deferred_volume = conf->deferred_volume;
1243     c->running_as_daemon = conf->daemonize;
1244     c->disallow_exit = conf->disallow_exit;
1245     c->flat_volumes = conf->flat_volumes;
1246     c->rescue_streams = conf->rescue_streams;
1247 #ifdef HAVE_DBUS
1248     c->server_type = conf->local_server_type;
1249 #endif
1250 
1251     pa_core_check_idle(c);
1252 
1253     c->state = PA_CORE_RUNNING;
1254 #ifdef HAVE_CPU_INFO
1255     pa_cpu_init(&c->cpu_info);
1256 #endif
1257     pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
1258     pa_signal_new(SIGINT, signal_callback, c);
1259     pa_signal_new(SIGTERM, signal_callback, c);
1260 #ifdef SIGUSR1
1261     pa_signal_new(SIGUSR1, signal_callback, c);
1262 #endif
1263 #ifdef SIGUSR2
1264     pa_signal_new(SIGUSR2, signal_callback, c);
1265 #endif
1266 #ifdef SIGHUP
1267     pa_signal_new(SIGHUP, signal_callback, c);
1268 #endif
1269 
1270     if (!conf->no_cpu_limit)
1271         pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
1272 
1273     buf = pa_strbuf_new();
1274 
1275 #ifdef HAVE_DBUS
1276     pa_assert_se(dbus_threads_init_default());
1277 
1278     if (start_server)
1279 #endif
1280     {
1281         const char *command_source = NULL;
1282 
1283         if (conf->load_default_script_file) {
1284             FILE *f;
1285 
1286             if ((f = pa_daemon_conf_open_default_script_file(conf))) {
1287                 r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
1288                 fclose(f);
1289                 command_source = pa_daemon_conf_get_default_script_file(conf);
1290             }
1291         }
1292 
1293         if (r >= 0) {
1294             r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
1295             command_source = _("command line arguments");
1296         }
1297 
1298         pa_log_error("%s", s = pa_strbuf_to_string_free(buf));
1299         pa_xfree(s);
1300 
1301         if (r < 0 && conf->fail) {
1302             pa_log(_("Failed to initialize daemon due to errors while executing startup commands. Source of commands: %s"), command_source);
1303             goto finish;
1304         }
1305 
1306         if (!c->modules || pa_idxset_size(c->modules) == 0) {
1307             pa_log(_("Daemon startup without any loaded modules, refusing to work."));
1308             goto finish;
1309         }
1310 #ifdef HAVE_DBUS
1311     } else {
1312         /* When we just provide the D-Bus server lookup service, we don't want
1313          * any modules to be loaded. We haven't loaded any so far, so one might
1314          * think there's no way to contact the server, but receiving certain
1315          * signals could still cause modules to load. */
1316         conf->disallow_module_loading = true;
1317 #endif
1318     }
1319 
1320     /* We completed the initial module loading, so let's disable it
1321      * from now on, if requested */
1322     c->disallow_module_loading = conf->disallow_module_loading;
1323 
1324 #ifdef HAVE_DBUS
1325     if (!conf->system_instance) {
1326         if ((server_lookup = pa_dbusobj_server_lookup_new(c))) {
1327             if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1")))
1328                 goto finish;
1329         }
1330     }
1331 
1332     if (start_server)
1333         server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server");
1334 #endif
1335 
1336 #ifdef HAVE_FORK
1337     if (daemon_pipe2[1] >= 0) {
1338         int ok = 0;
1339         pa_loop_write(daemon_pipe2[1], &ok, sizeof(ok), NULL);
1340         pa_close(daemon_pipe2[1]);
1341         daemon_pipe2[1] = -1;
1342     }
1343 #endif
1344     change_permission("/data/data/.pulse_dir", 0755);
1345     change_permission("/data/data/.pulse_dir/runtime", 0755);
1346     change_permission("/data/data/.pulse_dir/state", 0755);
1347     change_permission("/data/data/.pulse_dir/state/cookie", 0664);
1348     change_permission("/data/data/.pulse_dir/runtime/cli", 0660);
1349     change_permission("/data/data/.pulse_dir/runtime/native", 0666);
1350 
1351     pa_log_info("Daemon startup complete.");
1352 
1353 #ifdef HAVE_SYSTEMD_DAEMON
1354     sd_notify(0, "READY=1");
1355 #endif
1356 
1357 #ifdef OS_IS_WIN32
1358     if (is_svc) {
1359         SetServiceStatus(svc_status, &(SERVICE_STATUS){
1360             .dwServiceType      = SERVICE_WIN32,
1361             .dwCurrentState     = SERVICE_RUNNING,
1362             .dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN,
1363             .dwWin32ExitCode    = NO_ERROR,
1364             .dwWaitHint         = 0,
1365         });
1366     }
1367 #endif
1368 
1369     retval = 0;
1370     if (pa_mainloop_run(mainloop, &retval) < 0)
1371         goto finish;
1372 
1373     pa_log_info("Daemon shutdown initiated.");
1374 
1375 #ifdef HAVE_SYSTEMD_DAEMON
1376     sd_notify(0, "STOPPING=1");
1377 #endif
1378 
1379 #ifdef OS_IS_WIN32
1380     if (is_svc) {
1381         SetServiceStatus(svc_status, &(SERVICE_STATUS){
1382             .dwServiceType      = SERVICE_WIN32,
1383             .dwCurrentState     = SERVICE_STOP_PENDING,
1384             .dwControlsAccepted = 0,
1385             .dwWin32ExitCode    = NO_ERROR,
1386             .dwWaitHint         = 2000,
1387         });
1388     }
1389 #endif
1390 
1391 finish:
1392 #ifdef HAVE_DBUS
1393     if (server_bus)
1394         pa_dbus_connection_unref(server_bus);
1395     if (lookup_service_bus)
1396         pa_dbus_connection_unref(lookup_service_bus);
1397     if (server_lookup)
1398         pa_dbusobj_server_lookup_free(server_lookup);
1399 #endif
1400 
1401     if (autospawn_fd >= 0) {
1402         if (autospawn_locked)
1403             pa_autospawn_lock_release();
1404 
1405         pa_autospawn_lock_done(false);
1406     }
1407 
1408     if (c) {
1409         /* Ensure all the modules/samples are unloaded when the core is still ref'ed,
1410          * as unlink callback hooks in modules may need the core to be ref'ed */
1411         pa_module_unload_all(c);
1412         pa_scache_free_all(c);
1413 
1414         pa_core_unref(c);
1415         pa_log_info("Daemon terminated.");
1416     }
1417 
1418     if (!conf->no_cpu_limit)
1419         pa_cpu_limit_done();
1420 
1421     pa_signal_done();
1422 
1423 #ifdef HAVE_FORK
1424     /* If we have daemon_pipe[1] still open, this means we've failed after
1425      * the first fork, but before the second. Therefore just write to it. */
1426     if (daemon_pipe[1] >= 0)
1427         pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
1428     else if (daemon_pipe2[1] >= 0)
1429         pa_loop_write(daemon_pipe2[1], &retval, sizeof(retval), NULL);
1430 
1431     pa_close_pipe(daemon_pipe2);
1432     pa_close_pipe(daemon_pipe);
1433 #endif
1434 
1435     if (mainloop)
1436         pa_mainloop_free(mainloop);
1437 
1438     if (conf)
1439         pa_daemon_conf_free(conf);
1440 
1441     if (valid_pid_file)
1442         pa_pid_file_remove();
1443 
1444     /* This has no real purpose except making things valgrind-clean */
1445     pa_unset_env_recorded();
1446 
1447 #ifdef OS_IS_WIN32
1448     WSACleanup();
1449 #endif
1450 
1451 #ifdef HAVE_NO_OHOS
1452     if (ltdl_init)
1453         pa_ltdl_done();
1454 #endif
1455 
1456 #ifdef HAVE_DBUS
1457     dbus_shutdown();
1458 #endif
1459 
1460 #ifdef OS_IS_WIN32
1461     if (is_svc) {
1462         SetServiceStatus(svc_status, &(SERVICE_STATUS){
1463             .dwServiceType      = SERVICE_WIN32,
1464             .dwCurrentState     = SERVICE_STOPPED,
1465             .dwControlsAccepted = 0,
1466             .dwWin32ExitCode    = retval ? ERROR_PROCESS_ABORTED : NO_ERROR,
1467             .dwWaitHint         = 0,
1468         });
1469     }
1470 #endif
1471 
1472     return retval;
1473 }
1474 
1475 #ifdef __cplusplus
1476 #if __cplusplus
1477 }
1478 #endif
1479 #endif /* End of #ifdef __cplusplus */
1480