pacmd: don't enter busy loop when reading from stdin very early
[profile/ivi/pulseaudio.git] / 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/socket.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <sys/un.h>
33 #include <locale.h>
34
35 #include <pulse/error.h>
36 #include <pulse/util.h>
37 #include <pulse/xmalloc.h>
38 #include <pulse/i18n.h>
39
40 #include <pulsecore/poll.h>
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     pid_t pid ;
49     int fd = -1;
50     int ret = 1, i;
51     struct sockaddr_un sa;
52     char ibuf[PIPE_BUF], obuf[PIPE_BUF];
53     size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
54     char *cli;
55     pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed;
56     struct pollfd pollfd[3];
57     struct pollfd *watch_socket, *watch_stdin, *watch_stdout;
58
59     int stdin_type = 0, stdout_type = 0, fd_type = 0;
60
61     setlocale(LC_ALL, "");
62     bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
63
64     if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) {
65         pa_log(_("No PulseAudio daemon running, or not running as session daemon."));
66         goto fail;
67     }
68
69     if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
70         pa_log(_("socket(PF_UNIX, SOCK_STREAM, 0): %s"), strerror(errno));
71         goto fail;
72     }
73
74     pa_zero(sa);
75     sa.sun_family = AF_UNIX;
76
77     if (!(cli = pa_runtime_path("cli")))
78         goto fail;
79
80     pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path));
81     pa_xfree(cli);
82
83     for (i = 0; i < 5; i++) {
84         int r;
85
86         if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) {
87             pa_log(_("connect(): %s"), strerror(errno));
88             goto fail;
89         }
90
91         if (r >= 0)
92             break;
93
94         if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) {
95             pa_log(_("Failed to kill PulseAudio daemon."));
96             goto fail;
97         }
98
99         pa_msleep(300);
100     }
101
102     if (i >= 5) {
103         pa_log(_("Daemon not responding."));
104         goto fail;
105     }
106
107     ibuf_index = ibuf_length = obuf_index = obuf_length = 0;
108     ibuf_eof = obuf_eof = ibuf_closed = obuf_closed = FALSE;
109
110     if (argc > 1) {
111         for (i = 1; i < argc; i++) {
112             size_t k;
113
114             k = PA_MIN(sizeof(ibuf) - ibuf_length, strlen(argv[i]));
115             memcpy(ibuf + ibuf_length, argv[i], k);
116             ibuf_length += k;
117
118             if (ibuf_length < sizeof(ibuf)) {
119                 ibuf[ibuf_length] = i < argc-1 ? ' ' : '\n';
120                 ibuf_length++;
121             }
122         }
123
124         ibuf_eof = TRUE;
125     }
126
127     for (;;) {
128         struct pollfd *p;
129
130         if (ibuf_eof &&
131             obuf_eof &&
132             ibuf_length <= 0 &&
133             obuf_length <= 0)
134             break;
135
136         if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
137             shutdown(fd, SHUT_WR);
138             ibuf_closed = TRUE;
139         }
140
141         if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
142             shutdown(fd, SHUT_RD);
143             obuf_closed = TRUE;
144         }
145
146         pa_zero(pollfd);
147
148         p = pollfd;
149
150         if (ibuf_length > 0 || (!obuf_eof && obuf_length <= 0)) {
151             watch_socket = p++;
152             watch_socket->fd = fd;
153             watch_socket->events =
154                 (ibuf_length > 0 ? POLLOUT : 0) |
155                 (!obuf_eof && obuf_length <= 0 ? POLLIN : 0);
156         } else
157             watch_socket = NULL;
158
159         if (!ibuf_eof && ibuf_length <= 0) {
160             watch_stdin = p++;
161             watch_stdin->fd = STDIN_FILENO;
162             watch_stdin->events = POLLIN;
163         } else
164             watch_stdin = NULL;
165
166         if (obuf_length > 0) {
167             watch_stdout = p++;
168             watch_stdout->fd = STDOUT_FILENO;
169             watch_stdout->events = POLLOUT;
170         } else
171             watch_stdout = NULL;
172
173         if (pa_poll(pollfd, p-pollfd, -1) < 0) {
174
175             if (errno == EINTR)
176                 continue;
177
178             pa_log(_("poll(): %s"), strerror(errno));
179             goto fail;
180         }
181
182         if (watch_stdin) {
183             if (watch_stdin->revents & POLLIN) {
184                 ssize_t r;
185                 pa_assert(ibuf_length <= 0);
186
187                 if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), &stdin_type)) <= 0) {
188                     if (r < 0) {
189                         pa_log(_("read(): %s"), strerror(errno));
190                         goto fail;
191                     }
192
193                     ibuf_eof = TRUE;
194                 } else {
195                     ibuf_length = (size_t) r;
196                     ibuf_index = 0;
197                 }
198             } else if (watch_stdin->revents & POLLHUP)
199                 ibuf_eof = TRUE;
200         }
201
202         if (watch_socket) {
203             if (watch_socket->revents & POLLIN) {
204                 ssize_t r;
205                 pa_assert(obuf_length <= 0);
206
207                 if ((r = pa_read(fd, obuf, sizeof(obuf), &fd_type)) <= 0) {
208                     if (r < 0) {
209                         pa_log(_("read(): %s"), strerror(errno));
210                         goto fail;
211                     }
212
213                     obuf_eof = TRUE;
214                 } else {
215                     obuf_length = (size_t) r;
216                     obuf_index = 0;
217                 }
218             } else if (watch_socket->revents & POLLHUP)
219                 obuf_eof = TRUE;
220         }
221
222         if (watch_stdout) {
223             if (watch_stdout->revents & POLLHUP) {
224                 obuf_eof = TRUE;
225                 obuf_length = 0;
226             } else if (watch_stdout->revents & POLLOUT) {
227                 ssize_t r;
228                 pa_assert(obuf_length > 0);
229
230                 if ((r = pa_write(STDOUT_FILENO, obuf + obuf_index, obuf_length, &stdout_type)) < 0) {
231                     pa_log(_("write(): %s"), strerror(errno));
232                     goto fail;
233                 }
234
235                 obuf_length -= (size_t) r;
236                 obuf_index += obuf_index;
237             }
238         }
239
240         if (watch_socket) {
241             if (watch_socket->revents & POLLHUP) {
242                 ibuf_eof = TRUE;
243                 ibuf_length = 0;
244             } if (watch_socket->revents & POLLOUT) {
245                 ssize_t r;
246                 pa_assert(ibuf_length > 0);
247
248                 if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, &fd_type)) < 0) {
249                     pa_log(_("write(): %s"), strerror(errno));
250                     goto fail;
251                 }
252
253                 ibuf_length -= (size_t) r;
254                 ibuf_index += obuf_index;
255             }
256         }
257     }
258
259     ret = 0;
260
261 fail:
262     if (fd >= 0)
263         pa_close(fd);
264
265     return ret;
266 }