• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5 
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10 
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 
29 #include <pulsecore/module.h>
30 #include <pulsecore/iochannel.h>
31 #include <pulsecore/cli.h>
32 #include <pulsecore/sioman.h>
33 #include <pulsecore/log.h>
34 #include <pulsecore/modargs.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/core-util.h>
37 
38 PA_MODULE_AUTHOR("Lennart Poettering");
39 PA_MODULE_DESCRIPTION("Command line interface");
40 PA_MODULE_VERSION(PACKAGE_VERSION);
41 PA_MODULE_LOAD_ONCE(true);
42 PA_MODULE_USAGE("exit_on_eof=<exit daemon after EOF?>");
43 
44 static const char* const valid_modargs[] = {
45     "exit_on_eof",
46     NULL
47 };
48 
eof_and_unload_cb(pa_cli * c,void * userdata)49 static void eof_and_unload_cb(pa_cli*c, void *userdata) {
50     pa_module *m = userdata;
51 
52     pa_assert(c);
53     pa_assert(m);
54 
55     pa_module_unload_request(m, true);
56 }
57 
eof_and_exit_cb(pa_cli * c,void * userdata)58 static void eof_and_exit_cb(pa_cli*c, void *userdata) {
59     pa_module *m = userdata;
60 
61     pa_assert(c);
62     pa_assert(m);
63 
64     pa_core_exit(m->core, false, 0);
65 }
66 
pa__init(pa_module * m)67 int pa__init(pa_module*m) {
68     pa_iochannel *io;
69     pa_modargs *ma;
70     bool exit_on_eof = false;
71 #ifndef OS_IS_WIN32
72     int fd;
73 #endif
74 
75     pa_assert(m);
76 
77     if (m->core->running_as_daemon) {
78         pa_log_info("Running as daemon, refusing to load this module.");
79         return 0;
80     }
81 
82     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
83         pa_log("failed to parse module arguments.");
84         goto fail;
85     }
86 
87     if (pa_modargs_get_value_boolean(ma, "exit_on_eof", &exit_on_eof) < 0) {
88         pa_log("exit_on_eof= expects boolean argument.");
89         goto fail;
90     }
91 
92     if (pa_stdio_acquire() < 0) {
93         pa_log("STDIN/STDOUT already in use.");
94         goto fail;
95     }
96 
97     /* We try to open the controlling tty anew here. This has the
98      * benefit of giving us a new fd that doesn't share the O_NDELAY
99      * flag with fds 0, 1, or 2. Since pa_iochannel_xxx needs O_NDELAY
100      * on its fd using those fds directly could set O_NDELAY which
101      * fprintf() doesn't really like, resulting in truncated output
102      * of log messages, particularly because if stdout and stderr are
103      * dup'ed they share the same O_NDELAY, too. */
104 
105 #ifndef OS_IS_WIN32
106     if ((fd = pa_open_cloexec("/dev/tty", O_RDWR|O_NONBLOCK, 0)) >= 0) {
107         io = pa_iochannel_new(m->core->mainloop, fd, fd);
108         pa_log_debug("Managed to open /dev/tty.");
109     }
110     else
111 #endif
112     {
113         io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
114         pa_iochannel_set_noclose(io, true);
115         pa_log_debug("Failed to open /dev/tty, using stdin/stdout fds instead.");
116     }
117 
118     m->userdata = pa_cli_new(m->core, io, m);
119     pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
120 
121     pa_modargs_free(ma);
122 
123     return 0;
124 
125 fail:
126 
127     if (ma)
128         pa_modargs_free(ma);
129 
130     return -1;
131 }
132 
pa__done(pa_module * m)133 void pa__done(pa_module*m) {
134     pa_assert(m);
135 
136     if (m->userdata) {
137         pa_cli_free(m->userdata);
138         pa_stdio_release();
139     }
140 }
141