]> code.delx.au - pulseaudio/blob - src/utils/pacmd.c
use cloexec wrappers wherever applicable
[pulseaudio] / src / utils / pacmd.c
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, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27 #include <signal.h>
28 #include <sys/poll.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/un.h>
34 #include <locale.h>
35
36 #include <pulse/error.h>
37 #include <pulse/util.h>
38 #include <pulse/xmalloc.h>
39 #include <pulse/i18n.h>
40
41 #include <pulsecore/macro.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/pid.h>
45
46 int main(int argc, char*argv[]) {
47
48 enum {
49 WATCH_STDIN,
50 WATCH_STDOUT,
51 WATCH_SOCKET,
52 N_WATCH
53 };
54
55 pid_t pid ;
56 int fd = -1;
57 int ret = 1, i;
58 struct sockaddr_un sa;
59 char ibuf[PIPE_BUF], obuf[PIPE_BUF];
60 size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
61 char *cli;
62 pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed;
63 struct pollfd pollfd[N_WATCH];
64
65 setlocale(LC_ALL, "");
66 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
67
68 if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) {
69 pa_log(_("No PulseAudio daemon running, or not running as session daemon."));
70 goto fail;
71 }
72
73 if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
74 pa_log(_("socket(PF_UNIX, SOCK_STREAM, 0): %s"), strerror(errno));
75 goto fail;
76 }
77
78 pa_zero(sa);
79 sa.sun_family = AF_UNIX;
80
81 if (!(cli = pa_runtime_path("cli")))
82 goto fail;
83
84 pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path));
85 pa_xfree(cli);
86
87 for (i = 0; i < 5; i++) {
88 int r;
89
90 if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) {
91 pa_log(_("connect(): %s"), strerror(errno));
92 goto fail;
93 }
94
95 if (r >= 0)
96 break;
97
98 if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) {
99 pa_log(_("Failed to kill PulseAudio daemon."));
100 goto fail;
101 }
102
103 pa_msleep(300);
104 }
105
106 if (i >= 5) {
107 pa_log(_("Daemon not responding."));
108 goto fail;
109 }
110
111 ibuf_index = ibuf_length = obuf_index = obuf_length = 0;
112 ibuf_eof = obuf_eof = ibuf_closed = obuf_closed = FALSE;
113
114 if (argc > 1) {
115 for (i = 1; i < argc; i++) {
116 size_t k;
117
118 k = PA_MIN(sizeof(ibuf) - ibuf_length, strlen(argv[i]));
119 memcpy(ibuf + ibuf_length, argv[i], k);
120 ibuf_length += k;
121
122 if (ibuf_length < sizeof(ibuf)) {
123 ibuf[ibuf_length] = i < argc-1 ? ' ' : '\n';
124 ibuf_length++;
125 }
126 }
127
128 ibuf_eof = TRUE;
129 }
130
131 pa_zero(pollfd);
132
133 pollfd[WATCH_STDIN].fd = STDIN_FILENO;
134 pollfd[WATCH_STDOUT].fd = STDOUT_FILENO;
135 pollfd[WATCH_SOCKET].fd = fd;
136
137 for (;;) {
138 if (ibuf_eof &&
139 obuf_eof &&
140 ibuf_length <= 0 &&
141 obuf_length <= 0)
142 break;
143
144 pollfd[WATCH_STDIN].events = pollfd[WATCH_STDOUT].events = pollfd[WATCH_SOCKET].events = 0;
145
146 if (obuf_length > 0)
147 pollfd[WATCH_STDOUT].events |= POLLOUT;
148 else if (!obuf_eof)
149 pollfd[WATCH_SOCKET].events |= POLLIN;
150
151 if (ibuf_length > 0)
152 pollfd[WATCH_SOCKET].events |= POLLOUT;
153 else if (!ibuf_eof)
154 pollfd[WATCH_STDIN].events |= POLLIN;
155
156 if (poll(pollfd, N_WATCH, -1) < 0) {
157
158 if (errno == EINTR)
159 continue;
160
161 pa_log(_("poll(): %s"), strerror(errno));
162 goto fail;
163 }
164
165 if (pollfd[WATCH_STDIN].revents & POLLIN) {
166 ssize_t r;
167 pa_assert(!ibuf_length);
168
169 if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), NULL)) <= 0) {
170 if (r < 0) {
171 pa_log(_("read(): %s"), strerror(errno));
172 goto fail;
173 }
174
175 ibuf_eof = TRUE;
176 } else {
177 ibuf_length = (size_t) r;
178 ibuf_index = 0;
179 }
180 }
181
182 if (pollfd[WATCH_SOCKET].revents & POLLIN) {
183 ssize_t r;
184 pa_assert(!obuf_length);
185
186 if ((r = pa_read(fd, obuf, sizeof(obuf), NULL)) <= 0) {
187 if (r < 0) {
188 pa_log(_("read(): %s"), strerror(errno));
189 goto fail;
190 }
191
192 obuf_eof = TRUE;
193 } else {
194 obuf_length = (size_t) r;
195 obuf_index = 0;
196 }
197 }
198
199 if (pollfd[WATCH_STDOUT].revents & POLLHUP) {
200 obuf_eof = TRUE;
201 obuf_length = 0;
202 } else if (pollfd[WATCH_STDOUT].revents & POLLOUT) {
203 ssize_t r;
204 pa_assert(obuf_length);
205
206 if ((r = pa_write(STDOUT_FILENO, obuf + obuf_index, obuf_length, NULL)) < 0) {
207 pa_log(_("write(): %s"), strerror(errno));
208 goto fail;
209 }
210
211 obuf_length -= (size_t) r;
212 obuf_index += obuf_index;
213 }
214
215 if (pollfd[WATCH_SOCKET].revents & POLLHUP) {
216 ibuf_eof = TRUE;
217 ibuf_length = 0;
218 } if (pollfd[WATCH_SOCKET].revents & POLLOUT) {
219 ssize_t r;
220 pa_assert(ibuf_length);
221
222 if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, NULL)) < 0) {
223 pa_log(_("write(): %s"), strerror(errno));
224 goto fail;
225 }
226
227 ibuf_length -= (size_t) r;
228 ibuf_index += obuf_index;
229 }
230
231 if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
232 pa_close(STDIN_FILENO);
233 shutdown(fd, SHUT_WR);
234 ibuf_closed = TRUE;
235 }
236
237 if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
238 shutdown(fd, SHUT_RD);
239 pa_close(STDOUT_FILENO);
240 obuf_closed = TRUE;
241 }
242 }
243
244 ret = 0;
245
246 fail:
247 if (fd >= 0)
248 pa_close(fd);
249
250 return ret;
251 }